aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-05-19 21:07:59 +0200
committerMel <mel@rnrd.eu>2026-05-19 21:07:59 +0200
commit0e4ce87b90b28cdf044a6a1dd8ce1690813faf92 (patch)
tree6d59fb35bd2599fe8b9294966a229c694eefe0f5 /boot
parent556aafa5eb681f5500169268d3cdea82a298c2af (diff)
downloadcatskill-0e4ce87b90b28cdf044a6a1dd8ce1690813faf92.tar.zst
catskill-0e4ce87b90b28cdf044a6a1dd8ce1690813faf92.zip
Simplify statement synthesis boilerplate
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
-rw-r--r--boot/lower.c172
1 files changed, 54 insertions, 118 deletions
diff --git a/boot/lower.c b/boot/lower.c
index fb2d29a..b2b2349 100644
--- a/boot/lower.c
+++ b/boot/lower.c
@@ -995,10 +995,9 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
struct Tree_Expression* rhs_tree = inner->value.binary_operator.right_operand;
if (op == BINARY_ASSIGN) {
- union Statement_Value v = { 0 };
- v.assign.lhs = lower_expression(ctx, lhs_tree);
- v.assign.rhs = lower_expression(ctx, rhs_tree);
- return statement_new(STATEMENT_ASSIGN, v, tree_stmt->span);
+ struct Expression* lhs = lower_expression(ctx, lhs_tree);
+ struct Expression* rhs = lower_expression(ctx, rhs_tree);
+ return ir_make_assign(lhs, rhs, tree_stmt->span);
}
if (op > BINARY_ASSIGN) {
// compound assigns always synthesize into a basic assignment
@@ -1019,18 +1018,10 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
return nil;
}
- union Expression_Value bin_v = { 0 };
- bin_v.binary_operator.operation = simple_op;
- bin_v.binary_operator.left_operand = lower_expression(ctx, lhs_tree);
- bin_v.binary_operator.right_operand = lower_expression(ctx, rhs_tree);
- struct Expression* binary =
- expression_new(EXPRESSION_BINARY_OPERATION, bin_v, inner->span);
-
- union Statement_Value v = { 0 };
- v.assign.lhs = lower_expression(ctx, lhs_tree);
- v.assign.rhs = binary;
-
- return statement_new(STATEMENT_ASSIGN, v, tree_stmt->span);
+ struct Expression* binary = ir_make_binary(
+ simple_op, lower_expression(ctx, lhs_tree), lower_expression(ctx, rhs_tree),
+ inner->span);
+ return ir_make_assign(lower_expression(ctx, lhs_tree), binary, tree_stmt->span);
}
}
if (inner && inner->kind == TREE_EXPRESSION_INCREMENT_DECREMENT) {
@@ -1048,28 +1039,13 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
enum Binary_Operation simple_op =
incdec->operation == INCREMENT_DECREMENT_INCREMENT ? BINARY_PLUS : BINARY_MINUS;
- union Expression_Value one_v = { 0 };
- one_v.integer_literal.value = 1;
- struct Expression* one = expression_new(EXPRESSION_INTEGER_LITERAL, one_v, inner->span);
-
- union Expression_Value bin_v = { 0 };
- bin_v.binary_operator.operation = simple_op;
- bin_v.binary_operator.left_operand = lower_expression(ctx, subject);
- bin_v.binary_operator.right_operand = one;
+ struct Expression* one = ir_make_integer(1, inner->span);
struct Expression* binary =
- expression_new(EXPRESSION_BINARY_OPERATION, bin_v, inner->span);
-
- union Statement_Value v = { 0 };
- v.assign.lhs = lower_expression(ctx, subject);
- v.assign.rhs = binary;
-
- return statement_new(STATEMENT_ASSIGN, v, tree_stmt->span);
+ ir_make_binary(simple_op, lower_expression(ctx, subject), one, inner->span);
+ return ir_make_assign(lower_expression(ctx, subject), binary, tree_stmt->span);
}
- union Statement_Value v = { 0 };
- v.expression.inner = lower_expression(ctx, inner);
-
- return statement_new(STATEMENT_EXPRESSION, v, tree_stmt->span);
+ return ir_make_expression_statement(lower_expression(ctx, inner), tree_stmt->span);
}
case TREE_STATEMENT_BLOCK: {
union Statement_Value v = { 0 };
@@ -1100,20 +1076,16 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
switch (loop->style) {
case TREE_STATEMENT_LOOP_STYLE_WHILE: {
- union Statement_Value v = { 0 };
- v.loop.condition = lower_expression(ctx, loop->condition);
- v.loop.body = lower_block(ctx, &loop->body);
- return statement_new(STATEMENT_LOOP, v, tree_stmt->span);
+ struct Expression* cond = lower_expression(ctx, loop->condition);
+ struct Block* body = lower_block(ctx, &loop->body);
+ return ir_make_loop(cond, body, tree_stmt->span);
}
case TREE_STATEMENT_LOOP_STYLE_ENDLESS: {
// synthesize a `true` literal so the ir always has a real
// condition to emit.
- union Expression_Value tv = { 0 };
- tv.bool_literal.value = true;
- union Statement_Value v = { 0 };
- v.loop.condition = expression_new(EXPRESSION_BOOLEAN_LITERAL, tv, tree_stmt->span);
- v.loop.body = lower_block(ctx, &loop->body);
- return statement_new(STATEMENT_LOOP, v, tree_stmt->span);
+ struct Expression* cond = ir_make_bool(true, tree_stmt->span);
+ struct Block* body = lower_block(ctx, &loop->body);
+ return ir_make_loop(cond, body, tree_stmt->span);
}
case TREE_STATEMENT_LOOP_STYLE_C:
case TREE_STATEMENT_LOOP_STYLE_FOR_EACH: {
@@ -1126,8 +1098,6 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
struct Tree_Expression* init = nil;
struct Tree_Expression* cond_tree = loop->condition;
struct Tree_Expression* iter_tree = loop->iteration;
- struct Tree_Expression* synth_cond = nil;
- struct Statement* synth_iter = nil;
if (loop->style == TREE_STATEMENT_LOOP_STYLE_FOR_EACH) {
if (!decl->initializer
@@ -1139,7 +1109,6 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
return nil;
}
init = decl->initializer->value.binary_operator.left_operand;
-
// condition and iteration step are synthesized below
} else {
init = decl->initializer;
@@ -1170,76 +1139,47 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
struct Type_Ref iter_type = lower_intern_type_ref(ctx, decl->type);
lower_declare_local(ctx, name, iter_type);
- // build the iteration variable
- union Statement_Value decl_v = { 0 };
- decl_v.declaration.name = name;
- decl_v.declaration.type = iter_type;
- decl_v.declaration.initializer = init ? lower_expression(ctx, init) : nil;
- struct Statement* decl_stmt = statement_new(STATEMENT_DECLARATION, decl_v, decl->span);
+ // build the iteration variable declaration
+ struct Statement* decl_stmt = ir_make_declaration(
+ name, iter_type, init ? lower_expression(ctx, init) : nil, decl->span);
- // for range for-each
- // we synthesize the right condition and step.
+ // condition and iteration step: for c-style we lower the source
+ // ones, for for-each over a range we synthesize `i < hi` and
+ // `i = i + 1`.
+ struct Expression* cond_expr = nil;
+ struct Statement* iter_stmt = nil;
if (loop->style == TREE_STATEMENT_LOOP_STYLE_FOR_EACH) {
struct Tree_Expression* hi = decl->initializer->value.binary_operator.right_operand;
- struct Expression* lhs = ir_make_name(name, tree_stmt->span);
- struct Expression* rhs = lower_expression(ctx, hi);
- synth_cond = nil; // unused; we go straight to the ir form
- (void)synth_cond;
-
- struct Expression* cond_expr =
- ir_make_binary(BINARY_LESS_THAN, lhs, rhs, tree_stmt->span);
-
- // step: x = x + 1
- struct Expression* iter_lhs = ir_make_name(name, tree_stmt->span);
- struct Expression* iter_rhs_left = ir_make_name(name, tree_stmt->span);
- struct Expression* one = ir_make_integer(1, tree_stmt->span);
- struct Expression* iter_rhs =
- ir_make_binary(BINARY_PLUS, iter_rhs_left, one, tree_stmt->span);
- union Statement_Value iter_v = { 0 };
- iter_v.assign.lhs = iter_lhs;
- iter_v.assign.rhs = iter_rhs;
- synth_iter = statement_new(STATEMENT_ASSIGN, iter_v, tree_stmt->span);
-
- // rest of the construction continues below
- struct Block* body = lower_block(ctx, &loop->body);
- if (synth_iter) array_push(&body->statements, &synth_iter);
-
- union Statement_Value while_v = { 0 };
- while_v.loop.condition = cond_expr;
- while_v.loop.body = body;
- struct Statement* while_stmt =
- statement_new(STATEMENT_LOOP, while_v, tree_stmt->span);
-
- struct Block* outer = block_new();
- outer->statements = array_new(struct Statement*, 4);
- array_push(&outer->statements, &decl_stmt);
- array_push(&outer->statements, &while_stmt);
-
- lower_pop_scope(ctx, SCOPE_TYPE_BLOCK);
-
- union Statement_Value v = { 0 };
- v.block.inner = outer;
-
- return statement_new(STATEMENT_BLOCK, v, tree_stmt->span);
+ // condition: i < hi
+ cond_expr = ir_make_binary(
+ BINARY_LESS_THAN, ir_make_name(name, tree_stmt->span),
+ lower_expression(ctx, hi), tree_stmt->span);
+ // step: i = i + 1
+ iter_stmt = ir_make_assign(
+ ir_make_name(name, tree_stmt->span),
+ ir_make_binary(
+ BINARY_PLUS, ir_make_name(name, tree_stmt->span),
+ ir_make_integer(1, tree_stmt->span), tree_stmt->span),
+ tree_stmt->span);
+ } else {
+ cond_expr = cond_tree ? lower_expression(ctx, cond_tree) : nil;
+ if (iter_tree) {
+ struct Tree_Statement iter_node = {
+ .kind = TREE_STATEMENT_EXPRESSION,
+ .value = { .expression = { .inner = iter_tree } },
+ .span = iter_tree->span,
+ };
+ iter_stmt = lower_statement(ctx, &iter_node);
+ }
}
- // c-style
- // no synthesis needed!
+ // assemble the body, appending the iteration step at the end so
+ // both for-styles share the same `{ decl; while { body; iter; } }`
+ // shape.
struct Block* body = lower_block(ctx, &loop->body);
- if (iter_tree) {
- struct Tree_Statement iter_node = {
- .kind = TREE_STATEMENT_EXPRESSION,
- .value = { .expression = { .inner = iter_tree } },
- .span = iter_tree->span,
- };
- struct Statement* iter_stmt = lower_statement(ctx, &iter_node);
- if (iter_stmt) array_push(&body->statements, &iter_stmt);
- }
+ if (iter_stmt) array_push(&body->statements, &iter_stmt);
- union Statement_Value while_v = { 0 };
- while_v.loop.condition = cond_tree ? lower_expression(ctx, cond_tree) : nil;
- while_v.loop.body = body;
- struct Statement* while_stmt = statement_new(STATEMENT_LOOP, while_v, tree_stmt->span);
+ struct Statement* while_stmt = ir_make_loop(cond_expr, body, tree_stmt->span);
struct Block* outer = block_new();
outer->statements = array_new(struct Statement*, 4);
@@ -1247,11 +1187,7 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
array_push(&outer->statements, &while_stmt);
lower_pop_scope(ctx, SCOPE_TYPE_BLOCK);
-
- union Statement_Value v = { 0 };
- v.block.inner = outer;
-
- return statement_new(STATEMENT_BLOCK, v, tree_stmt->span);
+ return ir_make_block_statement(outer, tree_stmt->span);
}
default:
lower_emit_error_c(ctx->unit, tree_stmt->span, "unknown loop style");
@@ -1259,9 +1195,9 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
}
}
case TREE_STATEMENT_BREAK:
- return statement_new(STATEMENT_BREAK, (union Statement_Value){ 0 }, tree_stmt->span);
+ return ir_make_break(tree_stmt->span);
case TREE_STATEMENT_CONTINUE:
- return statement_new(STATEMENT_CONTINUE, (union Statement_Value){ 0 }, tree_stmt->span);
+ return ir_make_continue(tree_stmt->span);
default:
lower_emit_error_c(ctx->unit, tree_stmt->span, "unimplemented: this statement kind");
return nil;