aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-05-04 21:19:42 +0200
committerMel <mel@rnrd.eu>2026-05-04 21:19:42 +0200
commit59cf0e45d701bd7ec0bbdbf10f69ec7cec66051a (patch)
treea38eb53feb3b23e5f4bd2487e97fd41ff11728de /boot
parent8783c2c0a3465d380376ba346f6bea4525ddd379 (diff)
downloadcatskill-59cf0e45d701bd7ec0bbdbf10f69ec7cec66051a.tar.zst
catskill-59cf0e45d701bd7ec0bbdbf10f69ec7cec66051a.zip
Lower source if + while + endless statements
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
-rw-r--r--boot/lower.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/boot/lower.c b/boot/lower.c
index 4a831d9..9531483 100644
--- a/boot/lower.c
+++ b/boot/lower.c
@@ -882,7 +882,8 @@ lower_pop_scope(struct Lower_Context* ctx, enum Scope_Type expected)
struct Scope* top = array_at(struct Scope, &ctx->scope_stack, ctx->scope_stack.length - 1);
- check(top->type == expected, "scope type mismatch on pop: expected %d, got %d", (int)expected, (int)top->type);
+ check(top->type == expected, "scope type mismatch on pop: expected %d, got %d", (int)expected,
+ (int)top->type);
check(expected != SCOPE_TYPE_UNIT, "lowering pass tried popping top-level unit scope");
--ctx->scope_stack.length;
@@ -955,8 +956,7 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
union Statement_Value v = { 0 };
v.declaration.name = name;
v.declaration.type = type;
- if (decl->initializer)
- v.declaration.initializer = lower_expression(ctx, decl->initializer);
+ if (decl->initializer) v.declaration.initializer = lower_expression(ctx, decl->initializer);
return statement_new(STATEMENT_DECLARATION, v, tree_stmt->span);
}
@@ -996,6 +996,58 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
return statement_new(STATEMENT_BLOCK, v, tree_stmt->span);
}
+ case TREE_STATEMENT_CONDITIONAL: {
+ struct Tree_Statement_Value_Conditional* cond = &tree_stmt->value.conditional;
+ union Statement_Value v = { 0 };
+ v.conditional.branches = array_new(struct If_Branch, 8);
+
+ for (uint i = 0; i < cond->condition_count; ++i) {
+ struct If_Branch branch = {
+ .condition =
+ cond->conditions[i].when
+ ? lower_expression(ctx, cond->conditions[i].when)
+ : nil,
+ .body = lower_block(ctx, &cond->conditions[i].then),
+ };
+ array_push(&v.conditional.branches, &branch);
+ }
+
+ return statement_new(STATEMENT_CONDITIONAL, v, tree_stmt->span);
+ }
+ case TREE_STATEMENT_LOOP: {
+ struct Tree_Statement_Value_Loop* loop = &tree_stmt->value.loop;
+ union Statement_Value v = { 0 };
+
+ switch (loop->style) {
+ case TREE_STATEMENT_LOOP_STYLE_WHILE:
+ v.loop.condition = lower_expression(ctx, loop->condition);
+ v.loop.body = lower_block(ctx, &loop->body);
+
+ break;
+ case TREE_STATEMENT_LOOP_STYLE_ENDLESS: {
+ // synthesize a `true` literal
+ union Expression_Value tv = { 0 };
+ tv.bool_literal.value = true;
+ v.loop.condition = expression_new(EXPRESSION_BOOLEAN_LITERAL, tv, tree_stmt->span);
+ v.loop.body = lower_block(ctx, &loop->body);
+
+ break;
+ }
+ case TREE_STATEMENT_LOOP_STYLE_C:
+ case TREE_STATEMENT_LOOP_STYLE_FOR_EACH:
+ lower_emit_error_c(
+ ctx->unit, tree_stmt->span, "unimplemented: c-style and for-each loops");
+ return nil;
+ default:
+ lower_emit_error_c(ctx->unit, tree_stmt->span, "unknown loop style");
+ return nil;
+ }
+ return statement_new(STATEMENT_LOOP, v, tree_stmt->span);
+ }
+ case TREE_STATEMENT_BREAK:
+ return statement_new(STATEMENT_BREAK, (union Statement_Value){ 0 }, tree_stmt->span);
+ case TREE_STATEMENT_CONTINUE:
+ return statement_new(STATEMENT_CONTINUE, (union Statement_Value){ 0 }, tree_stmt->span);
default:
lower_emit_error_c(ctx->unit, tree_stmt->span, "unimplemented: this statement kind");
return nil;