From a03973653262fbbfed7ce42dfa39646d16bdc98f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 21 Jun 2024 00:25:55 +0100 Subject: while loops, comparisons, modulo, fizzbuzz --- com.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'com.c') diff --git a/com.c b/com.c index fef2dab..cfe4df5 100644 --- a/com.c +++ b/com.c @@ -83,17 +83,42 @@ static void compile_node(State *S, Chunk *ch, AstNode a) { // B: compile_node(S, ch, l.vals[1]); chunk_wbc(S, ch, OP_0BRANCH); - size_t ph1 = placeholder(S, ch); + size_t ph_a = placeholder(S, ch); compile_node(S, ch, l.vals[2]); chunk_wbc(S, ch, OP_SKIP); - size_t ph2 = placeholder(S, ch); - size_t dest1 = ch->bc.len; + size_t ph_b = placeholder(S, ch); + size_t dest_a = ch->bc.len; compile_node(S, ch, l.vals[3]); - size_t dest2 = ch->bc.len; + size_t dest_b = ch->bc.len; - patch(S, ch, ph1, dest1 - ph1 - 2); - patch(S, ch, ph2, dest2 - ph2 - 2); + patch(S, ch, ph_a, dest_a - ph_a - 2); + patch(S, ch, ph_b, dest_b - ph_b - 2); + } else if (0 == strcmp(name, "while")) { + CK(l.len >= 3, "while requires at least 2 arguments"); + // (while cond body ...) + // A: + // cond + // 0branch ->B + // body .... + // redo ->A + // B: + // nil (while loop always returns nil) + size_t dest_a = ch->bc.len; + compile_node(S, ch, l.vals[1]); + chunk_wbc(S, ch, OP_0BRANCH); + size_t ph_b = placeholder(S, ch); + for (int i = 2; i < l.len; i++) { + compile_node(S, ch, l.vals[i]); + chunk_wbc(S, ch, OP_DROP); + } + chunk_wbc(S, ch, OP_REDO); + size_t ph_a = placeholder(S, ch); + size_t dest_b = ch->bc.len; + chunk_wbc(S, ch, OP_NIL); + + patch(S, ch, ph_a, ph_a - dest_a + 2); + patch(S, ch, ph_b, dest_b - ph_b - 2); } else { @@ -106,6 +131,9 @@ static void compile_node(State *S, Chunk *ch, AstNode a) { OP('-', OP_SUB) OP('*', OP_MUL) OP('/', OP_DIV) + OP('=', OP_EQU) + OP('<', OP_CMP) + OP('%', OP_MOD) #undef OP default: printf("unkown op %s\n",l.vals[0].as.str); -- cgit v1.2.3