From 10d436107cce369a7351c8ffccb273a2965b36d9 Mon Sep 17 00:00:00 2001 From: r4 Date: Tue, 21 Dec 2021 15:02:53 +0100 Subject: [PATCH] very basic while loop --- example.script | 17 +++------------ ir.c | 6 ++--- parse.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/example.script b/example.script index 9465ac7..af78fb1 100644 --- a/example.script +++ b/example.script @@ -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 -}*/ +} diff --git a/ir.c b/ir.c index a6dc956..d7ef498 100644 --- a/ir.c +++ b/ir.c @@ -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; diff --git a/parse.c b/parse.c index 8cc8a1e..1f26259 100644 --- a/parse.c +++ b/parse.c @@ -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); }