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);
}