change IR stream to linked list

This commit is contained in:
r4
2021-12-29 13:27:58 +01:00
parent 45feb3fe1d
commit 7773cc6c14
7 changed files with 159 additions and 119 deletions

81
parse.c
View File

@@ -32,12 +32,12 @@ static size_t get_ident_addr(const Scope *sc, const char *name, const Tok *errpo
static IRParam tok_to_irparam(Scope *sc, Tok *t);
static Scope make_scope(Scope *parent, bool with_idents);
static void term_scope(Scope *sc);
static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret);
static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr);
static IRParam expr_into_irparam(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret);
static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr);
static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
static void skip_newlns(TokList *toks, TokListItem *from);
static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t);
static void stmt(IRList *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t);
static void mark_err(const Tok *t) {
err_ln = t->ln;
@@ -132,7 +132,7 @@ static void term_scope(Scope *sc) {
* If ir_tok is not the expression's last instruction, ir_tok is written to
* out_ir and t is replaced by a pointer to the result's memory address.
* */
static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok ir_tok, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret) {
static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok ir_tok, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret) {
if (t == expr_start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM) {
/* ir_tok was the expression's last IR instruction. */
@@ -149,7 +149,7 @@ static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok
size_t dest_addr = expr_scope->mem_addr++;
set_irtok_dest_addr(&ir_tok, dest_addr);
irtoks_app(out_ir, ir_tok);
irlist_app(out_ir, ir_tok);
t->tok = (Tok){
.kind = TokIdent,
@@ -213,7 +213,7 @@ static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok
* l_op r_op
* both l_op and r_op are delimiters (their precedence is PREC_DELIM) => done
*/
static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) {
static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) {
TokListItem *start = t;
Scope sc = make_scope(parent_sc, false);
@@ -253,7 +253,7 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
if (r.kind == ExprRetLastInstr) {
size_t res_addr = sc.mem_addr++;
set_irtok_dest_addr(&r.LastInstr, res_addr);
irtoks_app(out_ir, r.LastInstr);
irlist_app(out_ir, r.LastInstr);
t->tok = (Tok){
.ln = t->tok.ln,
.col = t->tok.col,
@@ -532,12 +532,12 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
}
}
static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr) {
static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr) {
ExprRet r;
TRY(r = expr(out_ir, toks, funcs, parent_sc, t));
if (r.kind == ExprRetLastInstr) {
set_irtok_dest_addr(&r.LastInstr, addr);
irtoks_app(out_ir, r.LastInstr);
irlist_app(out_ir, r.LastInstr);
t->tok = (Tok){
.ln = t->tok.ln,
.col = t->tok.col,
@@ -550,7 +550,7 @@ static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *par
} else if (r.kind == ExprRetVal || r.kind == ExprRetIdent) {
IRParam res;
TRY(res = tok_to_irparam(parent_sc, &t->tok));
irtoks_app(out_ir, (IRTok){
irlist_app(out_ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRSet,
@@ -564,14 +564,14 @@ static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *par
ASSERT_UNREACHED();
}
static IRParam expr_into_irparam(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) {
static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) {
ExprRet r;
TRY_RET(r = expr(out_ir, toks, funcs, parent_sc, t), (IRParam){0});
if (r.kind == ExprRetLastInstr) {
Scope sc = make_scope(parent_sc, false);
size_t addr = sc.mem_addr++;
set_irtok_dest_addr(&r.LastInstr, addr);
irtoks_app(out_ir, r.LastInstr);
irlist_app(out_ir, r.LastInstr);
return (IRParam){
.kind = IRParamAddr,
.Addr = addr,
@@ -595,7 +595,7 @@ static void skip_newlns(TokList *toks, TokListItem *from) {
toklist_del(toks, from, curr->prev);
}
static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t) {
static void stmt(IRList *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t) {
TokListItem *start = t;
if (t->tok.kind == TokIdent && t->tok.Ident.kind == IdentName && (t->next->tok.kind == TokDeclare || t->next->tok.kind == TokAssign)) {
char *name = t->tok.Ident.Name;
@@ -643,8 +643,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
* */
/* add initial jmp instruction */
size_t jmp_instr_iaddr = out_ir->len;
irtoks_app(out_ir, (IRTok){
irlist_app(out_ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRJmp,
@@ -652,30 +651,32 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
.iaddr = 0, /* unknown for now */
},
});
IRItem *jmp_instr = out_ir->end;
size_t body_iaddr = out_ir->len;
/* parse condition */
IRToks cond_ir;
irtoks_init_short(&cond_ir);
IRList cond_ir;
irlist_init_short(&cond_ir);
IRParam cond;
TRY_ELSE(cond = expr_into_irparam(&cond_ir, toks, funcs, sc, t->next), irtoks_term(&cond_ir));
TRY_ELSE(cond = expr_into_irparam(&cond_ir, toks, funcs, sc, t->next), irlist_term(&cond_ir));
/* parse loop body */
skip_newlns(toks, t->next);
TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irtoks_term(&cond_ir));
TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irlist_term(&cond_ir));
/* finally we know where the jmp from the beginning has to jump to */
out_ir->toks[jmp_instr_iaddr].Jmp.iaddr = out_ir->len;
jmp_instr->tok.Jmp.iaddr = out_ir->len;
/* append condition IR to program IR, then terminate condition IR stream */
irtoks_eat_irtoks(out_ir, &cond_ir, out_ir->len-1);
irlist_eat_irlist(out_ir, &cond_ir);
/* add conditional jump */
irtoks_app(out_ir, (IRTok){
irlist_app(out_ir, (IRTok){
.ln = t->next->tok.ln,
.col = t->next->tok.col,
.instr = IRJnz,
.CJmp = {
.iaddr = jmp_instr_iaddr + 1,
.iaddr = body_iaddr,
.condition = cond,
},
});
@@ -695,8 +696,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
TRY(cond = expr_into_irparam(out_ir, toks, funcs, sc, t->next));
/* add conditional jmp instruction */
size_t if_cjmp_instr_iaddr = out_ir->len;
irtoks_app(out_ir, (IRTok){
irlist_app(out_ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRJnz,
@@ -705,12 +705,13 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
.condition = cond,
},
});
IRItem *if_cjmp_instr = out_ir->end;
/* parse if body */
skip_newlns(toks, t->next);
IRToks if_body;
irtoks_init_short(&if_body);
TRY_ELSE(stmt(&if_body, toks, funcs, sc, t->next), irtoks_term(&if_body));
IRList if_body;
irlist_init_short(&if_body);
TRY_ELSE(stmt(&if_body, toks, funcs, sc, t->next), irlist_term(&if_body));
skip_newlns(toks, t->next);
if (t->next->tok.kind == TokElse) {
@@ -718,12 +719,11 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
/* parse and add else body */
skip_newlns(toks, t->next);
TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irtoks_term(&if_body));
TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irlist_term(&if_body));
}
/* add jmp instruction to jump back to common code */
size_t else_jmp_instr_iaddr = out_ir->len;
irtoks_app(out_ir, (IRTok){
irlist_app(out_ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRJmp,
@@ -731,15 +731,16 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
.iaddr = 0, /* unknown for now */
},
});
IRItem *else_jmp_instr = out_ir->end;
/* set if condition jmp target */
out_ir->toks[if_cjmp_instr_iaddr].CJmp.iaddr = out_ir->len;
if_cjmp_instr->tok.CJmp.iaddr = out_ir->len;
/* add if body */
irtoks_eat_irtoks(out_ir, &if_body, out_ir->len-1);
irlist_eat_irlist(out_ir, &if_body);
/* set else jmp target */
out_ir->toks[else_jmp_instr_iaddr].CJmp.iaddr = out_ir->len;
else_jmp_instr->tok.CJmp.iaddr = out_ir->len;
} else {
/* assume expression */
TRY(expr_into_irparam(out_ir, toks, funcs, sc, t));
@@ -748,7 +749,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt
toklist_del(toks, start, t);
}
IRToks parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs) {
IRList parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs) {
bf = builtin_funcs;
Map funcs;
@@ -760,12 +761,12 @@ IRToks parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs)
err_ln = 0; err_col = 0;
set_err("Builtin function %s() declared more than once", builtin_funcs[i].name);
map_term(&funcs);
return (IRToks){0};
return (IRList){0};
}
}
IRToks ir;
irtoks_init_long(&ir);
IRList ir;
irlist_init_long(&ir);
Scope global_scope = make_scope(NULL, true);
for (;;) {
skip_newlns(toks, toks->begin);