aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/ir.c239
-rw-r--r--boot/lower.c57
-rw-r--r--boot/transpile.c4
3 files changed, 250 insertions, 50 deletions
diff --git a/boot/ir.c b/boot/ir.c
index 54ee2b3..4bdfc6e 100644
--- a/boot/ir.c
+++ b/boot/ir.c
@@ -541,3 +541,242 @@ block_new(void)
*block = (struct Block){ 0 };
return block;
}
+
+struct Expression*
+ir_make_integer(int64 value, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.integer_literal.value = value;
+ return expression_new(EXPRESSION_INTEGER_LITERAL, v, span);
+}
+
+struct Expression*
+ir_make_float(float64 value, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.float_literal.value = value;
+ return expression_new(EXPRESSION_FLOAT_LITERAL, v, span);
+}
+
+struct Expression*
+ir_make_string(struct String value, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.string_literal.value = value;
+ return expression_new(EXPRESSION_STRING_LITERAL, v, span);
+}
+
+struct Expression*
+ir_make_bool(bool value, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.bool_literal.value = value;
+ return expression_new(EXPRESSION_BOOLEAN_LITERAL, v, span);
+}
+
+struct Expression*
+ir_make_name(struct String name, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.name.name = name;
+ return expression_new(EXPRESSION_NAME, v, span);
+}
+
+struct Expression*
+ir_make_unary(enum Unary_Operation op, struct Expression* operand, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.unary_operator.operation = op;
+ v.unary_operator.operand = operand;
+ return expression_new(EXPRESSION_UNARY_OPERATION, v, span);
+}
+
+struct Expression*
+ir_make_binary(
+ enum Binary_Operation op, struct Expression* left, struct Expression* right, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.binary_operator.operation = op;
+ v.binary_operator.left_operand = left;
+ v.binary_operator.right_operand = right;
+ return expression_new(EXPRESSION_BINARY_OPERATION, v, span);
+}
+
+struct Expression*
+ir_make_sizeof(struct Type_Ref target, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.sizeof_operator.target = target;
+ return expression_new(EXPRESSION_SIZEOF_OPERATION, v, span);
+}
+
+struct Expression*
+ir_make_call(struct Expression* subject, Array(struct Expression*) arguments, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.call.subject = subject;
+ v.call.arguments = arguments;
+ return expression_new(EXPRESSION_CALL, v, span);
+}
+
+struct Expression*
+ir_make_member(struct Expression* subject, struct String name, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.member.subject = subject;
+ v.member.name = name;
+ return expression_new(EXPRESSION_MEMBER, v, span);
+}
+
+struct Expression*
+ir_make_subscript(struct Expression* subject, struct Expression* index, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.subscript.subject = subject;
+ v.subscript.index = index;
+ return expression_new(EXPRESSION_SUBSCRIPT, v, span);
+}
+
+struct Expression*
+ir_make_cast(struct Type_Ref target, struct Expression* operand, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.cast.target = target;
+ v.cast.operand = operand;
+ return expression_new(EXPRESSION_CAST, v, span);
+}
+
+struct Expression*
+ir_make_construct(Type_Id type_id, Array(struct Construct_Field) fields, struct Span span)
+{
+ union Expression_Value v = { 0 };
+ v.construct.type_id = type_id;
+ v.construct.fields = fields;
+ return expression_new(EXPRESSION_CONSTRUCT, v, span);
+}
+
+// type-ref constructors.
+// `bare` is the no-modifier form; `pointer` wraps one `&` modifier; `with_mods`
+// takes a fully-formed mods array (caller owns it).
+
+struct Type_Ref
+type_ref_bare(Type_Id type_id)
+{
+ return (struct Type_Ref){
+ .type_id = type_id,
+ .mods = array_new(enum Type_Modifier, 4),
+ };
+}
+
+struct Type_Ref
+type_ref_pointer(Type_Id type_id)
+{
+ struct Type_Ref ref = type_ref_bare(type_id);
+ enum Type_Modifier mod = TYPE_MOD_REFERENCE;
+ array_push(&ref.mods, &mod);
+ return ref;
+}
+
+struct Type_Ref
+type_ref_with_mods(Type_Id type_id, Array(enum Type_Modifier) mods)
+{
+ return (struct Type_Ref){
+ .type_id = type_id,
+ .mods = mods,
+ };
+}
+
+// statement builder family.
+// same shape as the expression builders: wrap the union-init around
+// `statement_new` so call sites stay readable.
+
+struct Statement*
+ir_make_declaration(
+ struct String name, struct Type_Ref type, struct Expression* initializer, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.declaration.name = name;
+ v.declaration.type = type;
+ v.declaration.initializer = initializer;
+ return statement_new(STATEMENT_DECLARATION, v, span);
+}
+
+struct Statement*
+ir_make_assign(struct Expression* lhs, struct Expression* rhs, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.assign.lhs = lhs;
+ v.assign.rhs = rhs;
+ return statement_new(STATEMENT_ASSIGN, v, span);
+}
+
+struct Statement*
+ir_make_expression_statement(struct Expression* inner, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.expression.inner = inner;
+ return statement_new(STATEMENT_EXPRESSION, v, span);
+}
+
+struct Statement*
+ir_make_conditional(Array(struct If_Branch) branches, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.conditional.branches = branches;
+ return statement_new(STATEMENT_CONDITIONAL, v, span);
+}
+
+struct Statement*
+ir_make_loop(struct Expression* condition, struct Block* body, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.loop.condition = condition;
+ v.loop.body = body;
+ return statement_new(STATEMENT_LOOP, v, span);
+}
+
+struct Statement*
+ir_make_return(struct Expression* value, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.return_value.value = value;
+ return statement_new(STATEMENT_RETURN, v, span);
+}
+
+struct Statement*
+ir_make_break(struct Span span)
+{
+ union Statement_Value v = { 0 };
+ return statement_new(STATEMENT_BREAK, v, span);
+}
+
+struct Statement*
+ir_make_continue(struct Span span)
+{
+ union Statement_Value v = { 0 };
+ return statement_new(STATEMENT_CONTINUE, v, span);
+}
+
+struct Statement*
+ir_make_block_statement(struct Block* inner, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.block.inner = inner;
+ return statement_new(STATEMENT_BLOCK, v, span);
+}
+
+struct Statement*
+ir_make_label(struct String name, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.label.name = name;
+ return statement_new(STATEMENT_LABEL, v, span);
+}
+
+struct Statement*
+ir_make_goto(struct String target, struct Span span)
+{
+ union Statement_Value v = { 0 };
+ v.goto_target.target = target;
+ return statement_new(STATEMENT_GOTO, v, span);
+}
diff --git a/boot/lower.c b/boot/lower.c
index f3c04d3..fb2d29a 100644
--- a/boot/lower.c
+++ b/boot/lower.c
@@ -308,10 +308,7 @@ lower_synthesize_structural(struct Lower_Context* ctx, struct Tree_Type* tree_ty
type->value.structure.fields = array_new(struct Field, 4);
struct Type_Ref inner = lower_intern_type_ref(ctx, tree_type->value.array.element_type);
- struct Type_Ref data_ref = {
- .type_id = inner.type_id,
- .mods = array_new(enum Type_Modifier, 4),
- };
+ struct Type_Ref data_ref = type_ref_bare(inner.type_id);
FOR_EACH_ARRAY (enum Type_Modifier, m, &inner.mods) array_push(&data_ref.mods, m);
enum Type_Modifier ptr = TYPE_MOD_REFERENCE;
array_push(&data_ref.mods, &ptr);
@@ -403,10 +400,7 @@ lower_synthesize_structural(struct Lower_Context* ctx, struct Tree_Type* tree_ty
struct Type_Ref
lower_intern_type_ref(struct Lower_Context* ctx, struct Tree_Type* tree_type)
{
- struct Type_Ref ref = {
- .type_id = ctx->unit->types.primitive_void_id,
- .mods = array_new(enum Type_Modifier, 4),
- };
+ struct Type_Ref ref = type_ref_bare(ctx->unit->types.primitive_void_id);
if (!tree_type || tree_type->type == TREE_TYPE_NONE) return ref;
@@ -726,38 +720,6 @@ lower_pass_1(struct Lower_Context* ctx, struct Tree* tree)
struct Block* lower_block(struct Lower_Context* ctx, struct Tree_Block* tree_block);
struct Statement* lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt);
-// small helpers used when synthesizing nodes when de-sugaring source.
-
-struct Expression*
-lower_make_name_expression(struct String name, struct Span span)
-{
- union Expression_Value v = { 0 };
- v.name.name = name;
-
- return expression_new(EXPRESSION_NAME, v, span);
-}
-
-struct Expression*
-lower_make_integer_literal_expression(int64 value, struct Span span)
-{
- union Expression_Value v = { 0 };
- v.integer_literal.value = value;
-
- return expression_new(EXPRESSION_INTEGER_LITERAL, v, span);
-}
-
-struct Expression*
-lower_make_binary_expression(
- enum Binary_Operation op, struct Expression* left, struct Expression* right, struct Span span)
-{
- union Expression_Value v = { 0 };
- v.binary_operator.operation = op;
- v.binary_operator.left_operand = left;
- v.binary_operator.right_operand = right;
-
- return expression_new(EXPRESSION_BINARY_OPERATION, v, span);
-}
-
// turns a source expression into the lowered form.
struct Expression*
lower_expression(struct Lower_Context* ctx, struct Tree_Expression* tree_expr)
@@ -911,7 +873,7 @@ lower_expression(struct Lower_Context* ctx, struct Tree_Expression* tree_expr)
fn->synthetic = true;
lower_fill_function_signature(ctx, fn, tree_expr);
- return lower_make_name_expression(name, tree_expr->span);
+ return ir_make_name(name, tree_expr->span);
}
case TREE_EXPRESSION_SUBSCRIPT:
case TREE_EXPRESSION_MEMBER:
@@ -1219,21 +1181,20 @@ lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt)
// we synthesize the right condition and step.
if (loop->style == TREE_STATEMENT_LOOP_STYLE_FOR_EACH) {
struct Tree_Expression* hi = decl->initializer->value.binary_operator.right_operand;
- struct Expression* lhs = lower_make_name_expression(name, tree_stmt->span);
+ 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 =
- lower_make_binary_expression(BINARY_LESS_THAN, lhs, rhs, tree_stmt->span);
+ ir_make_binary(BINARY_LESS_THAN, lhs, rhs, tree_stmt->span);
// step: x = x + 1
- struct Expression* iter_lhs = lower_make_name_expression(name, tree_stmt->span);
- struct Expression* iter_rhs_left =
- lower_make_name_expression(name, tree_stmt->span);
- struct Expression* one = lower_make_integer_literal_expression(1, tree_stmt->span);
+ 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 =
- lower_make_binary_expression(BINARY_PLUS, iter_rhs_left, one, tree_stmt->span);
+ 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;
diff --git a/boot/transpile.c b/boot/transpile.c
index 7264085..9d910b3 100644
--- a/boot/transpile.c
+++ b/boot/transpile.c
@@ -205,7 +205,7 @@ transpile_visit_type_definition_alias(struct Visit* visit, struct Type* type)
// aliases map to typedefs
// TODO: maybe aliases are too much sugar for the lowered representation,
// technically any reference to an alias could directly map to the underlying type.
- struct Type_Ref bare = { .type_id = type->value.alias.target_id, .mods = { 0 } };
+ struct Type_Ref bare = type_ref_bare(type->value.alias.target_id);
TRANSPILE_WRITE("typedef ");
VISIT(visit_type_ref, &bare);
TRANSPILE_WRITE(" %s;\n", string_c_str(type->name));
@@ -484,7 +484,7 @@ transpile_visit_expression_construct(struct Visit* visit, struct Expression* exp
{
TRANSPILE_PREAMBLE
- struct Type_Ref bare = { .type_id = expression->value.construct.type_id, .mods = { 0 } };
+ struct Type_Ref bare = type_ref_bare(expression->value.construct.type_id);
TRANSPILE_WRITE("(");
VISIT(visit_type_ref, &bare);
TRANSPILE_WRITE("){");