diff options
| author | Mel <mel@rnrd.eu> | 2026-05-04 18:39:54 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2026-05-04 18:39:54 +0200 |
| commit | 06eff276ce3440df22674572a660e86fc21637d5 (patch) | |
| tree | 43b7821dcaf9bb9a2600ee7a684d82469069e77d /boot/lower.c | |
| parent | 8a69b17ff0ce5c132391124f3c89e03338dede19 (diff) | |
| download | catskill-06eff276ce3440df22674572a660e86fc21637d5.tar.zst catskill-06eff276ce3440df22674572a660e86fc21637d5.zip | |
Initial lowering pass 2 implementation, create shells for source expressions and statements
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/lower.c')
| -rw-r--r-- | boot/lower.c | 137 |
1 files changed, 112 insertions, 25 deletions
diff --git a/boot/lower.c b/boot/lower.c index 1218281..3820408 100644 --- a/boot/lower.c +++ b/boot/lower.c @@ -62,24 +62,24 @@ lower_emit_error_c(struct Unit* unit, struct Span span, const ascii* message) bool lower_type_lookup_by_name(struct Unit* unit, struct String name, Type_Id* out_id) { - FOR_EACH_ARRAY(struct Type_Name_To_Id, mapping, &unit->types.by_name, { - if (string_equals(mapping.name, name)) { - *out_id = mapping.id; + FOR_EACH_ARRAY (struct Type_Name_To_Id, mapping, &unit->types.by_name) { + if (string_equals(mapping->name, name)) { + *out_id = mapping->id; return true; } - }) + } return false; } bool lower_function_lookup_by_name(struct Unit* unit, struct String name, Function_Id* out_id) { - FOR_EACH_ARRAY(struct Function_Name_To_Id, mapping, &unit->functions.by_name, { - if (string_equals(mapping.name, name)) { - *out_id = mapping.id; + FOR_EACH_ARRAY (struct Function_Name_To_Id, mapping, &unit->functions.by_name) { + if (string_equals(mapping->name, name)) { + *out_id = mapping->id; return true; } - }) + } return false; } @@ -192,7 +192,8 @@ lower_synthesize_type_name(struct Lower_Context* ctx) const ascii* synthetic_type_name_template = "__cat_type_%lu"; ascii name_buf[64]; - snprintf(name_buf, sizeof name_buf, synthetic_type_name_template, ctx->synthetic_type_counter++); + snprintf( + name_buf, sizeof name_buf, synthetic_type_name_template, ctx->synthetic_type_counter++); return string_from_c_string(name_buf); } @@ -201,9 +202,9 @@ lower_synthesize_type_name(struct Lower_Context* ctx) Type_Id lower_synthesize_structural(struct Lower_Context* ctx, struct Tree_Type* tree_type, uint64 hash) { - FOR_EACH_ARRAY(struct Type_Hash_To_Id, mapping, &ctx->unit->types.by_hash, { - if (mapping.hash == hash) return mapping.id; - }) + FOR_EACH_ARRAY (struct Type_Hash_To_Id, mapping, &ctx->unit->types.by_hash) { + if (mapping->hash == hash) return mapping->id; + } Type_Id id = array_length(&ctx->unit->types.entries); struct String name = lower_synthesize_type_name(ctx); @@ -254,7 +255,7 @@ lower_synthesize_structural(struct Lower_Context* ctx, struct Tree_Type* tree_ty .type_id = inner.type_id, .mods = array_new(enum Type_Modifier, 4), }; - FOR_EACH_ARRAY(enum Type_Modifier, m, &inner.mods, { array_push(&data_ref.mods, &m); }) + 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); @@ -317,7 +318,8 @@ lower_synthesize_structural(struct Lower_Context* ctx, struct Tree_Type* tree_ty struct Tree_Function_Header* header = &tree_type->value.function.header; type->value.function.return_type = lower_intern_type_ref(ctx, header->return_type); - lower_add_dependency(type, type->value.function.return_type); // possibly hard dependency on return + // possibly hard dependency on return type + lower_add_dependency(type, type->value.function.return_type); type->value.function.params = array_new(struct Type_Ref, 16); bool variadic = false; @@ -664,6 +666,88 @@ lower_pass_1(struct Lower_Context* ctx, struct Tree* tree) lower_pass_1_fill_bodies(ctx, 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); + +// turns a source expression into the lowered form. +struct Expression* +lower_expression(struct Lower_Context* ctx, struct Tree_Expression* tree_expr) +{ + // TODO: implement all the expressions + switch (tree_expr->kind) { + case TREE_EXPRESSION_INTEGER_LITERAL: { + union Expression_Value v = { 0 }; + v.integer_literal.value = tree_expr->value.integer_literal.value; + return expression_new(EXPRESSION_INTEGER_LITERAL, v, tree_expr->span); + } + case TREE_EXPRESSION_FLOAT_LITERAL: { + union Expression_Value v = { 0 }; + v.float_literal.value = tree_expr->value.float_literal.value; + return expression_new(EXPRESSION_FLOAT_LITERAL, v, tree_expr->span); + } + case TREE_EXPRESSION_STRING_LITERAL: { + union Expression_Value v = { 0 }; + v.string_literal.value = tree_expr->value.string_literal.value; + return expression_new(EXPRESSION_STRING_LITERAL, v, tree_expr->span); + } + case TREE_EXPRESSION_BOOLEAN_LITERAL: { + union Expression_Value v = { 0 }; + v.bool_literal.value = tree_expr->value.bool_literal.value; + return expression_new(EXPRESSION_BOOLEAN_LITERAL, v, tree_expr->span); + } + case TREE_EXPRESSION_NAME: { + union Expression_Value v = { 0 }; + v.name.name = tree_expr->value.name.name; + return expression_new(EXPRESSION_NAME, v, tree_expr->span); + } + default: + lower_emit_error_c(ctx->unit, tree_expr->span, "unimplemented: this expression kind"); + return nil; + } +} + +// turns a source statement into the lowered form. +struct Statement* +lower_statement(struct Lower_Context* ctx, struct Tree_Statement* tree_stmt) +{ + // TODO: implement all the statements + switch (tree_stmt->kind) { + case TREE_STATEMENT_RETURN: { + union Statement_Value v = { 0 }; + if (tree_stmt->value.return_value.value) + v.return_value.value = lower_expression(ctx, tree_stmt->value.return_value.value); + return statement_new(STATEMENT_RETURN, v, tree_stmt->span); + } + default: + lower_emit_error_c(ctx->unit, tree_stmt->span, "unimplemented: this statement kind"); + return nil; + } +} + +// turns a source block of statements into the lowered form of a block. +struct Block* +lower_block(struct Lower_Context* ctx, struct Tree_Block* tree_block) +{ + struct Block* block = block_new(); + block->statements = array_new(struct Statement*, 16); + + FOR_EACH (struct Tree_Statement*, tree_stmt, tree_block->statements) { + struct Statement* stmt = lower_statement(ctx, tree_stmt); + if (stmt) array_push(&block->statements, &stmt); + } + return block; +} + +// lowering pass 2 +// walks every collected function's source body and produces a lowered statement block. +void +lower_pass_2(struct Lower_Context* ctx) +{ + FOR_EACH_ARRAY (struct Function*, fn, &ctx->unit->functions.entries) { + if ((*fn)->ast_body) (*fn)->body = lower_block(ctx, (*fn)->ast_body); + } +} + // return line number for the given byte position in the source. (1-based) uint lower_span_to_line(struct String source, struct Span span) @@ -745,10 +829,10 @@ lower_topological_sort_dependency_graph(struct Unit* unit, struct Source_File so for (uint i = 0; i < n; ++i) { struct Type* type = *array_at(struct Type*, &unit->types.entries, i); Type_Id me = (Type_Id)i; - FOR_EACH_ARRAY(Type_Id, dep, &type->depends_on, { - struct _Array* slot = array_at(struct _Array, &reverse_deps, dep); + FOR_EACH_ARRAY (Type_Id, dep, &type->depends_on) { + struct _Array* slot = array_at(struct _Array, &reverse_deps, *dep); _array_push(slot, &me); - }) + } } uint output_count = 0; @@ -767,10 +851,10 @@ lower_topological_sort_dependency_graph(struct Unit* unit, struct Source_File so *array_at(uint, &in_degree, chosen) = done_sentinel; struct _Array* dependents = array_at(struct _Array, &reverse_deps, chosen); - FOR_EACH_ARRAY(Type_Id, dependent, dependents, { - uint* d = array_at(uint, &in_degree, dependent); + FOR_EACH_ARRAY (Type_Id, dependent, dependents) { + uint* d = array_at(uint, &in_degree, *dependent); if (*d != done_sentinel) (*d)--; - }) + } } if (output_count == n) return; @@ -795,12 +879,12 @@ lower_topological_sort_dependency_graph(struct Unit* unit, struct Source_File so struct Type* type = *array_at(struct Type*, &unit->types.entries, current); Type_Id next = (Type_Id)-1; - FOR_EACH_ARRAY(Type_Id, dep, &type->depends_on, { - if (*array_at(uint, &in_degree, dep) != done_sentinel) { - next = dep; + FOR_EACH_ARRAY (Type_Id, dep, &type->depends_on) { + if (*array_at(uint, &in_degree, *dep) != done_sentinel) { + next = *dep; break; } - }) + } if (next == (Type_Id)-1) return; // not a real cycle uint chain_len = array_length(&chain); @@ -851,6 +935,9 @@ lower_tree(struct Tree* tree, struct Source_File source, struct Unit* unit) .synthetic_type_counter = 0, }; - if (tree) lower_pass_1(&ctx, tree); + if (tree) { + lower_pass_1(&ctx, tree); + lower_pass_2(&ctx); + } lower_topological_sort_dependency_graph(unit, source); } |
