From 326977594581c5ddb5ca9a2d2d9b71d699312411 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 18 Oct 2026 13:08:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(tpc):=20=E7=A6=81=E6=AD=A2=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E8=81=94=E5=90=88=20T1=20|=20T2=20=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 四类类型注解入口统一调用 RejectTypeUnion:任意 T1 | T2 直接报错,报文含行号与 CPtr[T]/rawptr[T]、const/volatile/static/export/extern 替代写法;仅保留内建修饰标记与类型的组合。 --- lib/Projectrans/DeclarationGenerator.py | 4 ++- lib/core/Handles/HandlesTypeMerge.py | 3 +- lib/core/LLVMTypeMapper.py | 3 +- lib/core/SymbolUtils.py | 45 +++++++++++++++++++++++++ lib/core/TypeAnnotationResolver.py | 3 +- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index 4918840..12ffba7 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -10,7 +10,7 @@ import llvmlite.ir as ir from lib.core import TypeSystem from lib.core.TypeSystem import CTypeRegistry from lib.core.SymbolUtils import ( - IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode, IsCPtrNode, + IsListAnnotation, AnnotationContainsName, RejectTypeUnion, IsCPtrSubscriptNode, IsCPtrNode, IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr, EnumClassIntWidth, ClassHasFuncLevelCVTable) @@ -1187,6 +1187,8 @@ class DeclarationGenerator: if annotation is None: return 'i8*' + RejectTypeUnion(annotation) + non_struct_types: set[str] = {'list', 'dict', 'tuple', 'set', 'array', 'CArray', 'rawarray'} if isinstance(annotation, ast.Name): diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index 36562cc..746ef0f 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -5,7 +5,7 @@ if TYPE_CHECKING: from typing import List from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo from lib.core.SymbolUtils import ( - IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, + IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, RejectTypeUnion, DesugarPtrSubscriptToUnion) from lib.core import TypeSystem import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib) @@ -27,6 +27,7 @@ class HandlesTypeMerge(BaseHandle): def GetCTypeInfo(self, Node: ast.AST) -> CTypeInfo: """获取 CTypeInfo 对象""" + RejectTypeUnion(Node) Result = self._GetCTypeInfoInternal(Node) if isinstance(Result, CTypeInfo): return Result diff --git a/lib/core/LLVMTypeMapper.py b/lib/core/LLVMTypeMapper.py index 13d428e..93ce774 100644 --- a/lib/core/LLVMTypeMapper.py +++ b/lib/core/LLVMTypeMapper.py @@ -19,7 +19,7 @@ if TYPE_CHECKING: from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap from lib.core.SymbolUtils import ( - IsListAnnotation, IsCPtrNode, IsCPtrSubscriptNode, + IsListAnnotation, RejectTypeUnion, IsCPtrNode, IsCPtrSubscriptNode, IsRawPtrSubscriptNode, EnumIntWidth, ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab) from lib.core import TypeSystem as _t @@ -121,6 +121,7 @@ class LLVMTypeMapper: if node is None: self._symtab.diagnostics.warn('', 0, "类型注解为 None,回退到 i32") return 'i32' + RejectTypeUnion(node) if isinstance(node, ast.Name): return self._resolve_name(node) elif isinstance(node, ast.Attribute): diff --git a/lib/core/SymbolUtils.py b/lib/core/SymbolUtils.py index 43a73a8..d2491ae 100644 --- a/lib/core/SymbolUtils.py +++ b/lib/core/SymbolUtils.py @@ -2160,6 +2160,51 @@ def RequireNameDefined(Gen: object, Trans: object, Node: object, Name: str) -> N ) +# 类型注解中允许出现在 `|` 一侧的内建修饰标记。除此之外的任何 `T1 | T2` +# 都视为「类型联合」并直接拒绝:类型注解只能是单一类型。 +_UNION_MARKER_NAMES: frozenset[str] = frozenset({ + 'CConst', 'CVolatile', 'CExport', 'CExtern', 'CStatic', 'CInline', 'State', + 'CDefine', 'CTypedef', 'CPtr', 'CArrayPtr', 'CAutoPtr', 'CRef', 'CTempRef', + 'BigEndian', 'LittleEndian', 'Bit', +}) + + +def _IsUnionMarkerNode(node: ast.AST) -> bool: + """节点是否为内建修饰标记(裸名、attr.* 或带调用括号的标记)。""" + if isinstance(node, ast.Name): + return node.id in _UNION_MARKER_NAMES + if isinstance(node, ast.Attribute): + cur: ast.AST = node + while isinstance(cur, ast.Attribute): + cur = cur.value + return isinstance(cur, ast.Name) and cur.id == 'attr' + if isinstance(node, ast.Call): + return _IsUnionMarkerNode(node.func) + return False + + +def _ContainsUnionMarker(node: ast.AST) -> bool: + if _IsUnionMarkerNode(node): + return True + if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + return _ContainsUnionMarker(node.left) or _ContainsUnionMarker(node.right) + return False + + +def RejectTypeUnion(Annotation: ast.AST | None) -> None: + """拒绝 `T1 | T2` 类型联合;只允许「单一类型 | 内建修饰标记」。""" + if not (isinstance(Annotation, ast.BinOp) and isinstance(Annotation.op, ast.BitOr)): + return + if _ContainsUnionMarker(Annotation): + return + Line: int = getattr(Annotation, 'lineno', 0) or 0 + raise TypeError( + f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行)。" + f"类型注解只能是单一类型:指针请写 CPtr[T] / rawptr[T];" + f"const / volatile / static / export / extern 请使用对应关键字。" + ) + + def AnnotationContainsMarker(node: ast.AST, MarkerName: str) -> bool: """注解 AST 中是否出现指定内建标记名(裸名,或属性形态的尾名)。""" if isinstance(node, ast.Name): diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index 92fa6de..750a428 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -9,7 +9,7 @@ from typing import TYPE_CHECKING from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper from lib.core.ConstEvaluator import ConstEvaluator from lib.core.SymbolUtils import ( - IsListAnnotation, + IsListAnnotation, RejectTypeUnion, ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab) from lib.core import TypeSystem from lib.constants.config import mode as _config_mode @@ -91,6 +91,7 @@ class TypeAnnotationResolver: Node: AST 节点(如 ast.Name, ast.Attribute 等) SymbolTable: 符号表字典 """ + RejectTypeUnion(Node) if isinstance(Node, ast.Constant): return TypeAnnotationResolver._from_node_constant(Node, SymbolTable) if isinstance(Node, ast.Name):