summaryrefslogtreecommitdiff
path: root/src/codegen/codegen_utils.c
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-16 00:19:37 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-16 00:19:37 +0000
commit23d18925df02157e9330c3612992e40553bb5da1 (patch)
tree89a893944aa7555c59b7700aa608f39680c0a120 /src/codegen/codegen_utils.c
parent301d9582884ec7d180791e5c9c6ec649dc01ff68 (diff)
Working on reducing function pollution
Diffstat (limited to 'src/codegen/codegen_utils.c')
-rw-r--r--src/codegen/codegen_utils.c782
1 files changed, 347 insertions, 435 deletions
diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c
index 2feb757..c10685b 100644
--- a/src/codegen/codegen_utils.c
+++ b/src/codegen/codegen_utils.c
@@ -17,505 +17,417 @@ int defer_count = 0;
ASTNode *g_current_lambda = NULL;
// Helper to emit variable declarations with array types.
-void emit_var_decl_type(ParserContext *ctx, FILE *out, const char *type_str, const char *var_name)
-{
- (void)ctx;
-
- char *bracket = strchr(type_str, '[');
-
- if (bracket)
- {
- int base_len = bracket - type_str;
- fprintf(out, "%.*s %s%s", base_len, type_str, var_name, bracket);
- }
- else
- {
- fprintf(out, "%s %s", type_str, var_name);
- }
+void emit_var_decl_type(ParserContext *ctx, FILE *out, const char *type_str,
+ const char *var_name) {
+ (void)ctx;
+
+ char *bracket = strchr(type_str, '[');
+
+ if (bracket) {
+ int base_len = bracket - type_str;
+ fprintf(out, "%.*s %s%s", base_len, type_str, var_name, bracket);
+ } else {
+ fprintf(out, "%s %s", type_str, var_name);
+ }
}
// Find struct definition
-ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name)
-{
- if (!name)
- {
- return NULL;
- }
- ASTNode *s = global_user_structs;
- while (s)
- {
- if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 && !s->strct.is_incomplete)
- {
- return s;
- }
- s = s->next;
+ASTNode *find_struct_def_codegen(ParserContext *ctx, const char *name) {
+ if (!name) {
+ return NULL;
+ }
+ ASTNode *s = global_user_structs;
+ while (s) {
+ if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 &&
+ !s->strct.is_incomplete) {
+ return s;
}
-
- // Check parsed structs list (imports)-
- StructRef *sr = ctx->parsed_structs_list;
- while (sr)
- {
- if (sr->node && sr->node->type == NODE_STRUCT && strcmp(sr->node->strct.name, name) == 0 &&
- !sr->node->strct.is_incomplete)
- {
- return sr->node;
- }
- sr = sr->next;
+ s = s->next;
+ }
+
+ // Check parsed structs list (imports)-
+ StructRef *sr = ctx->parsed_structs_list;
+ while (sr) {
+ if (sr->node && sr->node->type == NODE_STRUCT &&
+ strcmp(sr->node->strct.name, name) == 0 &&
+ !sr->node->strct.is_incomplete) {
+ return sr->node;
}
- s = ctx->instantiated_structs;
- while (s)
- {
- if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 && !s->strct.is_incomplete)
- {
- return s;
- }
- s = s->next;
+ sr = sr->next;
+ }
+ s = ctx->instantiated_structs;
+ while (s) {
+ if (s->type == NODE_STRUCT && strcmp(s->strct.name, name) == 0 &&
+ !s->strct.is_incomplete) {
+ return s;
}
- return NULL;
+ s = s->next;
+ }
+ return NULL;
}
// Get field type from struct.
-char *get_field_type_str(ParserContext *ctx, const char *struct_name, const char *field_name)
-{
- char clean_name[256];
- strncpy(clean_name, struct_name, sizeof(clean_name) - 1);
- clean_name[sizeof(clean_name) - 1] = 0;
-
- char *ptr = strchr(clean_name, '<');
- if (ptr)
- {
- *ptr = 0;
- }
-
- ASTNode *def = find_struct_def_codegen(ctx, clean_name);
- if (!def)
- {
- return NULL;
- }
+char *get_field_type_str(ParserContext *ctx, const char *struct_name,
+ const char *field_name) {
+ char clean_name[256];
+ strncpy(clean_name, struct_name, sizeof(clean_name) - 1);
+ clean_name[sizeof(clean_name) - 1] = 0;
+
+ char *ptr = strchr(clean_name, '<');
+ if (ptr) {
+ *ptr = 0;
+ }
+
+ ASTNode *def = find_struct_def_codegen(ctx, clean_name);
+ if (!def) {
+ return NULL;
+ }
- ASTNode *f = def->strct.fields;
- while (f)
- {
- if (strcmp(f->field.name, field_name) == 0)
- {
- return f->field.type;
- }
- f = f->next;
+ ASTNode *f = def->strct.fields;
+ while (f) {
+ if (strcmp(f->field.name, field_name) == 0) {
+ return f->field.type;
}
- return NULL;
+ f = f->next;
+ }
+ return NULL;
}
// Type inference.
-char *infer_type(ParserContext *ctx, ASTNode *node)
-{
- if (!node)
- {
- return NULL;
+char *infer_type(ParserContext *ctx, ASTNode *node) {
+ if (!node) {
+ return NULL;
+ }
+ if (node->resolved_type && strcmp(node->resolved_type, "unknown") != 0) {
+ return node->resolved_type;
+ }
+
+ if (node->type == NODE_EXPR_LITERAL) {
+ if (node->type_info) {
+ return type_to_string(node->type_info);
}
- if (node->resolved_type && strcmp(node->resolved_type, "unknown") != 0)
- {
- return node->resolved_type;
+ return NULL;
+ }
+
+ if (node->type == NODE_EXPR_VAR) {
+ Symbol *sym = find_symbol_entry(ctx, node->var_ref.name);
+ if (sym) {
+ if (sym->type_name) {
+ return sym->type_name;
+ }
+ if (sym->type_info) {
+ return type_to_string(sym->type_info);
+ }
}
+ }
- if (node->type == NODE_EXPR_LITERAL)
- {
- if (node->type_info)
- {
- return type_to_string(node->type_info);
+ if (node->type == NODE_EXPR_CALL) {
+ if (node->call.callee->type == NODE_EXPR_VAR) {
+ FuncSig *sig = find_func(ctx, node->call.callee->var_ref.name);
+ if (sig) {
+ if (sig->is_async) {
+ return "Async";
}
- return NULL;
- }
-
- if (node->type == NODE_EXPR_VAR)
- {
- Symbol *sym = find_symbol_entry(ctx, node->var_ref.name);
- if (sym)
- {
- if (sym->type_name)
- {
- return sym->type_name;
- }
- if (sym->type_info)
- {
- return type_to_string(sym->type_info);
- }
+ if (sig->ret_type) {
+ return type_to_string(sig->ret_type);
}
- }
+ }
- if (node->type == NODE_EXPR_CALL)
- {
- if (node->call.callee->type == NODE_EXPR_VAR)
- {
- FuncSig *sig = find_func(ctx, node->call.callee->var_ref.name);
- if (sig)
- {
- if (sig->is_async)
- {
- return "Async";
- }
- if (sig->ret_type)
- {
- return type_to_string(sig->ret_type);
- }
- }
-
- // Fallback for known stdlib memory functions.
- if (strcmp(node->call.callee->var_ref.name, "malloc") == 0 ||
- strcmp(node->call.callee->var_ref.name, "calloc") == 0 ||
- strcmp(node->call.callee->var_ref.name, "realloc") == 0)
- {
- return "void*";
- }
- ASTNode *sdef = find_struct_def_codegen(ctx, node->call.callee->var_ref.name);
- if (sdef)
- {
- return node->call.callee->var_ref.name;
- }
- }
- // Method call: target.method() - look up Type_method signature.
- if (node->call.callee->type == NODE_EXPR_MEMBER)
- {
- char *target_type = infer_type(ctx, node->call.callee->member.target);
- if (target_type)
- {
- char clean_type[256];
- strcpy(clean_type, target_type);
- char *ptr = strchr(clean_type, '*');
- if (ptr)
- {
- *ptr = 0;
- }
-
- char *base = clean_type;
- if (strncmp(base, "struct ", 7) == 0)
- {
- base += 7;
- }
-
- char func_name[512];
- sprintf(func_name, "%s_%s", base, node->call.callee->member.field);
-
- FuncSig *sig = find_func(ctx, func_name);
- if (sig && sig->ret_type)
- {
- return type_to_string(sig->ret_type);
- }
- }
+ // Fallback for known stdlib memory functions.
+ if (strcmp(node->call.callee->var_ref.name, "malloc") == 0 ||
+ strcmp(node->call.callee->var_ref.name, "calloc") == 0 ||
+ strcmp(node->call.callee->var_ref.name, "realloc") == 0) {
+ return "void*";
+ }
+ ASTNode *sdef =
+ find_struct_def_codegen(ctx, node->call.callee->var_ref.name);
+ if (sdef) {
+ return node->call.callee->var_ref.name;
+ }
+ }
+ // Method call: target.method() - look up Type_method signature.
+ if (node->call.callee->type == NODE_EXPR_MEMBER) {
+ char *target_type = infer_type(ctx, node->call.callee->member.target);
+ if (target_type) {
+ char clean_type[256];
+ strcpy(clean_type, target_type);
+ char *ptr = strchr(clean_type, '*');
+ if (ptr) {
+ *ptr = 0;
}
- if (node->call.callee->type == NODE_EXPR_VAR)
- {
- Symbol *sym = find_symbol_entry(ctx, node->call.callee->var_ref.name);
- if (sym && sym->type_info && sym->type_info->kind == TYPE_FUNCTION &&
- sym->type_info->inner)
- {
- return type_to_string(sym->type_info->inner);
- }
+ char *base = clean_type;
+ if (strncmp(base, "struct ", 7) == 0) {
+ base += 7;
}
- }
- if (node->type == NODE_TRY)
- {
- char *inner_type = infer_type(ctx, node->try_stmt.expr);
- if (inner_type)
- {
- // Extract T from Result<T> or Option<T>
- char *start = strchr(inner_type, '<');
- if (start)
- {
- start++; // Skip <
- char *end = strrchr(inner_type, '>');
- if (end && end > start)
- {
- int len = end - start;
- char *extracted = xmalloc(len + 1);
- strncpy(extracted, start, len);
- extracted[len] = 0;
- return extracted;
- }
- }
- }
- }
+ char func_name[512];
+ sprintf(func_name, "%s_%s", base, node->call.callee->member.field);
- if (node->type == NODE_EXPR_MEMBER)
- {
- char *parent_type = infer_type(ctx, node->member.target);
- if (!parent_type)
- {
- return NULL;
+ FuncSig *sig = find_func(ctx, func_name);
+ if (sig && sig->ret_type) {
+ return type_to_string(sig->ret_type);
}
+ }
+ }
- char clean_name[256];
- strcpy(clean_name, parent_type);
- char *ptr = strchr(clean_name, '*');
- if (ptr)
- {
- *ptr = 0;
- }
+ if (node->call.callee->type == NODE_EXPR_VAR) {
+ Symbol *sym = find_symbol_entry(ctx, node->call.callee->var_ref.name);
+ if (sym && sym->type_info && sym->type_info->kind == TYPE_FUNCTION &&
+ sym->type_info->inner) {
+ return type_to_string(sym->type_info->inner);
+ }
+ }
+ }
+
+ if (node->type == NODE_TRY) {
+ char *inner_type = infer_type(ctx, node->try_stmt.expr);
+ if (inner_type) {
+ // Extract T from Result<T> or Option<T>
+ char *start = strchr(inner_type, '<');
+ if (start) {
+ start++; // Skip <
+ char *end = strrchr(inner_type, '>');
+ if (end && end > start) {
+ int len = end - start;
+ char *extracted = xmalloc(len + 1);
+ strncpy(extracted, start, len);
+ extracted[len] = 0;
+ return extracted;
+ }
+ }
+ }
+ }
- return get_field_type_str(ctx, clean_name, node->member.field);
+ if (node->type == NODE_EXPR_MEMBER) {
+ char *parent_type = infer_type(ctx, node->member.target);
+ if (!parent_type) {
+ return NULL;
}
- if (node->type == NODE_EXPR_BINARY)
- {
- if (strcmp(node->binary.op, "??") == 0)
- {
- return infer_type(ctx, node->binary.left);
- }
+ char clean_name[256];
+ strcpy(clean_name, parent_type);
+ char *ptr = strchr(clean_name, '*');
+ if (ptr) {
+ *ptr = 0;
+ }
- const char *op = node->binary.op;
- char *left_type = infer_type(ctx, node->binary.left);
- char *right_type = infer_type(ctx, node->binary.right);
+ return get_field_type_str(ctx, clean_name, node->member.field);
+ }
- int is_logical = (strcmp(op, "&&") == 0 || strcmp(op, "||") == 0 || strcmp(op, "==") == 0 ||
- strcmp(op, "!=") == 0 || strcmp(op, "<") == 0 || strcmp(op, ">") == 0 ||
- strcmp(op, "<=") == 0 || strcmp(op, ">=") == 0);
+ if (node->type == NODE_EXPR_BINARY) {
+ if (strcmp(node->binary.op, "??") == 0) {
+ return infer_type(ctx, node->binary.left);
+ }
- if (is_logical)
- {
- return xstrdup("int");
- }
+ const char *op = node->binary.op;
+ char *left_type = infer_type(ctx, node->binary.left);
+ char *right_type = infer_type(ctx, node->binary.right);
- if (left_type && strcmp(left_type, "usize") == 0)
- {
- return "usize";
- }
- if (right_type && strcmp(right_type, "usize") == 0)
- {
- return "usize";
- }
- if (left_type && strcmp(left_type, "double") == 0)
- {
- return "double";
- }
+ int is_logical = (strcmp(op, "&&") == 0 || strcmp(op, "||") == 0 ||
+ strcmp(op, "==") == 0 || strcmp(op, "!=") == 0 ||
+ strcmp(op, "<") == 0 || strcmp(op, ">") == 0 ||
+ strcmp(op, "<=") == 0 || strcmp(op, ">=") == 0);
- return left_type ? left_type : right_type;
+ if (is_logical) {
+ return xstrdup("int");
}
- if (node->type == NODE_MATCH)
- {
- ASTNode *case_node = node->match_stmt.cases;
- while (case_node)
- {
- char *type = infer_type(ctx, case_node->match_case.body);
- if (type && strcmp(type, "void") != 0 && strcmp(type, "unknown") != 0)
- {
- return type;
- }
- case_node = case_node->next;
- }
- return NULL;
+ if (left_type && strcmp(left_type, "usize") == 0) {
+ return "usize";
}
-
- if (node->type == NODE_EXPR_INDEX)
- {
- char *array_type = infer_type(ctx, node->index.array);
- if (array_type)
- {
- // If T*, returns T. If T[], returns T.
- char *ptr = strrchr(array_type, '*');
- if (ptr)
- {
- int len = ptr - array_type;
- char *buf = xmalloc(len + 1);
- strncpy(buf, array_type, len);
- buf[len] = 0;
- return buf;
- }
- }
- return "int";
+ if (right_type && strcmp(right_type, "usize") == 0) {
+ return "usize";
+ }
+ if (left_type && strcmp(left_type, "double") == 0) {
+ return "double";
}
- if (node->type == NODE_EXPR_UNARY)
- {
- if (strcmp(node->unary.op, "&") == 0)
- {
- char *inner = infer_type(ctx, node->unary.operand);
- if (inner)
- {
- char *buf = xmalloc(strlen(inner) + 2);
- sprintf(buf, "%s*", inner);
- return buf;
- }
- }
- if (strcmp(node->unary.op, "*") == 0)
- {
- char *inner = infer_type(ctx, node->unary.operand);
- if (inner)
- {
- char *ptr = strchr(inner, '*');
- if (ptr)
- {
- // Return base type (naive)
- int len = ptr - inner;
- char *dup = xmalloc(len + 1);
- strncpy(dup, inner, len);
- dup[len] = 0;
- return dup;
- }
- }
- }
- return infer_type(ctx, node->unary.operand);
+ return left_type ? left_type : right_type;
+ }
+
+ if (node->type == NODE_MATCH) {
+ ASTNode *case_node = node->match_stmt.cases;
+ while (case_node) {
+ char *type = infer_type(ctx, case_node->match_case.body);
+ if (type && strcmp(type, "void") != 0 && strcmp(type, "unknown") != 0) {
+ return type;
+ }
+ case_node = case_node->next;
+ }
+ return NULL;
+ }
+
+ if (node->type == NODE_EXPR_INDEX) {
+ char *array_type = infer_type(ctx, node->index.array);
+ if (array_type) {
+ // If T*, returns T. If T[], returns T.
+ char *ptr = strrchr(array_type, '*');
+ if (ptr) {
+ int len = ptr - array_type;
+ char *buf = xmalloc(len + 1);
+ strncpy(buf, array_type, len);
+ buf[len] = 0;
+ return buf;
+ }
+ }
+ return "int";
+ }
+
+ if (node->type == NODE_EXPR_UNARY) {
+ if (strcmp(node->unary.op, "&") == 0) {
+ char *inner = infer_type(ctx, node->unary.operand);
+ if (inner) {
+ char *buf = xmalloc(strlen(inner) + 2);
+ sprintf(buf, "%s*", inner);
+ return buf;
+ }
+ }
+ if (strcmp(node->unary.op, "*") == 0) {
+ char *inner = infer_type(ctx, node->unary.operand);
+ if (inner) {
+ char *ptr = strchr(inner, '*');
+ if (ptr) {
+ // Return base type (naive)
+ int len = ptr - inner;
+ char *dup = xmalloc(len + 1);
+ strncpy(dup, inner, len);
+ dup[len] = 0;
+ return dup;
+ }
+ }
+ }
+ return infer_type(ctx, node->unary.operand);
+ }
+
+ if (node->type == NODE_AWAIT) {
+ // Infer underlying type T from await Async<T>
+ // If it's a direct call await foo(), we know T from foo's signature.
+ if (node->unary.operand->type == NODE_EXPR_CALL &&
+ node->unary.operand->call.callee->type == NODE_EXPR_VAR) {
+ FuncSig *sig =
+ find_func(ctx, node->unary.operand->call.callee->var_ref.name);
+ if (sig && sig->ret_type) {
+ return type_to_string(sig->ret_type);
+ }
}
- if (node->type == NODE_AWAIT)
- {
- // Infer underlying type T from await Async<T>
- // If it's a direct call await foo(), we know T from foo's signature.
- if (node->unary.operand->type == NODE_EXPR_CALL &&
- node->unary.operand->call.callee->type == NODE_EXPR_VAR)
- {
- FuncSig *sig = find_func(ctx, node->unary.operand->call.callee->var_ref.name);
- if (sig && sig->ret_type)
- {
- return type_to_string(sig->ret_type);
- }
- }
+ return "void*";
+ }
- return "void*";
- }
+ if (node->type == NODE_EXPR_CAST) {
+ return node->cast.target_type;
+ }
- if (node->type == NODE_EXPR_CAST)
- {
- return node->cast.target_type;
- }
+ if (node->type == NODE_EXPR_STRUCT_INIT) {
+ return node->struct_init.struct_name;
+ }
- if (node->type == NODE_EXPR_STRUCT_INIT)
- {
- return node->struct_init.struct_name;
+ if (node->type == NODE_EXPR_LITERAL) {
+ if (node->literal.type_kind == TOK_STRING) {
+ return "string";
}
-
- if (node->type == NODE_EXPR_LITERAL)
- {
- if (node->literal.type_kind == TOK_STRING)
- {
- return "string";
- }
- if (node->literal.type_kind == TOK_CHAR)
- {
- return "char";
- }
- if (node->literal.type_kind == 1)
- {
- return "double";
- }
- return "int";
+ if (node->literal.type_kind == TOK_CHAR) {
+ return "char";
+ }
+ if (node->literal.type_kind == 1) {
+ return "double";
}
+ return "int";
+ }
- return NULL;
+ return NULL;
}
// Extract variable names from argument string.
-char *extract_call_args(const char *args)
-{
- if (!args || strlen(args) == 0)
- {
- return xstrdup("");
+char *extract_call_args(const char *args) {
+ if (!args || strlen(args) == 0) {
+ return xstrdup("");
+ }
+ char *out = xmalloc(strlen(args) + 1);
+ out[0] = 0;
+
+ char *dup = xstrdup(args);
+ char *p = strtok(dup, ",");
+ while (p) {
+ while (*p == ' ') {
+ p++;
}
- char *out = xmalloc(strlen(args) + 1);
- out[0] = 0;
-
- char *dup = xstrdup(args);
- char *p = strtok(dup, ",");
- while (p)
- {
- while (*p == ' ')
- {
- p++;
- }
- char *last_space = strrchr(p, ' ');
- char *ptr_star = strrchr(p, '*');
-
- char *name = p;
- if (last_space)
- {
- name = last_space + 1;
- }
- if (ptr_star && ptr_star > last_space)
- {
- name = ptr_star + 1;
- }
+ char *last_space = strrchr(p, ' ');
+ char *ptr_star = strrchr(p, '*');
- if (strlen(out) > 0)
- {
- strcat(out, ", ");
- }
- strcat(out, name);
+ char *name = p;
+ if (last_space) {
+ name = last_space + 1;
+ }
+ if (ptr_star && ptr_star > last_space) {
+ name = ptr_star + 1;
+ }
- p = strtok(NULL, ",");
+ if (strlen(out) > 0) {
+ strcat(out, ", ");
}
- free(dup);
- return out;
+ strcat(out, name);
+
+ p = strtok(NULL, ",");
+ }
+ free(dup);
+ return out;
}
// Parse original method name from mangled name.
-const char *parse_original_method_name(const char *mangled)
-{
- const char *last = strrchr(mangled, '_');
- return last ? last + 1 : mangled;
+const char *parse_original_method_name(const char *mangled) {
+ const char *last = strrchr(mangled, '_');
+ return last ? last + 1 : mangled;
}
// Replace string type in arguments.
-char *replace_string_type(const char *args)
-{
- if (!args)
- {
- return NULL;
- }
- char *res = xmalloc(strlen(args) * 2 + 1);
- res[0] = 0;
- const char *p = args;
- while (*p)
- {
- const char *match = strstr(p, "string ");
- if (match)
- {
- if (match > args && (isalnum(*(match - 1)) || *(match - 1) == '_'))
- {
- strncat(res, p, match - p + 6);
- p = match + 6;
- }
- else
- {
- strncat(res, p, match - p);
- strcat(res, "const char* ");
- p = match + 7;
- }
- }
- else
- {
- strcat(res, p);
- break;
- }
+char *replace_string_type(const char *args) {
+ if (!args) {
+ return NULL;
+ }
+ char *res = xmalloc(strlen(args) * 2 + 1);
+ res[0] = 0;
+ const char *p = args;
+ while (*p) {
+ const char *match = strstr(p, "string ");
+ if (match) {
+ if (match > args && (isalnum(*(match - 1)) || *(match - 1) == '_')) {
+ strncat(res, p, match - p + 6);
+ p = match + 6;
+ } else {
+ strncat(res, p, match - p);
+ strcat(res, "const char* ");
+ p = match + 7;
+ }
+ } else {
+ strcat(res, p);
+ break;
}
- return res;
+ }
+ return res;
}
// Helper to emit auto type or fallback.
-void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out)
-{
- char *inferred = NULL;
- if (init_expr)
- {
- inferred = infer_type(ctx, init_expr);
- }
-
- if (inferred && strcmp(inferred, "__auto_type") != 0 && strcmp(inferred, "unknown") != 0)
- {
- fprintf(out, "%s", inferred);
- }
- else
- {
- if (strstr(g_config.cc, "tcc"))
- {
- zpanic_with_suggestion(t,
- "Type inference failed for variable initialization and TCC does "
- "not support __auto_type",
- "Please specify the type explicitly: 'var x: Type = ...'");
- }
- else
- {
- fprintf(out, "__auto_type");
- }
+void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t,
+ FILE *out) {
+ char *inferred = NULL;
+ if (init_expr) {
+ inferred = infer_type(ctx, init_expr);
+ }
+
+ if (inferred && strcmp(inferred, "__auto_type") != 0 &&
+ strcmp(inferred, "unknown") != 0) {
+ fprintf(out, "%s", inferred);
+ } else {
+ if (strstr(g_config.cc, "tcc")) {
+ zpanic_with_suggestion(
+ t,
+ "Type inference failed for variable initialization and TCC does "
+ "not support __auto_type",
+ "Please specify the type explicitly: 'var x: Type = ...'");
+ } else {
+ fprintf(out, "__auto_type");
}
+ }
}