diff --git a/App/lib/core/Handles/HandlesClassDef.vp b/App/lib/core/Handles/HandlesClassDef.vp index f05970d..3d4a9c3 100644 --- a/App/lib/core/Handles/HandlesClassDef.vp +++ b/App/lib/core/Handles/HandlesClassDef.vp @@ -3618,7 +3618,14 @@ def _translate_method(trans: HT.Translator | t.CPtr, resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans) if resolved is not None: - param_ty = resolved + # 裸类形参 → Ptr(struct):按"对象即指针"引用传参。 + # 若按 struct 值传参,self.Head = node 会取局部拷贝地址 + # (append 返回后悬垂,G5 Test4 head.Value 读到垃圾)。 + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved pname: t.CChar | t.CPtr = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) @@ -3683,7 +3690,12 @@ def _translate_method(trans: HT.Translator | t.CPtr, resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg2.annotation, imported_modules, from_imports, trans) if resolved2 is not None: - param_ty2 = resolved2 + # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) + match resolved2: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty2 = llvmlite.Ptr(pool, resolved2) + case _: + param_ty2 = resolved2 alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) if alloca is not None: HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) diff --git a/App/lib/core/Handles/HandlesExprCall.vp b/App/lib/core/Handles/HandlesExprCall.vp index 2d4d675..2aacae2 100644 --- a/App/lib/core/Handles/HandlesExprCall.vp +++ b/App/lib/core/Handles/HandlesExprCall.vp @@ -4532,6 +4532,46 @@ def _extract_type_args_from_slice(pool: memhub.MemBuddy | t.CPtr, # 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1 # 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。 # ============================================================ +def _infer_generic_ctor_type_arg(pool: memhub.MemBuddy | t.CPtr, + arg_node: ast.AST | t.CPtr) -> str: + """从构造实参 AST 推断泛型类型实参名;无法推断时默认 "int"(与 TPC 一致) + + 裸名泛型类构造(Box(42) → Box[int])需要从实参推断类型实参。 + 对应 TPC _HandleGenericClassNewLlvm 的推断逻辑(常量/类型转换调用)。 + 注意:本函数仅做 AST 静态推断,不发射 IR(避免重复翻译实参)。 + """ + if pool is None or arg_node is None: + return "int" + k: int = arg_node.kind() + # 常量: 42→int, 3.14→double, "abc"→str + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg_node) + if cn.const_kind == ast.CONST_FLOAT: + return "double" + if cn.const_kind == ast.CONST_STR: + return "str" + return "int" + # 类型转换调用: int(...)/float(...)/t.CInt(...)/t.CDouble(...) + if k == ast.ASTKind.Call: + cl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(arg_node) + if cl_f.func is not None: + if cl_f.func.kind() == ast.ASTKind.Name: + fn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl_f.func) + if fn_nm.id is not None: + if string.strcmp(fn_nm.id, "float") == 0: + return "double" + if string.strcmp(fn_nm.id, "int") == 0: + return "int" + elif cl_f.func.kind() == ast.ASTKind.Attribute: + fn_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl_f.func) + if fn_at.attr is not None: + if string.strstr(fn_at.attr, "Float") is not None or string.strstr(fn_at.attr, "Double") is not None: + return "double" + if string.strstr(fn_at.attr, "Int") is not None or string.strstr(fn_at.attr, "UInt") is not None or string.strstr(fn_at.attr, "Char") is not None or string.strstr(fn_at.attr, "Short") is not None or string.strstr(fn_at.attr, "Long") is not None: + return "int" + return "int" + + def _translate_generic_ctor_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, @@ -4731,8 +4771,12 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr, # 等价于 (t.CChar | t.CPtr)(x) / (t.CInt32T)(x) # 单参数:str(val) → bitcast val to i8* # int(val) → trunc/sext val to i32 + # 泛型类型参数: 类特化/泛型函数上下文中的 T(x) 先解析 T 为具体类型名 + # (如 "int")再按内建强转处理(Box[int].__init__ 的 self.value = T(v)、 + # combine[T1,T2] 的 T1(b) 依赖此路径) if func_name is not None and can == 1: - if string.strcmp(func_name, "str") == 0 or string.strcmp(func_name, "bytes") == 0: + cast_fn_name: str = HandlesType.resolve_generic_type_name(func_name) + if string.strcmp(cast_fn_name, "str") == 0 or string.strcmp(cast_fn_name, "bytes") == 0: # str(x) / bytes(x) → i8* (bitcast) cast_arg: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) @@ -4740,7 +4784,7 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr, i8_ptr_ty_builtin: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) return _translate_t_type_cast(pool, builder, cast_arg, i8_ptr_ty_builtin) return None - elif string.strcmp(func_name, "int") == 0: + elif string.strcmp(cast_fn_name, "int") == 0: # int(x) → i32 cast_arg_int: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) @@ -4748,7 +4792,7 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr, i32_ty_builtin: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) return _translate_t_type_cast(pool, builder, cast_arg_int, i32_ty_builtin) return None - elif string.strcmp(func_name, "bool") == 0: + elif string.strcmp(cast_fn_name, "bool") == 0: # bool(x) → i1(严格 != 0 归一化) # 整数: icmp ne x, 0 → i1 # 浮点: fcmp one x, 0.0 → i1 @@ -4823,8 +4867,17 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr, # 裸名 typedef 调用: BYTEPTR(ptr1), HANDLE(val), CHARPTR(str) 等 # 用户通过 `from stdint import *` 导入 typedef 后,可直接用裸名做类型转换 # map_t_type 包含所有内置 typedef 名称(BYTEPTR/HANDLE/LPCSTR/size_t 等) + # 泛型类型参数转换: 泛型上下文(类特化/泛型函数)中 T(x) → 先解析 T 为具体 + # 类型名(如 "int")再走 map_t_type(Box[int].__init__ 的 self.value = T(v)、 + # combine[T1,T2] 的 T1(b) 依赖此路径) if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: - bare_ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, func_name) + bare_fn_name: str = HandlesType.resolve_generic_type_name(func_name) + bare_ty: llvmlite.LLVMType | t.CPtr = None + # 泛型上下文解析出的内建名(如 T→"double"):map_t_type 只认 t.CDouble + if string.strcmp(bare_fn_name, "double") == 0 or string.strcmp(bare_fn_name, "float") == 0: + bare_ty = llvmlite.Double(pool) + else: + bare_ty = HandlesType.map_t_type(pool, bare_fn_name) if bare_ty is not None and can == 1: bare_arg_node: ast.AST | t.CPtr = cargs.get(0) if bare_arg_node is not None: @@ -5403,6 +5456,31 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr, return _translate_struct_ctor( pool, builder, mod, struct_ty, func_name, cargs, can, trans) + # 裸名泛型类模板构造: Box(42) → 从实参推断类型实参 → 特化 → 构造 + # (TPC 参考: _HandleGenericClassNewLlvm;GenericTest Test4 Box(42)/Test5 + # Pair(10,20)/Test10 Counter(0) 依赖此路径。显式类型实参 list[int](mb) + # 走 translate_call 上方的 Subscript 分支,此处处理裸名 + 推断。) + if struct_ty is None and gen_ctor_entry is None and trans is not None: + if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: + template_cd_bare: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(func_name) + if template_cd_bare is not None and template_cd_bare.type_params is not None: + tp_bare: list[str] | t.CPtr = template_cd_bare.type_params + tp_count_bare: t.CSizeT = tp_bare.__len__() + if tp_count_bare > 0: + inferred_args_bare: list[str] | t.CPtr = list[str](pool, 8) + if inferred_args_bare is not None: + tpi_bare: t.CSizeT = 0 + for tpi_bare in range(tp_count_bare): + ta_bare: str = "int" + if tpi_bare < can: + ta_bare = _infer_generic_ctor_type_arg(pool, cargs.get(tpi_bare)) + inferred_args_bare.append(ta_bare) + spec_name_bare: str = HandlesClassDef._specialize_generic_class( + trans, func_name, inferred_args_bare) + if spec_name_bare is not None: + return _translate_generic_ctor_call( + pool, builder, mod, spec_name_bare, cl, trans) + # REnum 变体构造检测: ClassName.VariantName(args...) # 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体 # 必须在跨模块调用查找之前,否则 ClassName 会被误判为模块名 diff --git a/App/lib/core/Handles/HandlesFunctions.vp b/App/lib/core/Handles/HandlesFunctions.vp index 45435ae..1a79f27 100644 --- a/App/lib/core/Handles/HandlesFunctions.vp +++ b/App/lib/core/Handles/HandlesFunctions.vp @@ -401,7 +401,12 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr, resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans) if resolved is not None: - param_ty = resolved + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved pname: t.CChar | t.CPtr = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) @@ -523,7 +528,12 @@ def translate_function_def(trans: HT.Translator | t.CPtr, resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg_e.annotation, imported_modules, from_imports, trans) if resolved_e is not None: - param_ty_e = resolved_e + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved_e: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty_e = llvmlite.Ptr(pool, resolved_e) + case _: + param_ty_e = resolved_e pname_e: t.CChar | t.CPtr = pool.alloc(32) if pname_e is not None: viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) @@ -605,7 +615,12 @@ def translate_function_def(trans: HT.Translator | t.CPtr, resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg.annotation, imported_modules, from_imports, trans) if resolved is not None: - param_ty = resolved + # 裸类形参 → Ptr(struct)(对象即指针,与方法形参一致) + match resolved: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty = llvmlite.Ptr(pool, resolved) + case _: + param_ty = resolved pname: t.CChar | t.CPtr = pool.alloc(32) if pname is not None: viperlib.snprintf(pname, 32, "%%%s", arg.arg) @@ -632,6 +647,21 @@ def translate_function_def(trans: HT.Translator | t.CPtr, # 进入函数作用域(嵌套符号表) HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) + # PEP 695 泛型函数: def f[T](...) — 设置泛型上下文,类型参数映射到 "int" 兜底。 + # TPV 无泛型函数特化机制(类泛型走 _specialize_generic_class),泛型函数按普通 + # 函数编译;设置上下文使参数注解 T / 方法体中的 T(x) 转换可解析为 int。 + # (注意与类特化的 set_generic_context 一样是全局状态,需在退出作用域前清除。) + tp_names_fn: list[str] | t.CPtr = None + if fd.type_params is not None: + tp_names_fn = fd.type_params + tp_args_fn: list[str] | t.CPtr = list[str](pool, 8) + if tp_args_fn is not None: + tpn_fn: t.CSizeT = fd.type_params.__len__() + tpi_fn: t.CSizeT = 0 + for tpi_fn in range(tpn_fn): + tp_args_fn.append("int") + HandlesType.set_generic_context(tp_names_fn, tp_args_fn) + # 为参数创建 alloca if args_node is not None: ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) @@ -650,7 +680,12 @@ def translate_function_def(trans: HT.Translator | t.CPtr, resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( pool, arg2.annotation, imported_modules, from_imports, trans) if resolved2 is not None: - param_ty2 = resolved2 + # 与 add_param 保持一致:裸类形参 → Ptr(struct)(对象即指针) + match resolved2: + case llvmlite.LLVMType.Struct(_, _, _): + param_ty2 = llvmlite.Ptr(pool, resolved2) + case _: + param_ty2 = resolved2 alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) if alloca is not None: HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) @@ -765,6 +800,8 @@ def translate_function_def(trans: HT.Translator | t.CPtr, llvmlite.build_ret(func_builder, _zero_val) # 恢复模块级作用域(退出函数作用域) + if tp_names_fn is not None: + HandlesType.clear_generic_context() HandlesVar.exit_scope(trans.SymTab) trans._cur_func = old_func trans._cur_builder = old_builder diff --git a/App/lib/core/Handles/HandlesType.vp b/App/lib/core/Handles/HandlesType.vp index b557911..8ee35c2 100644 --- a/App/lib/core/Handles/HandlesType.vp +++ b/App/lib/core/Handles/HandlesType.vp @@ -1582,6 +1582,14 @@ def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, # class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr) # 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty* # 命名空间隔离:严格模式下仅解析可见的结构体 + # 跨模块同名类优先:当前模块自身定义了同名类时,用 find_struct_by_module + # 命中本模块的类(如 main.vp 的 G5Node 不再被 g5container.vp 预注册的 + # G5Node 顶掉,避免 alloca 用本模块类型、load 用他模块类型的混用)。 + # 本模块未定义时回退按裸名全局查找(import 来的类走此路径)。 + if trans is not None and trans.ModuleSha1 is not None: + own_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module(nm.id, trans.ModuleSha1) + if own_entry is not None and own_entry.Ty is not None: + return own_entry.Ty if HandlesStruct.is_struct_visible(nm.id) != 0: struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(nm.id) if struct_ty is not None: