diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/transpile.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/boot/transpile.c b/boot/transpile.c index a239b2b..384b7c1 100644 --- a/boot/transpile.c +++ b/boot/transpile.c @@ -262,6 +262,69 @@ struct Visit_Table transpile_definition_visit_functions = { .visit_type_function = walk_type_primitive, // no-op, already done in pass 1 }; +// the c-side name a function is emitted under. +// `main` becomes `catskill_main` so the runtime trailer can wrap it. +const ascii* +transpile_function_c_name(struct Function* function) +{ + if (function->is_main) return "catskill_main"; + return string_c_str(function->name); +} + +// emits c-side format of a function header. +// shared by the signature and body passes. +void +transpile_function_emit_signature(struct Visit* visit, struct Function* function) +{ + TRANSPILE_PREAMBLE + + VISIT(visit_type_ref, &function->return_type); + TRANSPILE_WRITE(" %s(", transpile_function_c_name(function)); + if (array_length(&function->params) == 0) { + TRANSPILE_WRITE("void"); + } else { + bool first = true; + FOR_EACH_ARRAY (struct Param, param, &function->params) { + if (!first) TRANSPILE_WRITE(", "); + VISIT(visit_type_ref, ¶m->type); + TRANSPILE_WRITE(" %s", string_c_str(param->name)); + first = false; + } + if (function->variadic) TRANSPILE_WRITE(", ..."); + } + TRANSPILE_WRITE(")"); +} + +void +transpile_visit_function_signature(struct Visit* visit, struct Function* function) +{ + TRANSPILE_PREAMBLE + transpile_function_emit_signature(visit, function); + TRANSPILE_WRITE(";\n"); +} + +void +transpile_visit_function_body(struct Visit* visit, struct Function* function) +{ + TRANSPILE_PREAMBLE + transpile_function_emit_signature(visit, function); + TRANSPILE_WRITE(" {\n}\n"); +} + +// transpilation pass 3 visit table +// emits forward declarations of functions +struct Visit_Table transpile_signature_visit_functions = { + .visit_type_ref = transpile_visit_type_ref, + .visit_function = transpile_visit_function_signature, +}; + +// transpilation pass 4 visit table +// emits full definitions of functions +struct Visit_Table transpile_body_visit_functions = { + .visit_type_ref = transpile_visit_type_ref, + .visit_function = transpile_visit_function_body, +}; + // walk a lowered translation unit and emit c source into the transpiler's output. // the order of the translation unit, and thus the final source output is fixed. // preamble, then imports, type forwards, type definitions in topological dependency @@ -273,6 +336,8 @@ transpile_unit(struct Transpiler* transpiler, struct Unit* unit) visit_table_fill_defaults(&transpile_forward_visit_functions); visit_table_fill_defaults(&transpile_definition_visit_functions); + visit_table_fill_defaults(&transpile_signature_visit_functions); + visit_table_fill_defaults(&transpile_body_visit_functions); struct Visit visit_value = { .user_data = transpiler }; struct Visit* visit = &visit_value; @@ -283,19 +348,31 @@ transpile_unit(struct Transpiler* transpiler, struct Unit* unit) TRANSPILE_WRITE("#include \"%.*s\"\n", (int)import->path.length, import->path.data); } - // trigger pass 1 walk + // pass 1: type forwards visit->table = &transpile_forward_visit_functions; FOR_EACH_ARRAY (struct Type*, type_slot, &unit->types.entries) { VISIT(visit_type, *type_slot); } - // trigger pass 2 walk + // pass 2: type definitions visit->table = &transpile_definition_visit_functions; FOR_EACH_ARRAY (Type_Id, ordered_id, &unit->type_emission_order) { struct Type* type = *array_at(struct Type*, &unit->types.entries, *ordered_id); VISIT(visit_type, type); } + // pass 3: function signatures + visit->table = &transpile_signature_visit_functions; + FOR_EACH_ARRAY (struct Function*, function_slot, &unit->functions.entries) { + VISIT(visit_function, *function_slot); + } + + // pass 4: function definitions + visit->table = &transpile_body_visit_functions; + FOR_EACH_ARRAY (struct Function*, function_slot, &unit->functions.entries) { + VISIT(visit_function, *function_slot); + } + bool main_takes_args = false; bool has_main = false; FOR_EACH_ARRAY (struct Function*, function_slot, &unit->functions.entries) { |
