feat: 命名参数 draw_rect(width: 10, height: 20)
This commit is contained in:
+61
-5
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user