diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/lower.c | 172 |
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; |
