aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-05-05 03:45:04 +0200
committerMel <mel@rnrd.eu>2026-05-05 03:45:04 +0200
commit285cc6b0eaf3800248219edbba0646ece6ae2f3a (patch)
tree30cc69fb881a42f1ac7f4048f77ab7160b0f70da
parent1dc6425a76bdfa53d088ba150f1287726a2e7370 (diff)
downloadcatskill-285cc6b0eaf3800248219edbba0646ece6ae2f3a.tar.zst
catskill-285cc6b0eaf3800248219edbba0646ece6ae2f3a.zip
Output transpiled function signatures and definitions
Signed-off-by: Mel <mel@rnrd.eu>
-rw-r--r--boot/transpile.c81
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, &param->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) {