diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler.c | 67 |
1 files changed, 41 insertions, 26 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? |