From 593bb7d44082872e56b762fed374ad414245f4c2 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 30 Jun 2024 08:59:50 +0200 Subject: Add while loop compilation --- src/compiler.c | 34 ++++++++++++++++++++++++++++++++++ tests/compilation.bad | 6 ++---- tests/fib.bad | 12 ++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/fib.bad diff --git a/src/compiler.c b/src/compiler.c index 0f9607e..ea9234a 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -558,9 +558,43 @@ compile_if(Chunk *chunk, Node *node) { return (CompResult){.type = COMP_NIL}; } +CompResult +compile_while(Chunk *chunk, Node *node) { + sz start = array_size(chunk->code); + CompResult cond = compile_expr(chunk, node->while_cond); + OpCode jmpop; + switch (cond.type) { + case COMP_CONST: { + jmpop = OP_JMPFI; + } break; + case COMP_REG: { + jmpop = OP_JMPF; + } break; + default: { + return (CompResult){.type = COMP_ERR}; + } break; + } + sz jump_a = array_size(chunk->code); + + // Jump to the `end of the loop` branch. + EMIT_OP(jmpop, cond.idx, 0xff, 0, node->while_cond, chunk); + + // Condition is true. + CompResult then_expr = compile_expr(chunk, node->while_expr); + sz end_expr = array_size(chunk->code); + sz loopback = add_constant(chunk, (start - end_expr)); + EMIT_OP(OP_JMPI, loopback, 0, 0, node, chunk); + sz const_a = add_constant(chunk, end_expr - jump_a + 1); + chunk->code[jump_a].a = const_a; + + // Return. + return (CompResult){.type = COMP_NIL}; +} + CompResult compile_expr(Chunk *chunk, Node *node) { switch (node->kind) { + case NODE_WHILE: return compile_while(chunk, node); case NODE_IF: return compile_if(chunk, node); // Logic. // case NODE_XOR: diff --git a/tests/compilation.bad b/tests/compilation.bad index afb2be0..187d4ae 100644 --- a/tests/compilation.bad +++ b/tests/compilation.bad @@ -18,10 +18,8 @@ ; } let a = 0 -if 1 != 1 { - set a = 1 -} else { - set a = 2 +while a < 10 { + set a = a + 1 } a diff --git a/tests/fib.bad b/tests/fib.bad new file mode 100644 index 0000000..8eec0b8 --- /dev/null +++ b/tests/fib.bad @@ -0,0 +1,12 @@ +let n = 90 +let a = 0 +let b = 1 +let i = 0 +while i < n { + let tmp = a + b + set a = b + set b = tmp + set i = i + 1 +} + +a -- cgit v1.2.1