feat: 命名参数 draw_rect(width: 10, height: 20)

This commit is contained in:
2026-06-05 20:54:58 +08:00
parent c6e492662e
commit 6b6925b2b8
9 changed files with 272 additions and 24 deletions
+61 -5
View File
@@ -191,6 +191,34 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
}
break;
}
// 命名参数重排序: 将命名 arg 按参数名映射到正确位置
if (node->as.call.arg_names) {
AstNode* reordered[16] = {0};
for (size_t i = 0; i < node->as.call.arg_count; i++) {
if (node->as.call.arg_names[i]) {
// 查找参数名匹配
bool found = false;
for (size_t j = 0; j < sym->param_count; j++) {
if (sym->param_names && sym->param_names[j] &&
strcmp(node->as.call.arg_names[i], sym->param_names[j]) == 0) {
reordered[j] = node->as.call.args[i];
found = true; break;
}
}
if (!found) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"函数 '%s' 没有名为 '%s' 的参数",
node->as.call.name, node->as.call.arg_names[i]);
node->type.kind = TYPE_ERROR; return;
}
} else {
// 位置参数保持原位
reordered[i] = node->as.call.args[i];
}
}
// 填充未指定的命名参数(用 NULL 跳过,后续检查会报错)
memcpy(node->as.call.args, reordered, node->as.call.arg_count * sizeof(AstNode*));
}
for (size_t i = 0; i < node->as.call.arg_count; i++) {
analyze_expr(node->as.call.args[i], scope, errors, a);
TypeKind actual = node->as.call.args[i]->type.kind;
@@ -402,6 +430,31 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
node->as.method_call.arg_count);
node->type.kind = TYPE_ERROR; break;
}
// 命名参数重排序(同 CALL_EXPR 逻辑)
if (node->as.method_call.arg_names) {
AstNode* reordered[16] = {0};
for (size_t i = 0; i < node->as.method_call.arg_count; i++) {
if (node->as.method_call.arg_names[i]) {
bool found = false;
for (size_t j = 1; j < sym->param_count; j++) { // skip self
if (sym->param_names && sym->param_names[j] &&
strcmp(node->as.method_call.arg_names[i], sym->param_names[j]) == 0) {
reordered[j - 1] = node->as.method_call.args[i];
found = true; break;
}
}
if (!found) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"方法 '%s' 没有名为 '%s' 的参数",
node->as.method_call.method_name, node->as.method_call.arg_names[i]);
node->type.kind = TYPE_ERROR; return;
}
} else {
reordered[i] = node->as.method_call.args[i];
}
}
memcpy(node->as.method_call.args, reordered, node->as.method_call.arg_count * sizeof(AstNode*));
}
// 对每个参数进行类型检查(跳过 self 参数,即 sym->param_types[0] 是 self 的类型)
for (size_t i = 0; i < node->as.method_call.arg_count; i++) {
analyze_expr(node->as.method_call.args[i], scope, errors, a);
@@ -530,10 +583,12 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
for (size_t i = 0; i < node->as.program.fn_count; i++) {
AstNode* fn = node->as.program.functions[i];
TypeKind* pts = (TypeKind*)arena_alloc_impl(a, fn->as.function.param_count * sizeof(TypeKind));
const char** pnames = (const char**)arena_alloc_impl(a, fn->as.function.param_count * sizeof(const char*));
const char** pstruct_names = (const char**)arena_alloc_impl(a, fn->as.function.param_count * sizeof(const char*));
for (size_t j = 0; j < fn->as.function.param_count; j++) {
TypeKind pt = fn->as.function.params[j]->as.parameter.type;
const char* psn = fn->as.function.params[j]->as.parameter.struct_type_name;
const char* pn = fn->as.function.params[j]->as.parameter.name;
// 解析参数类型的别名
if (psn) {
Symbol* as = scope_lookup(scope, psn);
@@ -543,6 +598,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
}
}
pts[j] = pt;
pnames[j] = pn;
pstruct_names[j] = psn;
}
// 解析返回类型的别名
@@ -557,7 +613,7 @@ 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, pstruct_names,
pts, pnames, pstruct_names,
fn->as.function.param_count);
}
// 第三遍:分析每个函数体
@@ -840,13 +896,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, 1);
scope_insert_function(global_scope, arena, "print_i64", TYPE_VOID, NULL, params_i64, NULL, NULL, 1);
TypeKind params_f64[] = {TYPE_F64};
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, NULL, params_f64, NULL, 1);
scope_insert_function(global_scope, arena, "print_f64", TYPE_VOID, NULL, params_f64, NULL, NULL, 1);
TypeKind params_bool[] = {TYPE_BOOL};
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, NULL, params_bool, NULL, 1);
scope_insert_function(global_scope, arena, "print_bool", TYPE_VOID, NULL, params_bool, NULL, NULL, 1);
TypeKind params_str[] = {TYPE_STR};
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, NULL, params_str, NULL, 1);
scope_insert_function(global_scope, arena, "print_str", TYPE_VOID, NULL, params_str, NULL, NULL, 1);
analyze_node(ast, global_scope, errors, arena);
}
+6 -4
View File
@@ -30,7 +30,7 @@ Symbol* scope_insert(Scope* scope, void* alloc, const char* name,
if (!sym) return NULL;
sym->name = name; sym->kind = kind; sym->type = type;
sym->is_mut = false; sym->return_type = TYPE_VOID;
sym->param_types = NULL; sym->param_count = 0;
sym->param_types = NULL; sym->param_names = NULL; sym->param_count = 0;
sym->struct_field_names = NULL;
sym->struct_field_types = NULL;
sym->struct_field_count = 0;
@@ -46,7 +46,8 @@ Symbol* scope_insert(Scope* scope, void* alloc, const char* name,
Symbol* scope_insert_function(Scope* scope, void* alloc, const char* name,
TypeKind ret, const char* ret_struct_name,
TypeKind* pt, const char** pstruct_names, size_t pc) {
TypeKind* pt, const char** pnames,
const char** pstruct_names, size_t pc) {
if (scope->head) {
for (Symbol* sym = scope->head; sym; sym = sym->next) {
if (strcmp(sym->name, name) == 0) return NULL;
@@ -58,6 +59,7 @@ Symbol* scope_insert_function(Scope* scope, void* alloc, const char* name,
sym->return_type = ret;
sym->return_struct_type_name = ret_struct_name;
sym->param_types = pt;
sym->param_names = pnames;
sym->param_struct_names = pstruct_names;
sym->param_count = pc;
sym->struct_field_names = NULL;
@@ -85,7 +87,7 @@ Symbol* scope_insert_struct(Scope* scope, void* alloc, const char* name,
if (!sym) return NULL;
sym->name = name; sym->kind = SYM_STRUCT; sym->type = TYPE_STRUCT;
sym->is_mut = false; sym->return_type = TYPE_VOID;
sym->param_types = NULL; sym->param_count = 0;
sym->param_types = NULL; sym->param_names = NULL; sym->param_count = 0;
sym->struct_field_names = fnames;
sym->struct_field_types = ftypes;
sym->struct_field_struct_names = fstruct_names;
@@ -130,7 +132,7 @@ Symbol* scope_insert_enum(Scope* scope, void* alloc, const char* name,
if (!sym) return NULL;
sym->name = name; sym->kind = SYM_ENUM; sym->type = TYPE_ENUM;
sym->is_mut = false; sym->return_type = TYPE_VOID;
sym->param_types = NULL; sym->param_count = 0;
sym->param_types = NULL; sym->param_names = NULL; sym->param_count = 0;
sym->struct_field_names = vnames;
sym->struct_field_types = NULL;
sym->struct_field_struct_names = NULL;
+3 -1
View File
@@ -15,6 +15,7 @@ typedef struct Symbol {
TypeKind return_type;
const char* return_struct_type_name; // 返回类型为 struct 时的类型名
TypeKind* param_types;
const char** param_names; // 参数名(用于命名参数匹配)
const char** param_struct_names; // 参数为 struct 时的类型名
size_t param_count;
// 结构体特有(SYM_STRUCT
@@ -52,7 +53,8 @@ Symbol* scope_insert(Scope* scope, void* alloc, const char* name,
// 插入函数符号
Symbol* scope_insert_function(Scope* scope, void* alloc, const char* name,
TypeKind ret, const char* ret_struct_name,
TypeKind* pt, const char** pstruct_names, size_t pc);
TypeKind* pt, const char** pnames,
const char** pstruct_names, size_t pc);
// 插入结构体符号
Symbol* scope_insert_struct(Scope* scope, void* alloc, const char* name,