very basic while loop

This commit is contained in:
r4 2021-12-21 15:02:53 +01:00
parent 61d5661b96
commit 10d436107c
3 changed files with 64 additions and 18 deletions

View File

@ -1,15 +1,4 @@
a := 0
{
a := 1
b := a
}
//a := 1
//b := 1 - 2 * 2 + 5
//c := a + b * 2 * b
//d := a + 4 * b * a
/*x := 1
x := 1
y := 1
i := 60
@ -17,6 +6,6 @@ while i {
z := x + y
y = x
x = z
print(z)
//print(z)
i = i - 1
}*/
}

6
ir.c
View File

@ -69,6 +69,7 @@ static void print_irparam(const IRParam *p) {
void print_ir(IRToks *v) {
for (size_t i = 0; i < v->len; i++) {
printf("%04zx ", i);
printf("%s", irinstr_str[v->toks[i].instr]);
switch (v->toks[i].instr) {
case IRSet:
@ -92,13 +93,12 @@ void print_ir(IRToks *v) {
}
break;
case IRJmp:
printf(" ");
printf(" %zu", v->toks[i].Jmp.iaddr);
printf(" %zx", v->toks[i].Jmp.iaddr);
break;
case IRJnz:
printf(" ");
print_irparam(&v->toks[i].CJmp.condition);
printf(" %zu", v->toks[i].CJmp.iaddr);
printf(" %zx", v->toks[i].CJmp.iaddr);
break;
default:
break;

59
parse.c
View File

@ -356,9 +356,66 @@ static void stmt(State *s, Scope *sc, TokListItem *t) {
if (t->next->tok.Op == OpRCurl)
break;
}
TRY(stmt(s, &inner_sc, t->next));
TRY_ELSE(stmt(s, &inner_sc, t->next), term_scope(&inner_sc));
}
term_scope(&inner_sc);
t = t->next;
} else if (t->tok.kind == TokWhile) {
/* How while is generally implemented in IR:
* 0: jmp to 3
* 1: some_code
* 2: some_code
* 3: some stuff evaluating condition xyz
* 4: jmp to 1 if condition xyz is met
* */
size_t jmp_instr_iaddr = s->ir->len;
irtoks_app(s->ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRJmp,
.Jmp = {
.iaddr = 0, /* unknown for now */
},
});
t = t->next;
/* find beginning of while loop body */
TokListItem *lcurl;
for (TokListItem *i = t;; i++) {
if (i == NULL) {
mark_err(&start->tok);
set_err("Expected '{' after 'while' loop condition");
return;
}
if (i->tok.kind == TokOp && i->tok.Op == OpLCurl) {
lcurl = i;
break;
}
}
/* write loop body to IR stream */
TRY(stmt(s, sc, lcurl));
/* finally we know where the jmp from the beginning has to jump to */
s->ir->toks[jmp_instr_iaddr].Jmp.iaddr = s->ir->len;
size_t addr = sc->mem_addr++;
TRY(expr(s, sc, t, true, true, addr));
irtoks_app(s->ir, (IRTok){
.ln = t->tok.ln,
.col = t->tok.col,
.instr = IRJnz,
.CJmp = {
.iaddr = jmp_instr_iaddr + 1,
.condition = {
.kind = IRParamAddr,
.Addr = addr,
},
},
});
}
toklist_del(s->toks, start, t);
}