fix(generic): 恢复泛型特化发射主路径
补回 _specialize_generic_class 的 deepcopy/改名/字段与方法 T 替换/_EmitClassLlvm 发射逻辑,list[...].__len__ 与 get 正常生成;源码不再支持 CPtr[...],统一写 T*;编译错误只由主进程输出一次。
This commit is contained in:
1 parent
09553401e7
commit
369afb5011
13 files changed
+413
-95
No files matched your search
@@ -235,6 +235,110 @@ class ClassHandle(BaseHandle):
|
||||
tn_bare_cls: str = tn.split('.')[-1] if '.' in tn else tn
|
||||
if self._HasClassDefinition(tn_bare_cls, Gen):
|
||||
class_type_names.add(tn_bare_cls)
|
||||
# 特化 AST:复制模板 → 清空 type_params → 改名为特化名,再整体替换
|
||||
# T(注解 + 方法体)。之后走与普通类完全相同的 _EmitClassLlvm 发射
|
||||
# (declare_only=False 时逐方法 _EmitFunctionLlvm 生成方法体)。
|
||||
SpecNode: ast.ClassDef = copy.deepcopy(Node)
|
||||
SpecNode.type_params = []
|
||||
SpecNode.name = spec_name
|
||||
for item in SpecNode.body:
|
||||
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
|
||||
if item.annotation:
|
||||
item.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(item.annotation, type_map, cptr_params)
|
||||
elif isinstance(item, ast.FunctionDef):
|
||||
for arg in item.args.args:
|
||||
if arg.annotation:
|
||||
arg.annotation = self.Trans.FunctionHandler._replace_type_in_annotation(arg.annotation, type_map, cptr_params)
|
||||
# class 类型参数加指针语义。T 替换后的真实形态可能是
|
||||
# Attribute 链('<sha1>.GNode' → Name('<sha1>').GNode,
|
||||
# 见 _make_replacement_node/_make_name_node),不是 ast.Name,
|
||||
# 故按裸名判据(_BareClassAnnotationName)判定;已经是指针
|
||||
# 下标(CPtr[T] / rawptr[T])的注解返回 None,不重复加层。
|
||||
raw_name: str | None = self._BareClassAnnotationName(arg.annotation)
|
||||
if raw_name is not None and raw_name in class_type_names:
|
||||
arg.annotation = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=arg.annotation,
|
||||
ctx=ast.Load(),
|
||||
)
|
||||
if item.returns:
|
||||
item.returns = self.Trans.FunctionHandler._replace_type_in_annotation(item.returns, type_map, cptr_params)
|
||||
# 返回类型也加指针语义(同一裸名判据,形态同上)
|
||||
raw_name: str | None = self._BareClassAnnotationName(item.returns)
|
||||
if raw_name is not None and raw_name in class_type_names:
|
||||
item.returns = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=item.returns,
|
||||
ctx=ast.Load(),
|
||||
)
|
||||
self.Trans.FunctionHandler._apply_type_map_to_body(item.body, type_map, cptr_params)
|
||||
saved_builder: ir.IRBuilder = Gen.builder
|
||||
saved_func: ir.Function = Gen.func
|
||||
saved_variables: dict = dict(Gen.variables) if Gen.variables else {}
|
||||
saved_direct_values: dict = dict(Gen._direct_values) if Gen._direct_values else {}
|
||||
saved_var_type_info: dict = dict(Gen.var_type_info) if Gen.var_type_info else {}
|
||||
saved_var_signedness: dict = dict(Gen.var_signedness) if Gen.var_signedness else {}
|
||||
saved_global_vars: set = set(Gen.global_vars) if Gen.global_vars else set()
|
||||
saved_var_scopes: list = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else []
|
||||
saved_block: ir.Block | None = None
|
||||
if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated:
|
||||
saved_block = Gen.builder.block
|
||||
# 切换 module_sha1 为泛型模板定义模块的 SHA1,
|
||||
# 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀,
|
||||
# 与调用端 _struct_sha1_map 查到的 SHA1 一致。
|
||||
template_sha1: str | None = template.get('sha1')
|
||||
if not template_sha1:
|
||||
# 模板注册表缺 sha1 时回退到"模板类定义模块"(_struct_sha1_map 即
|
||||
# 类名 → 定义模块表,Phase2 从各 .vpi 扫描构建):与声明端
|
||||
# DeclarationGenerator._get_type_str 的泛型前缀、调用点
|
||||
# Gen._struct_sha1_map[spec_name] 同一条规则源;否则 declare/define
|
||||
# 两侧前缀分裂(使用方模块 vs 模板模块)→ 跨模块 undefined symbol。
|
||||
template_sha1 = Gen._struct_sha1_map.get(ClassName)
|
||||
saved_gen_sha1: str | None = getattr(Gen, 'module_sha1', None)
|
||||
saved_trans_sha1: str | None = getattr(self.Trans, '_module_sha1', None)
|
||||
if template_sha1:
|
||||
Gen.module_sha1 = template_sha1
|
||||
self.Trans._module_sha1 = template_sha1
|
||||
try:
|
||||
self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only)
|
||||
except BaseException:
|
||||
# 失败时撤销预注册缓存:否则后续调用会把「特化到一半」当成已完成
|
||||
# (declare_only=False),方法体永远不会再补发,错误被伪装成
|
||||
# "没有 __len__ 方法 / Undefined method"。异常本身不吞,继续上抛。
|
||||
Gen._generic_class_specializations.pop(spec_key, None)
|
||||
raise
|
||||
finally:
|
||||
# 确保 Gen 状态恢复,即使 _EmitClassLlvm 抛出异常(异常本身不吞,
|
||||
# 由调用方记录到 Gen._generic_spec_error 或直接上抛)。
|
||||
Gen.builder = saved_builder
|
||||
if saved_block is not None and Gen.builder is not None:
|
||||
Gen.builder.position_at_end(saved_block)
|
||||
Gen.func = saved_func
|
||||
Gen.variables = saved_variables
|
||||
Gen._direct_values = saved_direct_values
|
||||
Gen.var_type_info = saved_var_type_info
|
||||
Gen.var_signedness = saved_var_signedness
|
||||
Gen.global_vars = saved_global_vars
|
||||
self.Trans.VarScopes = saved_var_scopes
|
||||
# 恢复原始 module_sha1
|
||||
Gen.module_sha1 = saved_gen_sha1
|
||||
self.Trans._module_sha1 = saved_trans_sha1
|
||||
Gen._generic_class_specializations[spec_key] = (spec_name, declare_only)
|
||||
# 缓存 type_args/type_names,供后续 declare_only=False 完整特化补发方法体使用
|
||||
# (如 _HandleMethodCallLlvm 中发现方法未定义时触发)
|
||||
if not hasattr(Gen, '_generic_class_spec_type_info'):
|
||||
Gen._generic_class_spec_type_info = {}
|
||||
Gen._generic_class_spec_type_info[spec_key] = (list(type_args), list(type_names) if type_names else None)
|
||||
if not hasattr(self.Trans, '_generic_class_specializations'):
|
||||
self.Trans._generic_class_specializations = {}
|
||||
self.Trans._generic_class_specializations[spec_key] = spec_name
|
||||
# 用模板定义模块的 SHA1 注册到 _struct_sha1_map,与方法定义端一致
|
||||
if template_sha1:
|
||||
Gen._struct_sha1_map[spec_name] = template_sha1
|
||||
elif hasattr(self.Trans, '_module_sha1') and self.Trans._module_sha1:
|
||||
Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1
|
||||
return spec_name
|
||||
|
||||
def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None:
|
||||
"""解析基类名称的类型种类
|
||||
|
||||
|
||||
@@ -3068,8 +3068,10 @@ class ExprCallHandle(BaseHandle):
|
||||
base_name, cached_type_args, Gen,
|
||||
type_names=cached_type_names, declare_only=False
|
||||
)
|
||||
except Exception:
|
||||
# 失败时恢复 declare_only 标记,避免后续调用跳过补发
|
||||
except Exception as _spec_err:
|
||||
# 不静默吞特化异常:暴露到 Gen._generic_spec_error(Undefined method /
|
||||
# len 失败时随报文输出),并恢复 declare_only 标记避免后续调用跳过补发。
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
Gen._generic_class_specializations[spec_key] = (cached_name, True)
|
||||
Gen.builder = _saved_builder
|
||||
Gen.func = _saved_func
|
||||
|
||||
@@ -181,8 +181,8 @@ class ExprUtils:
|
||||
# 泛型特化方法尚未生成时,先补发特化
|
||||
try:
|
||||
self.Trans.ExprCallHandle._try_complete_generic_specialization(ClassName, op_name, Gen)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as _spec_err:
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
FullMethodName = f'{ClassName}.{op_name}'
|
||||
if not Gen._has_function(FullMethodName):
|
||||
FullMethodName = f'{ClassName}.{op_name}__'
|
||||
@@ -224,8 +224,8 @@ class ExprUtils:
|
||||
# 缓存机制会从 declare_only 升级为完整特化),补发后重新检查
|
||||
try:
|
||||
self.Trans.ExprCallHandle._try_complete_generic_specialization(best_candidates[0], op_name, Gen)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as _spec_err:
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
_fn2: str = f'{best_candidates[0]}.{op_name}' if Gen._has_function(f'{best_candidates[0]}.{op_name}') else f'{best_candidates[0]}.{op_name}__'
|
||||
_f2: Any = Gen._get_function(_fn2)
|
||||
if _f2 is not None and getattr(_f2, 'blocks', []):
|
||||
|
||||
@@ -591,8 +591,14 @@ class FunctionHandle(BaseHandle):
|
||||
# 避免过早触发完整特化(此时 MemManager.alloc 可能尚未注册,
|
||||
# 导致 __new__ 的 pool.alloc(48) 解析失败,IR 块未终止)。
|
||||
# 完整特化由后续类实例化(L3688/L3753)触发 declare_only=False。
|
||||
spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class(
|
||||
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
|
||||
try:
|
||||
spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class(
|
||||
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
|
||||
except Exception as _spec_err:
|
||||
# 不静默吞特化异常:记录到 Gen._generic_spec_error 后再
|
||||
# 交给外层返回类型回退(否则只剩一个错误的 CInt 返回类型)。
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
raise
|
||||
if spec_name2 and spec_name2 in Gen.structs:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2)
|
||||
@@ -995,30 +1001,29 @@ class FunctionHandle(BaseHandle):
|
||||
elif isinstance(node.func, ast.Attribute):
|
||||
if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map:
|
||||
replacement: str = type_map[node.func.value.id]
|
||||
# 指针类型参数(如 list[CPtr[AST]] 中的 T)在表达式上下文中
|
||||
# 需替换为 `CPtr[AST]` 下标,使 __sizeof__ 等处理器能正确识别
|
||||
# 指针语义并直接返回 8,避免触发 struct 加载和重入编译
|
||||
# 指针类型参数(如 list[CPtr[AST]] 中的 T):表达式里 T 的唯一
|
||||
# 用法是 `T.__sizeof__()`,指针大小恒为 8。替换成**裸 CPtr**
|
||||
# (而不是 CPtr[<mangled 串>]):mangled 串含 '.'/'*',既不是
|
||||
# 合法 Name,也会让 __sizeof__ 的 Subscript 分支(只认泛型切片)
|
||||
# 落空后把 CPtr 当变量求值 → "未定义名称: 'CPtr'"。
|
||||
if cptr_params and node.func.value.id in cptr_params:
|
||||
node.func.value = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=self._make_name_node(replacement),
|
||||
ctx=ast.Load()
|
||||
)
|
||||
node.func.value = ast.Name(id='CPtr', ctx=ast.Load())
|
||||
else:
|
||||
node.func.value = self._make_name_node(replacement)
|
||||
else:
|
||||
self._apply_type_map_to_expr(node.func.value, type_map, cptr_params)
|
||||
elif isinstance(node.func, ast.Subscript):
|
||||
# `T*(expr)` / `list[T](...)`:被调者/转换目标的切片也要替换。
|
||||
self._apply_type_map_to_expr(node.func, type_map, cptr_params)
|
||||
for arg in node.args:
|
||||
self._apply_type_map_to_expr(arg, type_map, cptr_params)
|
||||
elif isinstance(node, ast.Attribute):
|
||||
if isinstance(node.value, ast.Name) and node.value.id in type_map:
|
||||
replacement: str = type_map[node.value.id]
|
||||
if cptr_params and node.value.id in cptr_params:
|
||||
node.value = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=self._make_name_node(replacement),
|
||||
ctx=ast.Load()
|
||||
)
|
||||
# 同上:指针类型参数的表达式用法(T.__sizeof__ 等)只需
|
||||
# "指针语义",裸 CPtr 即指针大小 8;不要拼 mangled 串。
|
||||
node.value = ast.Name(id='CPtr', ctx=ast.Load())
|
||||
else:
|
||||
node.value = ast.Name(id=replacement, ctx=ast.Load())
|
||||
else:
|
||||
@@ -1041,7 +1046,14 @@ class FunctionHandle(BaseHandle):
|
||||
self._apply_type_map_to_expr(node.orelse, type_map, cptr_params)
|
||||
elif isinstance(node, ast.Subscript):
|
||||
self._apply_type_map_to_expr(node.value, type_map, cptr_params)
|
||||
self._apply_type_map_to_expr(node.slice, type_map, cptr_params)
|
||||
# `T*(expr)` 的指针转换在 AST 里是 Call(func=Subscript(CPtr, T)):
|
||||
# 切片上的 T 必须整体替换成 `_make_replacement_node` 的产物(如
|
||||
# CPtr[<sha1>.AST]),不能走 Name 分支直接改 id(mangled 串含 '.'/'*'
|
||||
# 不是合法标识符),否则会留下裸 T → 生成幻影结构体 %"<sha1>.T"。
|
||||
if isinstance(node.slice, ast.Name) and node.slice.id in type_map:
|
||||
node.slice = self._make_replacement_node(type_map[node.slice.id])
|
||||
else:
|
||||
self._apply_type_map_to_expr(node.slice, type_map, cptr_params)
|
||||
elif isinstance(node, ast.Name):
|
||||
if node.id in type_map:
|
||||
node.id = type_map[node.id]
|
||||
@@ -1504,8 +1516,14 @@ class FunctionHandle(BaseHandle):
|
||||
# 返回类型解析只需 struct 定义,不需方法体;使用 declare_only=True
|
||||
# 避免过早触发完整特化(此时 MemManager.alloc 可能尚未注册,
|
||||
# 导致 __new__ 的 pool.alloc(48) 解析失败,IR 块未终止)。
|
||||
spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class(
|
||||
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
|
||||
try:
|
||||
spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class(
|
||||
ret_class, ret_type_args, Gen, type_names=ret_type_names, declare_only=True)
|
||||
except Exception as _spec_err:
|
||||
# 不静默吞特化异常:记录到 Gen._generic_spec_error 后再
|
||||
# 交给外层返回类型回退(否则只剩一个错误的 CInt 返回类型)。
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
raise
|
||||
if spec_name2 and spec_name2 in Gen.structs:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CStruct(name=spec_name2)
|
||||
|
||||
@@ -4256,7 +4256,10 @@ class ImportHandle(BaseHandle):
|
||||
gc_spec: str | None = self.Trans.ClassHandler._specialize_generic_class(
|
||||
gc_base, gc_type_args, Gen, type_names=gc_type_names,
|
||||
declare_only=True)
|
||||
except Exception:
|
||||
except Exception as _spec_err:
|
||||
# 不静默吞特化异常:记录现场,供后续 Undefined method /
|
||||
# len 失败路径把真因带进报错。
|
||||
Gen._generic_spec_error = f'{type(_spec_err).__name__}: {_spec_err}'
|
||||
gc_spec = None
|
||||
Gen.module_sha1 = saved_module_sha1
|
||||
self.Trans._module_sha1 = saved_trans_sha1
|
||||
|
||||
@@ -4,7 +4,8 @@ if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode)
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode,
|
||||
MangleTypeArgByRegistry)
|
||||
from lib.core import TypeSystem
|
||||
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
|
||||
import vast as ast
|
||||
@@ -67,7 +68,7 @@ class HandlesTypeMerge(BaseHandle):
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字")
|
||||
Result = self._GetCTypeInfoInternal(Node)
|
||||
if isinstance(Result, CTypeInfo):
|
||||
Info = Result
|
||||
@@ -83,7 +84,7 @@ class HandlesTypeMerge(BaseHandle):
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字")
|
||||
LineNum = getattr(Node, 'lineno', None)
|
||||
|
||||
if getattr(self.Trans, 'DebugFile', None):
|
||||
@@ -119,6 +120,9 @@ class HandlesTypeMerge(BaseHandle):
|
||||
Info.BaseType = TypeSystem.CVoid
|
||||
return Info
|
||||
if BuiltinCls == TypeSystem.CPtr:
|
||||
# 裸 CPtr 仅来自内部类型字符串;源码注解写 CPtr / CPtr[...]
|
||||
# 已在解析层拒绝(提示改写 T*)。内部 Subscript(CPtr, T)
|
||||
# 仍由后续 Subscript 分支解析。
|
||||
Info.PtrCount = 1
|
||||
Info.BaseType = TypeSystem.CVoid
|
||||
return Info
|
||||
@@ -800,13 +804,18 @@ class HandlesTypeMerge(BaseHandle):
|
||||
arg_parts: list[str] = []
|
||||
for elt in slice_node.elts:
|
||||
slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(elt)
|
||||
arg_parts.append(slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(elt))
|
||||
_raw_arg: str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(elt)
|
||||
# 与 _mangle_generic_class_name 同口径(CInt → i32、
|
||||
# CFloat64T → f64):否则注解侧拼出 list[CInt],
|
||||
# 实际特化名却是 list[i32] → 同名结构体分裂。
|
||||
arg_parts.append(MangleTypeArgByRegistry(_raw_arg))
|
||||
# 必须用 '][' 分隔以匹配 _mangle_generic_class_name 的格式
|
||||
# (class_name + '[' + ']['.join(mangled_args) + ']')
|
||||
type_arg_str = ']['.join(arg_parts)
|
||||
else:
|
||||
slice_res = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node)
|
||||
type_arg_str = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node)
|
||||
_raw_arg = slice_res[0] if slice_res else self.Trans.ExprCallHandle._resolve_type_arg_str(slice_node)
|
||||
type_arg_str = MangleTypeArgByRegistry(_raw_arg)
|
||||
full_spec_name: str = f'{value_node.id}[{type_arg_str}]'
|
||||
ResultInfo.BaseType = TypeSystem.CStruct(name=full_spec_name)
|
||||
ResultInfo.Name = full_spec_name
|
||||
@@ -915,4 +924,4 @@ class HandlesTypeMerge(BaseHandle):
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字")
|
||||
@@ -2141,6 +2141,7 @@ _ANNOTATION_MARKER_ALIASES: dict[str, str] = {
|
||||
}
|
||||
|
||||
# 指针/引用下标的 base 名:注解里出现这些名字即表示"指针层"(等价旧 CPtr 标记)。
|
||||
# CPtr 仅作为内部表示(`T*` 脱糖产物);源码写 CPtr[...] 已在解析层拒绝。
|
||||
_POINTER_SUBSCRIPT_NAMES: frozenset[str] = frozenset({
|
||||
'CPtr', 'rawptr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr',
|
||||
})
|
||||
@@ -2152,7 +2153,7 @@ def RejectTypeUnionAnnotation(node: ast.AST | None) -> None:
|
||||
Line: int = getattr(node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字")
|
||||
|
||||
|
||||
def AnnotationContainsMarker(node: ast.AST, MarkerName: str) -> bool:
|
||||
|
||||
@@ -145,7 +145,7 @@ class TypeAnnotationResolver:
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
f"类型注解只能是单一类型:指针请写 T*(如 int*),修饰符请用关键字")
|
||||
if isinstance(Node, ast.Constant):
|
||||
Info: CTypeInfo = TypeAnnotationResolver._from_node_constant(Node, SymbolTable)
|
||||
elif isinstance(Node, ast.Name):
|
||||
@@ -575,6 +575,8 @@ class TypeAnnotationResolver:
|
||||
TypeObj = getattr(TypeSystem, TypeName, None)
|
||||
if isinstance(TypeObj, type) and issubclass(TypeObj, TypeSystem.CType) and TypeObj is not TypeSystem.CType:
|
||||
if TypeObj == TypeSystem.CPtr:
|
||||
# CPtr 名仅来自内部类型字符串(builtins typedef 值等);源码
|
||||
# 注解写 CPtr / CPtr[...] 已在解析层拒绝,提示改写为 T*。
|
||||
Result: CTypeInfo = CTypeInfo()
|
||||
Result.PtrCount = 1
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
@@ -790,6 +792,8 @@ class TypeAnnotationResolver:
|
||||
MarkerName = base.id
|
||||
elif isinstance(base, ast.Attribute):
|
||||
MarkerName = base.attr
|
||||
# 指针/引用下标:CPtr 仅由 `T*` 脱糖产生(内部表示),源码写 CPtr[...]
|
||||
# 已在解析层拒绝;rawptr / CRef / CTempRef / CArrayPtr / CAutoPtr 仍可直写。
|
||||
if MarkerName in ('CPtr', 'rawptr'):
|
||||
SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.slice, SymbolTable)
|
||||
Result: CTypeInfo = CTypeInfo()
|
||||
@@ -980,7 +984,7 @@ class TypeAnnotationResolver:
|
||||
Where: str = f'{File}:{Line}:{Col}' if File else f'第 {Line} 行第 {Col} 列'
|
||||
raise TypeError(
|
||||
f"[TPC] 类型注解不支持模块前缀 \"{FullName}\"({Where})。"
|
||||
f"请改写为 \"{TypeName}\";指针写 CPtr[T] / rawptr[T]。")
|
||||
f"请改写为 \"{TypeName}\";指针写 T*(如 int*)/ rawptr[T]。")
|
||||
# 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window
|
||||
if ModulePath:
|
||||
resolved: bool = False
|
||||
|
||||
Reference in new issue
Block a user