diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.h | 6 | ||||
| -rw-r--r-- | src/codegen/codegen_main.c | 902 |
2 files changed, 506 insertions, 402 deletions
diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index 4d13d65..4b66f99 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -16,11 +16,9 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out); // Utility functions (codegen_utils.c). char *infer_type(ParserContext *ctx, ASTNode *node); ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name); -char *get_field_type_str(ParserContext *ctx, const char *struct_name, - const char *field_name); +char *get_field_type_str(ParserContext *ctx, const char *struct_name, const char *field_name); char *extract_call_args(const char *args); -void emit_var_decl_type(ParserContext *ctx, FILE *out, const char *type_str, - const char *var_name); +void emit_var_decl_type(ParserContext *ctx, FILE *out, const char *type_str, const char *var_name); char *replace_string_type(const char *args); const char *parse_original_method_name(const char *mangled); void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out); diff --git a/src/codegen/codegen_main.c b/src/codegen/codegen_main.c index 3b0e4dc..3634af3 100644 --- a/src/codegen/codegen_main.c +++ b/src/codegen/codegen_main.c @@ -7,457 +7,563 @@ #include <string.h> // Helper: Check if a struct depends on another struct/enum by-value. -static int struct_depends_on(ASTNode *s1, const char *target_name) { - if (!s1) { - return 0; - } +static int struct_depends_on(ASTNode *s1, const char *target_name) +{ + if (!s1) + { + return 0; + } - // Only structs have dependencies that matter for ordering. - if (s1->type != NODE_STRUCT) { - return 0; - } - - ASTNode *field = s1->strct.fields; - while (field) { - if (field->type == NODE_FIELD && field->field.type) { - char *type_str = field->field.type; - // Skip pointers - they don't create ordering dependency. - if (strchr(type_str, '*')) { - field = field->next; - continue; - } + // Only structs have dependencies that matter for ordering. + if (s1->type != NODE_STRUCT) + { + return 0; + } - // Check if this field's type matches target (struct or enum). - if (strcmp(type_str, target_name) == 0) { - return 1; - } + ASTNode *field = s1->strct.fields; + while (field) + { + if (field->type == NODE_FIELD && field->field.type) + { + char *type_str = field->field.type; + // Skip pointers - they don't create ordering dependency. + if (strchr(type_str, '*')) + { + field = field->next; + continue; + } + + // Check if this field's type matches target (struct or enum). + if (strcmp(type_str, target_name) == 0) + { + return 1; + } + } + field = field->next; } - field = field->next; - } - return 0; + return 0; } // Topologically sort a list of struct/enum nodes. -static ASTNode *topo_sort_structs(ASTNode *head) { - if (!head) { - return NULL; - } - - // Count all nodes (structs + enums). - int count = 0; - ASTNode *n = head; - while (n) { - if (n->type == NODE_STRUCT || n->type == NODE_ENUM) { - count++; - } - n = n->next; - } - if (count == 0) { - return head; - } - - // Build array of all nodes. - ASTNode **nodes = malloc(count * sizeof(ASTNode *)); - int *emitted = calloc(count, sizeof(int)); - n = head; - int idx = 0; - while (n) { - if (n->type == NODE_STRUCT || n->type == NODE_ENUM) { - nodes[idx++] = n; +static ASTNode *topo_sort_structs(ASTNode *head) +{ + if (!head) + { + return NULL; } - n = n->next; - } - - // Build order array (indices in emission order). - int *order = malloc(count * sizeof(int)); - int order_idx = 0; - - int changed = 1; - int max_iterations = count * count; - int iterations = 0; - - while (changed && iterations < max_iterations) { - changed = 0; - iterations++; - - for (int i = 0; i < count; i++) { - if (emitted[i]) { - continue; - } - - // Enums have no dependencies, emit first. - if (nodes[i]->type == NODE_ENUM) { - order[order_idx++] = i; - emitted[i] = 1; - changed = 1; - continue; - } - - // For structs, check if all dependencies are emitted. - int can_emit = 1; - for (int j = 0; j < count; j++) { - if (i == j || emitted[j]) { - continue; - } - // Get the name of the potential dependency. - const char *dep_name = NULL; - if (nodes[j]->type == NODE_STRUCT) { - dep_name = nodes[j]->strct.name; - } else if (nodes[j]->type == NODE_ENUM) { - dep_name = nodes[j]->enm.name; + // Count all nodes (structs + enums). + int count = 0; + ASTNode *n = head; + while (n) + { + if (n->type == NODE_STRUCT || n->type == NODE_ENUM) + { + count++; } + n = n->next; + } + if (count == 0) + { + return head; + } - if (dep_name && struct_depends_on(nodes[i], dep_name)) { - can_emit = 0; - break; + // Build array of all nodes. + ASTNode **nodes = malloc(count * sizeof(ASTNode *)); + int *emitted = calloc(count, sizeof(int)); + n = head; + int idx = 0; + while (n) + { + if (n->type == NODE_STRUCT || n->type == NODE_ENUM) + { + nodes[idx++] = n; } - } - - if (can_emit) { - order[order_idx++] = i; - emitted[i] = 1; - changed = 1; - } + n = n->next; } - } - // Add any remaining nodes (cycles). - for (int i = 0; i < count; i++) { - if (!emitted[i]) { - order[order_idx++] = i; - } - } - - // Now build the linked list in the correct order. - ASTNode *result = NULL; - ASTNode *result_tail = NULL; - - for (int i = 0; i < order_idx; i++) { - ASTNode *node = nodes[order[i]]; - if (!result) { - result = node; - result_tail = node; - } else { - result_tail->next = node; - result_tail = node; - } - } - if (result_tail) { - result_tail->next = NULL; - } - - free(nodes); - free(emitted); - free(order); - return result; -} + // Build order array (indices in emission order). + int *order = malloc(count * sizeof(int)); + int order_idx = 0; -// Main entry point for code generation. -void codegen_node(ParserContext *ctx, ASTNode *node, FILE *out) { - if (node->type == NODE_ROOT) { - ASTNode *kids = node->root.children; - // Recursive Unwrap of Nested Roots (if accidentally wrapped multiple - // times). - while (kids && kids->type == NODE_ROOT) { - kids = kids->root.children; - } + int changed = 1; + int max_iterations = count * count; + int iterations = 0; - global_user_structs = kids; + while (changed && iterations < max_iterations) + { + changed = 0; + iterations++; - if (!ctx->skip_preamble) { - emit_preamble(ctx, out); - } - emit_includes_and_aliases(kids, out); - - // Emit Hoisted Code (from plugins) - if (ctx->hoist_out) { - long pos = ftell(ctx->hoist_out); - rewind(ctx->hoist_out); - char buf[4096]; - size_t n; - while ((n = fread(buf, 1, sizeof(buf), ctx->hoist_out)) > 0) { - fwrite(buf, 1, n, out); - } - fseek(ctx->hoist_out, pos, SEEK_SET); - } + for (int i = 0; i < count; i++) + { + if (emitted[i]) + { + continue; + } - ASTNode *merged = NULL; - ASTNode *merged_tail = NULL; - - ASTNode *s = ctx->instantiated_structs; - while (s) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *s; - copy->next = NULL; - if (!merged) { - merged = copy; - merged_tail = copy; - } else { - merged_tail->next = copy; - merged_tail = copy; - } - s = s->next; - } + // Enums have no dependencies, emit first. + if (nodes[i]->type == NODE_ENUM) + { + order[order_idx++] = i; + emitted[i] = 1; + changed = 1; + continue; + } - StructRef *sr = ctx->parsed_structs_list; - while (sr) { - if (sr->node) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *sr->node; - copy->next = NULL; - if (!merged) { - merged = copy; - merged_tail = copy; - } else { - merged_tail->next = copy; - merged_tail = copy; + // For structs, check if all dependencies are emitted. + int can_emit = 1; + for (int j = 0; j < count; j++) + { + if (i == j || emitted[j]) + { + continue; + } + + // Get the name of the potential dependency. + const char *dep_name = NULL; + if (nodes[j]->type == NODE_STRUCT) + { + dep_name = nodes[j]->strct.name; + } + else if (nodes[j]->type == NODE_ENUM) + { + dep_name = nodes[j]->enm.name; + } + + if (dep_name && struct_depends_on(nodes[i], dep_name)) + { + can_emit = 0; + break; + } + } + + if (can_emit) + { + order[order_idx++] = i; + emitted[i] = 1; + changed = 1; + } } - } - sr = sr->next; } - StructRef *er = ctx->parsed_enums_list; - while (er) { - if (er->node) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *er->node; - copy->next = NULL; - if (!merged) { - merged = copy; - merged_tail = copy; - } else { - merged_tail->next = copy; - merged_tail = copy; + // Add any remaining nodes (cycles). + for (int i = 0; i < count; i++) + { + if (!emitted[i]) + { + order[order_idx++] = i; } - } - er = er->next; } - ASTNode *k = kids; - while (k) { - if (k->type == NODE_STRUCT || k->type == NODE_ENUM) { - int found = 0; - ASTNode *chk = merged; - while (chk) { - if (chk->type == k->type) { - const char *n1 = - (k->type == NODE_STRUCT) ? k->strct.name : k->enm.name; - const char *n2 = - (chk->type == NODE_STRUCT) ? chk->strct.name : chk->enm.name; - if (n1 && n2 && strcmp(n1, n2) == 0) { - found = 1; - break; - } - } - chk = chk->next; + // Now build the linked list in the correct order. + ASTNode *result = NULL; + ASTNode *result_tail = NULL; + + for (int i = 0; i < order_idx; i++) + { + ASTNode *node = nodes[order[i]]; + if (!result) + { + result = node; + result_tail = node; } - - if (!found) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *k; - copy->next = NULL; - if (!merged) { - merged = copy; - merged_tail = copy; - } else { - merged_tail->next = copy; - merged_tail = copy; - } + else + { + result_tail->next = node; + result_tail = node; } - } - k = k->next; - } - - // Topologically sort. - ASTNode *sorted = topo_sort_structs(merged); - - print_type_defs(ctx, out, sorted); - emit_enum_protos(sorted, out); - - if (sorted) { - emit_struct_defs(ctx, sorted, out); } - emit_trait_defs(kids, out); - - ASTNode *raw_iter = kids; - while (raw_iter) { - if (raw_iter->type == NODE_RAW_STMT) { - fprintf(out, "%s\n", raw_iter->raw_stmt.content); - } - raw_iter = raw_iter->next; + if (result_tail) + { + result_tail->next = NULL; } - ASTNode *merged_globals = NULL; // Head + free(nodes); + free(emitted); + free(order); + return result; +} - if (ctx->parsed_globals_list) { - StructRef *s = ctx->parsed_globals_list; - while (s) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *s->node; - copy->next = merged_globals; - merged_globals = copy; +// Main entry point for code generation. +void codegen_node(ParserContext *ctx, ASTNode *node, FILE *out) +{ + if (node->type == NODE_ROOT) + { + ASTNode *kids = node->root.children; + // Recursive Unwrap of Nested Roots (if accidentally wrapped multiple + // times). + while (kids && kids->type == NODE_ROOT) + { + kids = kids->root.children; + } - s = s->next; - } - } + global_user_structs = kids; - emit_globals(ctx, merged_globals, out); - - ASTNode *merged_funcs = NULL; - ASTNode *merged_funcs_tail = NULL; - - if (ctx->instantiated_funcs) { - ASTNode *s = ctx->instantiated_funcs; - while (s) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *s; - copy->next = NULL; - if (!merged_funcs) { - merged_funcs = copy; - merged_funcs_tail = copy; - } else { - merged_funcs_tail->next = copy; - merged_funcs_tail = copy; + if (!ctx->skip_preamble) + { + emit_preamble(ctx, out); + } + emit_includes_and_aliases(kids, out); + + // Emit Hoisted Code (from plugins) + if (ctx->hoist_out) + { + long pos = ftell(ctx->hoist_out); + rewind(ctx->hoist_out); + char buf[4096]; + size_t n; + while ((n = fread(buf, 1, sizeof(buf), ctx->hoist_out)) > 0) + { + fwrite(buf, 1, n, out); + } + fseek(ctx->hoist_out, pos, SEEK_SET); } - s = s->next; - } - } - if (ctx->parsed_funcs_list) { - StructRef *s = ctx->parsed_funcs_list; - while (s) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *s->node; - copy->next = NULL; - if (!merged_funcs) { - merged_funcs = copy; - merged_funcs_tail = copy; - } else { - merged_funcs_tail->next = copy; - merged_funcs_tail = copy; + ASTNode *merged = NULL; + ASTNode *merged_tail = NULL; + + ASTNode *s = ctx->instantiated_structs; + while (s) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *s; + copy->next = NULL; + if (!merged) + { + merged = copy; + merged_tail = copy; + } + else + { + merged_tail->next = copy; + merged_tail = copy; + } + s = s->next; } - s = s->next; - } - } - if (ctx->parsed_impls_list) { - StructRef *s = ctx->parsed_impls_list; - while (s) { - ASTNode *copy = xmalloc(sizeof(ASTNode)); - *copy = *s->node; - copy->next = NULL; - if (!merged_funcs) { - merged_funcs = copy; - merged_funcs_tail = copy; - } else { - merged_funcs_tail->next = copy; - merged_funcs_tail = copy; + StructRef *sr = ctx->parsed_structs_list; + while (sr) + { + if (sr->node) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *sr->node; + copy->next = NULL; + if (!merged) + { + merged = copy; + merged_tail = copy; + } + else + { + merged_tail->next = copy; + merged_tail = copy; + } + } + sr = sr->next; } - s = s->next; - } - } - emit_protos(merged_funcs, out); + StructRef *er = ctx->parsed_enums_list; + while (er) + { + if (er->node) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *er->node; + copy->next = NULL; + if (!merged) + { + merged = copy; + merged_tail = copy; + } + else + { + merged_tail->next = copy; + merged_tail = copy; + } + } + er = er->next; + } - emit_impl_vtables(ctx, out); + ASTNode *k = kids; + while (k) + { + if (k->type == NODE_STRUCT || k->type == NODE_ENUM) + { + int found = 0; + ASTNode *chk = merged; + while (chk) + { + if (chk->type == k->type) + { + const char *n1 = (k->type == NODE_STRUCT) ? k->strct.name : k->enm.name; + const char *n2 = + (chk->type == NODE_STRUCT) ? chk->strct.name : chk->enm.name; + if (n1 && n2 && strcmp(n1, n2) == 0) + { + found = 1; + break; + } + } + chk = chk->next; + } + + if (!found) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *k; + copy->next = NULL; + if (!merged) + { + merged = copy; + merged_tail = copy; + } + else + { + merged_tail->next = copy; + merged_tail = copy; + } + } + } + k = k->next; + } - emit_lambda_defs(ctx, out); + // Topologically sort. + ASTNode *sorted = topo_sort_structs(merged); - emit_tests_and_runner(ctx, kids, out); + print_type_defs(ctx, out, sorted); + emit_enum_protos(sorted, out); - ASTNode *iter = merged_funcs; - while (iter) { - if (iter->type == NODE_IMPL) { - char *sname = iter->impl.struct_name; - if (!sname) { - iter = iter->next; - continue; + if (sorted) + { + emit_struct_defs(ctx, sorted, out); } - - char *mangled = replace_string_type(sname); - ASTNode *def = find_struct_def_codegen(ctx, mangled); - int skip = 0; - if (def) { - if (def->type == NODE_STRUCT && def->strct.is_template) { - skip = 1; - } else if (def->type == NODE_ENUM && def->enm.is_template) { - skip = 1; - } - } else { - char *lt = strchr(sname, '<'); - if (lt) { - int len = lt - sname; - char *buf = xmalloc(len + 1); - strncpy(buf, sname, len); - buf[len] = 0; - def = find_struct_def_codegen(ctx, buf); - if (def && def->strct.is_template) { - skip = 1; + emit_trait_defs(kids, out); + + ASTNode *raw_iter = kids; + while (raw_iter) + { + if (raw_iter->type == NODE_RAW_STMT) + { + fprintf(out, "%s\n", raw_iter->raw_stmt.content); } - free(buf); - } + raw_iter = raw_iter->next; } - if (mangled) { - free(mangled); - } - if (skip) { - iter = iter->next; - continue; + + ASTNode *merged_globals = NULL; // Head + + if (ctx->parsed_globals_list) + { + StructRef *s = ctx->parsed_globals_list; + while (s) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *s->node; + copy->next = merged_globals; + merged_globals = copy; + + s = s->next; + } } - } - if (iter->type == NODE_IMPL_TRAIT) { - char *sname = iter->impl_trait.target_type; - if (!sname) { - iter = iter->next; - continue; + + emit_globals(ctx, merged_globals, out); + + ASTNode *merged_funcs = NULL; + ASTNode *merged_funcs_tail = NULL; + + if (ctx->instantiated_funcs) + { + ASTNode *s = ctx->instantiated_funcs; + while (s) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *s; + copy->next = NULL; + if (!merged_funcs) + { + merged_funcs = copy; + merged_funcs_tail = copy; + } + else + { + merged_funcs_tail->next = copy; + merged_funcs_tail = copy; + } + s = s->next; + } } - char *mangled = replace_string_type(sname); - ASTNode *def = find_struct_def_codegen(ctx, mangled); - int skip = 0; - if (def) { - if (def->strct.is_template) { - skip = 1; - } - } else { - char *lt = strchr(sname, '<'); - if (lt) { - int len = lt - sname; - char *buf = xmalloc(len + 1); - strncpy(buf, sname, len); - buf[len] = 0; - def = find_struct_def_codegen(ctx, buf); - if (def && def->strct.is_template) { - skip = 1; + if (ctx->parsed_funcs_list) + { + StructRef *s = ctx->parsed_funcs_list; + while (s) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *s->node; + copy->next = NULL; + if (!merged_funcs) + { + merged_funcs = copy; + merged_funcs_tail = copy; + } + else + { + merged_funcs_tail->next = copy; + merged_funcs_tail = copy; + } + s = s->next; } - free(buf); - } } - if (mangled) { - free(mangled); + + if (ctx->parsed_impls_list) + { + StructRef *s = ctx->parsed_impls_list; + while (s) + { + ASTNode *copy = xmalloc(sizeof(ASTNode)); + *copy = *s->node; + copy->next = NULL; + if (!merged_funcs) + { + merged_funcs = copy; + merged_funcs_tail = copy; + } + else + { + merged_funcs_tail->next = copy; + merged_funcs_tail = copy; + } + s = s->next; + } } - if (skip) { - iter = iter->next; - continue; + + emit_protos(merged_funcs, out); + + emit_impl_vtables(ctx, out); + + emit_lambda_defs(ctx, out); + + emit_tests_and_runner(ctx, kids, out); + + ASTNode *iter = merged_funcs; + while (iter) + { + if (iter->type == NODE_IMPL) + { + char *sname = iter->impl.struct_name; + if (!sname) + { + iter = iter->next; + continue; + } + + char *mangled = replace_string_type(sname); + ASTNode *def = find_struct_def_codegen(ctx, mangled); + int skip = 0; + if (def) + { + if (def->type == NODE_STRUCT && def->strct.is_template) + { + skip = 1; + } + else if (def->type == NODE_ENUM && def->enm.is_template) + { + skip = 1; + } + } + else + { + char *lt = strchr(sname, '<'); + if (lt) + { + int len = lt - sname; + char *buf = xmalloc(len + 1); + strncpy(buf, sname, len); + buf[len] = 0; + def = find_struct_def_codegen(ctx, buf); + if (def && def->strct.is_template) + { + skip = 1; + } + free(buf); + } + } + if (mangled) + { + free(mangled); + } + if (skip) + { + iter = iter->next; + continue; + } + } + if (iter->type == NODE_IMPL_TRAIT) + { + char *sname = iter->impl_trait.target_type; + if (!sname) + { + iter = iter->next; + continue; + } + + char *mangled = replace_string_type(sname); + ASTNode *def = find_struct_def_codegen(ctx, mangled); + int skip = 0; + if (def) + { + if (def->strct.is_template) + { + skip = 1; + } + } + else + { + char *lt = strchr(sname, '<'); + if (lt) + { + int len = lt - sname; + char *buf = xmalloc(len + 1); + strncpy(buf, sname, len); + buf[len] = 0; + def = find_struct_def_codegen(ctx, buf); + if (def && def->strct.is_template) + { + skip = 1; + } + free(buf); + } + } + if (mangled) + { + free(mangled); + } + if (skip) + { + iter = iter->next; + continue; + } + } + codegen_node_single(ctx, iter, out); + iter = iter->next; } - } - codegen_node_single(ctx, iter, out); - iter = iter->next; - } - int has_user_main = 0; - ASTNode *chk = merged_funcs; - while (chk) { - if (chk->type == NODE_FUNCTION && strcmp(chk->func.name, "main") == 0) { - has_user_main = 1; - break; - } - chk = chk->next; - } + int has_user_main = 0; + ASTNode *chk = merged_funcs; + while (chk) + { + if (chk->type == NODE_FUNCTION && strcmp(chk->func.name, "main") == 0) + { + has_user_main = 1; + break; + } + chk = chk->next; + } - if (!has_user_main) { - fprintf(out, "\nint main() { _z_run_tests(); return 0; }\n"); + if (!has_user_main) + { + fprintf(out, "\nint main() { _z_run_tests(); return 0; }\n"); + } } - } } |
