about summary refs log tree commit diff
path: root/boot/lower.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/lower.c')
-rw-r--r--boot/lower.c137
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);
 }