diff --git a/App/lib/core/Gen/CallGenMixin.vp b/App/lib/core/Gen/CallGenMixin.vp index e37bdb5..83684fd 100644 --- a/App/lib/core/Gen/CallGenMixin.vp +++ b/App/lib/core/Gen/CallGenMixin.vp @@ -2023,6 +2023,11 @@ class CallGenMixin: tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) if tmp is None: return llvmlite.ConstZero(pool, struct_ty) + # 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的 + # fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点) + diag_node_ct: ast.AST | t.CPtr = None + if cargs is not None and len(cargs) > 0: + diag_node_ct = cargs.get(0) # 检查是否为 OOP 结构体(用类型指针定位 entry,规避跨模块同名 find_struct 找错) ctor_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) @@ -2081,7 +2086,7 @@ class CallGenMixin: new_ptr: llvmlite.Value | t.CPtr = self._call_method_on_ptr( pool, builder, mod, class_name, - "__new__", tmp, new_arg_vals, new_arg_count, trans) + "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct) if new_ptr is not None: storage_ptr = new_ptr # __new__ 只保证返回"实例存储指针",声明类型通常是 @@ -2099,7 +2104,7 @@ class CallGenMixin: # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 self._call_method_on_ptr(pool, builder, mod, class_name, - "__before_init__", storage_ptr, None, 0, trans) + "__before_init__", storage_ptr, None, 0, trans, diag_node_ct) # 如果有 __init__,调用 __init__(ptr, args...) # 注意: 仅依据 ctor_entry.HasInit 判断,不强制推断 @@ -2125,7 +2130,7 @@ class CallGenMixin: real_arg_count += 1 self._call_method_on_ptr(pool, builder, mod, class_name, - "__init__", storage_ptr, arg_vals, real_arg_count, trans) + "__init__", storage_ptr, arg_vals, real_arg_count, trans, diag_node_ct) elif has_new_flag == 0: # 无 __init__ 且无 __new__:逐字段 store 参数值 # (有 __new__ 时参数已由 __new__ 消费,不应存入字段) @@ -2709,9 +2714,19 @@ class CallGenMixin: node, f"调用 '{lookup_name}' 缺少参数(无默认值)", "TypeError") mdf_pi += 1 elif found_func is not None: - # 无默认参数信息但有 found_func:剩余形参即调用缺参(无默认值),fail-fast - HandlesType.fatal_error( - node, f"调用 '{lookup_name}' 缺少参数(无默认值)", "TypeError") + # 无函数表默认参数信息但有 found_func:数形参数量判断是否真的缺参。 + # 注意:不能无条件 fail-fast——mdf 缺失时 extra_count 可能正好等于 + # 形参数量(如 JsonValue(pool) 构造 __new__(self, pool)), + # 参数匹配是合法调用,误报会阻断正常构造。 + fp_count: int = 0 + fpn_c: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) + while fpn_c is not None: + fp_count += 1 + fpn_c = llvmlite.param_get_next(fpn_c) + if total_count < fp_count: + # 调用实参(含 self)少于形参(含 self)且无默认值:缺参错误 + HandlesType.fatal_error( + node, f"调用 '{lookup_name}' 缺少参数(无默认值)", "TypeError") # 参数类型强制转换:按 found_func 的形参类型 coerce 每个实参(跳过 self/cls 参数 0) # 修复: 构造器调用 __init__(ptr, base, 4096) 时 size 形参是 i64 (t.CSizeT), @@ -4268,6 +4283,11 @@ class CallGenMixin: tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) if tmp is None: return llvmlite.ConstZero(pool, struct_ty) + # 诊断节点:取第一个构造实参(有行号),供 _call_method_on_ptr 的 + # fatal_error 显示构造调用行号(本函数无 cl 参数,实参节点最接近调用点) + diag_node_ct: ast.AST | t.CPtr = None + if cargs is not None and len(cargs) > 0: + diag_node_ct = cargs.get(0) # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 # 用 find_struct_by_type 规避跨模块同名 find_struct 找错 @@ -4356,7 +4376,7 @@ class CallGenMixin: new_arg_count += 1 new_ptr: llvmlite.Value | t.CPtr = self._call_method_on_ptr( pool, builder, mod, class_name, - "__new__", tmp, new_arg_vals, new_arg_count, trans) + "__new__", tmp, new_arg_vals, new_arg_count, trans, diag_node_ct) if new_ptr is not None: storage_ptr = new_ptr # __new__ 只保证返回"实例存储指针",声明类型通常是 @@ -4402,7 +4422,7 @@ class CallGenMixin: # 调用 __init__(storage_ptr, *args) self._call_method_on_ptr(pool, builder, mod, class_name, - "__init__", storage_ptr, init_arg_vals, init_arg_count, trans) + "__init__", storage_ptr, init_arg_vals, init_arg_count, trans, diag_node_ct) # 返回指针 return storage_ptr