aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-29 20:06:57 +0200
committerBad Diode <bd@badd10de.dev>2024-06-29 20:06:57 +0200
commit5f8aa9ed2eef33ca2f3a6f19b56588290ea74d2f (patch)
treefb6614509bc28892bd7bc89ca0046e10366ed461
parentc9a2dab875784262069ecb17ba146e8b0619317a (diff)
downloadbdl-5f8aa9ed2eef33ca2f3a6f19b56588290ea74d2f.tar.gz
bdl-5f8aa9ed2eef33ca2f3a6f19b56588290ea74d2f.zip
Add if expressions without else
-rw-r--r--src/compiler.c67
-rw-r--r--tests/compilation.bad8
2 files changed, 45 insertions, 30 deletions
diff --git a/src/compiler.c b/src/compiler.c
index 5bddcb6..f46d00d 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -504,34 +504,49 @@ compile_if(Chunk *chunk, Node *node) {
504 } 504 }
505 } 505 }
506 506
507 // Jump to the end of the expression. 507 if (node->cond_else) {
508 sz jump_b = array_size(chunk->code); 508 // Jump to the end of the expression.
509 EMIT_OP(OP_JMPI, 0xff, 0, 0, node->cond_if, chunk); 509 sz jump_b = array_size(chunk->code);
510 510 EMIT_OP(OP_JMPI, 0xff, 0, 0, node->cond_else, chunk);
511 // Else expression. 511
512 CompResult else_expr = compile_expr(chunk, node->cond_else); 512 // Else expression.
513 if (has_value) { 513 CompResult else_expr = compile_expr(chunk, node->cond_else);
514 switch (else_expr.type) { 514 if (has_value) {
515 case COMP_CONST: { 515 switch (else_expr.type) {
516 EMIT_OP(OP_LD64K, reg_dst, else_expr.idx, 0, node->cond_if, 516 case COMP_CONST: {
517 chunk); 517 EMIT_OP(OP_LD64K, reg_dst, else_expr.idx, 0,
518 } break; 518 node->cond_else, chunk);
519 case COMP_REG: { 519 } break;
520 EMIT_OP(OP_MOV64, reg_dst, else_expr.idx, 0, node->cond_if, 520 case COMP_REG: {
521 chunk); 521 EMIT_OP(OP_MOV64, reg_dst, else_expr.idx, 0,
522 } break; 522 node->cond_else, chunk);
523 default: { 523 } break;
524 return (CompResult){.type = COMP_ERR}; 524 default: {
525 } break; 525 return (CompResult){.type = COMP_ERR};
526 } break;
527 }
528 }
529 sz end_expr = array_size(chunk->code);
530
531 // Backpatch jumps.
532 sz const_a = add_constant(chunk, jump_b + 1 - jump_a);
533 sz const_b = add_constant(chunk, end_expr - jump_b);
534 chunk->code[jump_a].a = const_a;
535 chunk->code[jump_b].dst = const_b;
536 } else {
537 sz end_expr = array_size(chunk->code);
538 if (has_value) {
539 sz const_a = add_constant(chunk, end_expr + 1 - jump_a);
540 chunk->code[jump_a].a = const_a;
541 sz zero = add_constant(chunk, 0);
542 sz end = add_constant(chunk, 2);
543 EMIT_OP(OP_JMPI, end, 0, 0, node, chunk);
544 EMIT_OP(OP_LD64K, reg_dst, zero, 0, node, chunk);
545 } else {
546 sz const_a = add_constant(chunk, end_expr - jump_a);
547 chunk->code[jump_a].a = const_a;
526 } 548 }
527 } 549 }
528 sz end_expr = array_size(chunk->code);
529
530 // Backpatch jumps.
531 sz const_a = add_constant(chunk, jump_b + 1 - jump_a);
532 sz const_b = add_constant(chunk, end_expr - jump_b);
533 chunk->code[jump_a].a = const_a;
534 chunk->code[jump_b].dst = const_b;
535 // TODO: does it has an else or not? Moreover, should we enforce on the 550 // TODO: does it has an else or not? Moreover, should we enforce on the
536 // semantic level that if the `if` expression returns a value we must add an 551 // semantic level that if the `if` expression returns a value we must add an
537 // else? 552 // else?
diff --git a/tests/compilation.bad b/tests/compilation.bad
index e0682a7..4b25a76 100644
--- a/tests/compilation.bad
+++ b/tests/compilation.bad
@@ -7,11 +7,11 @@
7 7
8; a + b + c 8; a + b + c
9 9
10; if true { 10if true {
11; 1 + 2 11 2
12; } 12}
13 13
14if false { 14if true {
15 1 + 2 15 1 + 2
16} else { 16} else {
17 3 + 4 17 3 + 4