feat: 泛型基础设施 — <T>解析 + 类型推断 (单态化 codegen 待补)
This commit is contained in:
+40
-19
@@ -159,31 +159,39 @@ static void analyze_binary_expr(AstNode* node, Scope* scope, ErrorList* errors,
|
||||
}
|
||||
|
||||
// 参数类型匹配检查(CALL_EXPR 和 METHOD_CALL 共用)
|
||||
static void check_arg_type(AstNode* arg, TypeKind expected, const char* expected_sname,
|
||||
size_t idx, AstNode* call_node, Scope* scope,
|
||||
static bool check_arg_type(AstNode* arg, TypeKind expected, const char* expected_sname,
|
||||
size_t idx, AstNode* call_node, Symbol* fn_sym,
|
||||
ErrorList* errors, Arena* a) {
|
||||
(void)scope; (void)a;
|
||||
(void)a;
|
||||
TypeKind actual = arg->type.kind;
|
||||
if (actual == TYPE_ERROR) return;
|
||||
if (expected == TYPE_STRUCT) {
|
||||
if (actual == TYPE_ERROR) return false;
|
||||
if (expected == TYPE_STRUCT && expected_sname) {
|
||||
// 检查是否是泛型类型参数(匹配则接受任意类型)
|
||||
if (fn_sym && fn_sym->type_params) {
|
||||
for (size_t t = 0; t < fn_sym->type_param_count; t++) {
|
||||
if (strcmp(expected_sname, fn_sym->type_params[t]) == 0)
|
||||
return true; // 泛型参数,接受任意类型
|
||||
}
|
||||
}
|
||||
const char* actual_name = arg->type.struct_name;
|
||||
if (actual != TYPE_STRUCT || !actual_name || !expected_sname ||
|
||||
if (actual != TYPE_STRUCT || !actual_name ||
|
||||
strcmp(actual_name, expected_sname) != 0) {
|
||||
error_add(errors, "<sema>", call_node->loc.line, call_node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
idx + 1, expected_sname ? expected_sname : "struct",
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (actual == expected) return;
|
||||
if (expected == TYPE_I64 && actual == TYPE_ENUM) return;
|
||||
if (can_implicit_convert(actual, expected)) return;
|
||||
if (actual == expected) return false;
|
||||
if (expected == TYPE_I64 && actual == TYPE_ENUM) return false;
|
||||
if (can_implicit_convert(actual, expected)) return false;
|
||||
if (actual == TYPE_I64 && arg->kind == AST_LITERAL_EXPR
|
||||
&& (expected == TYPE_I32 || expected == TYPE_U64 || expected == TYPE_CHAR)) return;
|
||||
&& (expected == TYPE_I32 || expected == TYPE_U64 || expected == TYPE_CHAR)) return false;
|
||||
error_add(errors, "<sema>", call_node->loc.line, call_node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
idx + 1, type_name(expected), type_name(actual));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 命名参数重排序(CALL_EXPR 和 METHOD_CALL 共用)
|
||||
@@ -241,9 +249,20 @@ static void analyze_call_expr(AstNode* node, Scope* scope, ErrorList* errors, Ar
|
||||
}
|
||||
for (size_t i = 0; i < node->as.call.arg_count; i++) {
|
||||
analyze_expr(node->as.call.args[i], scope, errors, a);
|
||||
check_arg_type(node->as.call.args[i], sym->param_types[i],
|
||||
bool is_generic_param = check_arg_type(node->as.call.args[i], sym->param_types[i],
|
||||
sym->param_struct_names ? sym->param_struct_names[i] : NULL,
|
||||
i, node, scope, errors, a);
|
||||
i, node, sym, errors, a);
|
||||
// 泛型: 若实参匹配类型参数,传播具体类型到返回值
|
||||
if (is_generic_param && sym->return_type == TYPE_STRUCT
|
||||
&& sym->return_struct_type_name && sym->type_params) {
|
||||
for (size_t t = 0; t < sym->type_param_count; t++) {
|
||||
if (strcmp(sym->return_struct_type_name, sym->type_params[t]) == 0) {
|
||||
node->type.kind = node->as.call.args[i]->type.kind;
|
||||
node->type.struct_name = node->as.call.args[i]->type.struct_name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
node->type.kind = sym->return_type;
|
||||
if (sym->return_type == TYPE_STRUCT && sym->return_struct_type_name)
|
||||
@@ -422,7 +441,7 @@ static void analyze_method_call(AstNode* node, Scope* scope, ErrorList* errors,
|
||||
analyze_expr(node->as.method_call.args[i], scope, errors, a);
|
||||
check_arg_type(node->as.method_call.args[i], sym->param_types[i + 1],
|
||||
sym->param_struct_names ? sym->param_struct_names[i + 1] : NULL,
|
||||
i, node, scope, errors, a);
|
||||
i, node, sym, errors, a);
|
||||
}
|
||||
node->type.kind = sym->return_type;
|
||||
if (sym->return_type == TYPE_STRUCT && sym->return_struct_type_name)
|
||||
@@ -572,7 +591,9 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
scope_insert_function(scope, a, fn->as.function.name,
|
||||
ret_t, ret_sn,
|
||||
pts, pnames, pstruct_names,
|
||||
fn->as.function.param_count);
|
||||
fn->as.function.param_count,
|
||||
fn->as.function.type_params,
|
||||
fn->as.function.type_param_count);
|
||||
}
|
||||
// 第三遍:分析每个函数体
|
||||
for (size_t i = 0; i < node->as.program.fn_count; i++) {
|
||||
@@ -884,13 +905,13 @@ void sema_analyze(AstNode* ast, ErrorList* errors, Arena* arena) {
|
||||
|
||||
// 注册内置函数
|
||||
TypeKind params_i64[] = {TYPE_I64};
|
||||
scope_insert_function(global_scope, arena, "print_i64", TYPE_VOID, NULL, params_i64, NULL, NULL, 1);
|
||||
scope_insert_function(global_scope, arena, "print_i64", TYPE_VOID, NULL, params_i64, NULL, NULL, 1, NULL, 0);
|
||||
TypeKind params_f64[] = {TYPE_F64};
|
||||
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, NULL, params_f64, NULL, NULL, 1);
|
||||
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, NULL, params_f64, NULL, NULL, 1, NULL, 0);
|
||||
TypeKind params_bool[] = {TYPE_BOOL};
|
||||
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, NULL, params_bool, NULL, NULL, 1);
|
||||
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, NULL, params_bool, NULL, NULL, 1, NULL, 0);
|
||||
TypeKind params_str[] = {TYPE_STR};
|
||||
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, NULL, params_str, NULL, NULL, 1);
|
||||
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, NULL, params_str, NULL, NULL, 1, NULL, 0);
|
||||
|
||||
analyze_node(ast, global_scope, errors, arena);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user