refactor(tpc): 删除类型联合语法并将修饰迁移为 AST 字段
类型注解不再接受任何 T1 | T2;const/volatile/static/export/extern/inline/define/typedef/__attribute__/BigEndian/LittleEndian/Bit 改为注解节点字段 Markers/Attributes/ByteOrder/BitWidth;指针与引用改为 CPtr[T]/CRef[T]/CTempRef[T]/CArrayPtr[T]/CAutoPtr[T];Python 与 vast_c 两套解析器、类型解析与声明端同步;C 扩展早于 vast_c.c 时自动回退纯 Python 解析器。
This commit is contained in:
1 parent
3269775945
commit
660a15bef8
19 files changed
+1312
-1576
No files matched your search
@@ -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, RejectTypeUnion, IsCPtrSubscriptNode, IsCPtrNode,
|
||||
IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode,
|
||||
IsRawPtrSubscriptNode, IsPtrSubscriptNode, ResolveGenericTypeArgStr,
|
||||
EnumClassIntWidth, ClassHasFuncLevelCVTable)
|
||||
|
||||
@@ -94,20 +94,16 @@ class DeclarationGenerator:
|
||||
self._DefineConstants[var_name] = node.value.value
|
||||
elif node.value and isinstance(node.value, ast.Name):
|
||||
self._DefineConstants[var_name] = node.value.id
|
||||
is_typedef: bool = False
|
||||
if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef':
|
||||
is_typedef = True
|
||||
elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef':
|
||||
is_typedef = True
|
||||
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef':
|
||||
is_typedef = True
|
||||
elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Name) and node.annotation.left.id == 'CTypedef':
|
||||
is_typedef = True
|
||||
if is_typedef:
|
||||
if node.value:
|
||||
self.typedef_map[var_name] = node.value
|
||||
elif isinstance(node.annotation, ast.BinOp) and node.annotation.right:
|
||||
self.typedef_map[var_name] = node.annotation.right
|
||||
Markers: tuple[str, ...] = tuple(getattr(node, 'Markers', None) or ()) + tuple(
|
||||
getattr(node.annotation, 'Markers', None) or ())
|
||||
is_typedef: bool = 'typedef' in Markers
|
||||
if not is_typedef:
|
||||
if isinstance(node.annotation, ast.Attribute) and getattr(node.annotation, 'attr', '') == 'CTypedef':
|
||||
is_typedef = True
|
||||
elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef':
|
||||
is_typedef = True
|
||||
if is_typedef and node.value:
|
||||
self.typedef_map[var_name] = node.value
|
||||
|
||||
lines: list[str] = []
|
||||
lines.append('; ModuleID = "transpyc_decl"')
|
||||
@@ -235,35 +231,39 @@ class DeclarationGenerator:
|
||||
|
||||
def _is_export_func(self, node: ast.FunctionDef) -> bool:
|
||||
"""检查函数是否标记为 CExport"""
|
||||
Markers: tuple[str, ...] = getattr(node, 'Markers', None) or ()
|
||||
if 'export' in Markers or 'state' in Markers:
|
||||
return True
|
||||
if not node.returns:
|
||||
return False
|
||||
return self._check_annotation_for_export(node.returns)
|
||||
|
||||
def _check_annotation_for_export(self, annotation: ast.AST | None) -> bool:
|
||||
"""递归检查类型注解中是否包含 CExport 或 State"""
|
||||
return bool(annotation) and (AnnotationContainsName(annotation, 'CExport') or AnnotationContainsName(annotation, 'State'))
|
||||
"""检查类型注解是否带 export / state 标记"""
|
||||
if annotation is None:
|
||||
return False
|
||||
Markers: tuple[str, ...] = getattr(annotation, 'Markers', None) or ()
|
||||
if 'export' in Markers or 'state' in Markers:
|
||||
return True
|
||||
return AnnotationContainsName(annotation, 'CExport') or AnnotationContainsName(annotation, 'State')
|
||||
|
||||
def _generate_global_decl(self, node: ast.AnnAssign) -> str | None:
|
||||
"""生成全局变量声明"""
|
||||
if not isinstance(node.target, ast.Name):
|
||||
return None
|
||||
var_name: str = node.target.id
|
||||
# CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global。
|
||||
# `define X: T = V` 会展开为注解 `T | CDefine`,故判据必须能识别**联合形态**——
|
||||
# 原判据只认裸 `CDefine`(注解为单个 Attribute),联合注解会漏判 →
|
||||
# stub 出现 `@X = external global i32` → 其他模块引用它时变成未定义符号(链接失败),
|
||||
# 且会遮住跨模块 CDefine 常量回退(同名全局优先于常量)。与 _check_annotation_for_export
|
||||
# 一样用递归判据。
|
||||
if AnnotationContainsName(node.annotation, 'CDefine'):
|
||||
# CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global,
|
||||
# 否则其他模块引用它时变成未定义符号(链接失败)。标记由 Markers 字段承载。
|
||||
Markers: tuple[str, ...] = tuple(getattr(node, 'Markers', None) or ()) + tuple(
|
||||
getattr(node.annotation, 'Markers', None) or ())
|
||||
if 'define' in Markers or AnnotationContainsName(node.annotation, 'CDefine'):
|
||||
return None
|
||||
if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef':
|
||||
if 'typedef' in Markers:
|
||||
return None
|
||||
if isinstance(node.annotation, ast.Attribute) and getattr(node.annotation, 'attr', '') == 'CTypedef':
|
||||
return None
|
||||
if isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef':
|
||||
return None
|
||||
if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef':
|
||||
return None
|
||||
if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Name) and node.annotation.left.id == 'CTypedef':
|
||||
return None
|
||||
if isinstance(node.annotation, ast.List):
|
||||
for elt in node.annotation.elts:
|
||||
if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'):
|
||||
@@ -1108,35 +1108,13 @@ class DeclarationGenerator:
|
||||
# 其他未知类型保守估算
|
||||
return 8
|
||||
|
||||
@staticmethod
|
||||
def _ptr_level_of(type_str: str) -> int:
|
||||
"""统计类型字符串尾部的指针层数('i8***' → 3,'i32' → 0)"""
|
||||
return len(type_str) - len(type_str.rstrip('*'))
|
||||
|
||||
def _merge_cptr_subscript(self, base_type: str, cptr_sub_type: str) -> str:
|
||||
"""base | CPtr[T] → Ptr^N(base_type),N = CPtr[T] 段自身指针层数。
|
||||
|
||||
与定义侧 VPC TypeGenResolve.vp:2610-2639 同口径:数 CPtr 侧已解析类型的
|
||||
外层 Ptr 嵌套层 N(TypeGenResolve.vp:2616-2632),再给另一侧**纯外包**
|
||||
N 层 Ptr(TypeGenResolve.vp:2633-2639,对 struct 基类型亦不吸收)。
|
||||
与 LLVMTypeMapper._resolve_bitor 的 IsCPtrSubscriptNode 分支(_add_pointer_levels
|
||||
逐层追加)同口径,对同一批形态两处结果一致。
|
||||
注:裸 | CPtr(非下标标记)仍走上方的 %"..."* 吸收分支,与本节无关。
|
||||
"""
|
||||
return base_type + '*' * self._ptr_level_of(cptr_sub_type)
|
||||
|
||||
def _ptr_subscript_type_str(self, annotation: ast.Subscript) -> str:
|
||||
"""指针下标(rawptr[T] / CPtr[T] / 裸名 CPtr[T],判据见
|
||||
SymbolUtils.IsPtrSubscriptNode)→ LLVM 类型串。
|
||||
|
||||
与定义端同源:SymbolUtils.DesugarPtrSubscriptToUnion 把三者折叠为等价
|
||||
联合写法 `T | CPtr` 后交 HandlesTypeMerge.MergeTypes,指针层数由
|
||||
_MergeAllComponentTypes 的"struct 基类型吸收一层 CPtr"决定 —— 裸类引用
|
||||
的非 embedded 形式本身即指针('%"sha1.X"*'),再包一层会被吸收 → 结果
|
||||
就是该指针本身;其余类型(标量 / 已是指针的 typedef / 泛型容器特化 /
|
||||
联合写法 / 嵌套指针下标)逐层外包。rawptr[...] 与 CPtr[...] 共用本条
|
||||
规则(此前 CPtr[list[X]] 在此得 list[X]**、rawptr[list[X]] 得
|
||||
list[X]*,同一指针语义两种结果)。
|
||||
裸类引用的非 embedded 形式本身即指针('%"sha1.X"*'),再包一层会被
|
||||
吸收 → 结果就是该指针本身;其余类型(标量 / 已是指针的 typedef /
|
||||
泛型容器特化 / 嵌套指针下标)逐层外包。
|
||||
"""
|
||||
inner: ast.AST = annotation.slice
|
||||
inner_type: str = self._get_type_str(inner)
|
||||
@@ -1149,36 +1127,12 @@ class DeclarationGenerator:
|
||||
def _is_bare_class_ref_annotation(self, inner: ast.AST, inner_type: str) -> bool:
|
||||
"""节点是否为"裸类引用"(本身即指针 → 吸收一层 CPtr)。
|
||||
|
||||
与 _get_type_str 的既有约定一致:类引用的**非** embedded 形式本身就是
|
||||
指针('%"sha1.X"*'),所以 `AST | CPtr` 合并后仍是该指针(定义端
|
||||
_MergeAllComponentTypes 的 struct 吸收)。联合写法(ast.BinOp)与指针
|
||||
下标(rawptr[...] / CPtr[...])不是裸类引用——它们已自带指针层数,
|
||||
须逐层外包(rawptr[Node] | CPtr → Node**、ast.AST | CPtr | CPtr
|
||||
→ AST**,与定义端整体拉平后只吸收一次 CPtr 一致)。
|
||||
|
||||
**例外:纯装饰器标记联合**。`CExtern | X` / `CExport | X` / `State | X`
|
||||
(vpi 记录的模块级全局就是这种写法,见 lib.Phase.Phase1.__init__.vpi 的
|
||||
`_mbuddy: CExtern | memhub.MemBuddy | CPtr`)里标记侧展开为**空串**
|
||||
(CTypeRegistry.NameToLLVM('CExtern') == ''),该联合语义上仍是 X 这一个
|
||||
裸类引用,故 `CExtern | X | CPtr` 必须与 `X | CPtr` 同判(吸收)——
|
||||
对齐 VPC TypeGenResolve 的第 3 条语义「ActualType | DecoratorMarker →
|
||||
ActualType」。漏此判据时联合被当成"已自带指针层数的左值"而多外包一层:
|
||||
声明端 `%"sha1.X"**` 与定义端 `%"sha1.X"*` 差一层,消费模块里
|
||||
`self.__mbuddy__ = _mbuddy` 之类的赋值即报"层数不同"fail-fast。
|
||||
类引用的**非** embedded 形式本身就是指针('%"sha1.X"*'),再包一层
|
||||
指针会被吸收;指针下标(rawptr[...] / CPtr[...])已自带指针层数,
|
||||
须逐层外包(CPtr[Node] → Node**)。
|
||||
"""
|
||||
if not inner_type:
|
||||
return False
|
||||
if isinstance(inner, ast.BinOp):
|
||||
if not isinstance(inner.op, ast.BitOr):
|
||||
return False
|
||||
LeftType: str = self._get_type_str(inner.left)
|
||||
RightType: str = self._get_type_str(inner.right)
|
||||
# 恰一侧是纯装饰器标记(展开为空/void)⇒ 类型全部来自另一侧,按另一侧判
|
||||
if LeftType in ('', 'void') and RightType not in ('', 'void'):
|
||||
return self._is_bare_class_ref_annotation(inner.right, RightType)
|
||||
if RightType in ('', 'void') and LeftType not in ('', 'void'):
|
||||
return self._is_bare_class_ref_annotation(inner.left, LeftType)
|
||||
return False
|
||||
if isinstance(inner, ast.Subscript):
|
||||
return not (IsRawPtrSubscriptNode(inner) or IsCPtrSubscriptNode(inner))
|
||||
return inner_type.startswith('%') and inner_type.endswith('*')
|
||||
@@ -1187,7 +1141,11 @@ class DeclarationGenerator:
|
||||
if annotation is None:
|
||||
return 'i8*'
|
||||
|
||||
RejectTypeUnion(annotation)
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
Line: int = getattr(annotation, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
|
||||
non_struct_types: set[str] = {'list', 'dict', 'tuple', 'set', 'array', 'CArray', 'rawarray'}
|
||||
|
||||
@@ -1318,71 +1276,10 @@ class DeclarationGenerator:
|
||||
sname: str = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}'
|
||||
return f'{sname}*'
|
||||
return 'i32'
|
||||
elif isinstance(annotation, ast.BinOp):
|
||||
left_type: str = self._get_type_str(annotation.left, embedded=embedded)
|
||||
right_type: str = self._get_type_str(annotation.right, embedded=embedded)
|
||||
if left_type in ('', 'void'):
|
||||
return right_type if right_type not in ('', 'void') else (left_type or right_type)
|
||||
if right_type in ('', 'void'):
|
||||
return left_type
|
||||
# CPtr (i8*) 与 left 合并:对齐 Phase 2 _MergeAllComponentTypes 的
|
||||
# "first CPtr absorption" 语义:struct | CPtr → struct*(吸收,struct 变量默认是指针)。
|
||||
# 但对于本身已是指针的类型(如 bytes=str=i8*),bytes | CPtr → i8**(不吸收)。
|
||||
# 例外:LLVM 聚合数组([N x T],字符串以 '[' 开头)不可再外包指针层 → i8*。
|
||||
# 注:具名泛型特化(%"mod.list[X]"*)**不**走此回退——stub 已由
|
||||
# _collect_undefined_type_decls 为其补 opaque 声明,保留名字才能与 define 端
|
||||
# 的 %"mod.list[ast.ASTptr]"* 逐字一致(原 `'[' in left_type` 会把
|
||||
# list[X] | CPtr 一并退化成 i8*,与定义端 %"mod.list[X]"* 不一致)。
|
||||
if right_type == 'i8*':
|
||||
if left_type[:1] == '[':
|
||||
return 'i8*'
|
||||
if left_type in ('', 'void'):
|
||||
return 'i8*'
|
||||
# 吸收仅对"裸类引用"成立(其非 embedded 形式本身即指针):
|
||||
# ast.AST | CPtr → %"sha1.AST"*。已自带指针层数的左值
|
||||
# (rawptr[...] / CPtr[...] 下标 / 联合写法)须逐层外包:
|
||||
# rawptr[Node] | CPtr → Node**、ast.AST | CPtr | CPtr → AST**
|
||||
# ——与定义端 _CollectAllOperandTypes 整体拉平、只吸收一次 CPtr
|
||||
# (_MergeAllComponentTypes 的 base_ptr_count>0 分支)一致。
|
||||
if self._is_bare_class_ref_annotation(annotation.left, left_type):
|
||||
return left_type
|
||||
if '*' in left_type:
|
||||
return f'{left_type}*'
|
||||
return f'{left_type}*'
|
||||
# X | CPtr[T](T 为下标段,非裸标记):CPtr 侧贡献自身指针层数 N,
|
||||
# 另一侧外包 N 层(Ptr^N(X));左右两侧写法对称(定义侧 VPC
|
||||
# TypeGenResolve.vp:2604-2609 亦两侧皆判)。必须先于下方
|
||||
# "'*' in left_type → 直接返回左值":否则左值本身已是指针
|
||||
# (BYTEPTR⇒i8*)时会吞掉右段层数(BYTEPTR | CPtr[CPtr] 改前得 i8*)。
|
||||
# LLVM 聚合([N x T] / { ... })不可再外包指针层,保持既有行为(只报不改)。
|
||||
if IsCPtrSubscriptNode(annotation.right) and left_type[:1] not in ('[', '{'):
|
||||
return self._merge_cptr_subscript(left_type, right_type)
|
||||
if IsCPtrSubscriptNode(annotation.left) and right_type[:1] not in ('[', '{'):
|
||||
return self._merge_cptr_subscript(right_type, left_type)
|
||||
# CPtr 裸标记在左侧(CPtr | X):与右侧写法(X | CPtr,见上)
|
||||
# 完全对称。缺此分支时左值 i8* 会吞掉右侧的指针层数:
|
||||
# CPtr | rawptr[Node] 声明端曾得 i8*,而定义端为 %"sha1.Node"**(差一层)。
|
||||
# 仅对裸标记 CPtr 生效(left 为 CPtr[T] 下标走上一条分支;
|
||||
# str/bytes 等其它 i8* 左值不受影响)。
|
||||
if IsCPtrNode(annotation.left) and right_type[:1] not in ('[', '{'):
|
||||
if self._is_bare_class_ref_annotation(annotation.right, right_type):
|
||||
return right_type
|
||||
return f'{right_type}*'
|
||||
if '*' in left_type:
|
||||
return left_type
|
||||
if '*' in right_type:
|
||||
return right_type
|
||||
return left_type
|
||||
elif isinstance(annotation, ast.Subscript):
|
||||
# 指针下标(rawptr[T] / CPtr[T] / 裸名 CPtr[T] / 导入别名 X[T],以及带
|
||||
# 模块前缀书写的 X.CPtr[T])≡ 源码联合写法 `T | CPtr`:与定义端
|
||||
# **同一判据**(SymbolUtils.IsPtrSubscriptNode,别名经本模块的
|
||||
# _from_import_aliases 表解析 X→CPtr)+ 同一层数规则
|
||||
# (_ptr_subscript_type_str:裸类引用吸收一层、其余逐层外包),内层 T
|
||||
# 照常解析(跨模块类由 struct_sha1_map 补 SHA1 前缀)。此前 rawptr[T]
|
||||
# 在此退化成 i8*,CPtr[T] 走的是"embedded + 追加一层"的独立分支:
|
||||
# 非同一规则,且对泛型容器特化多出一层(CPtr[list[X]] 得 list[X]**,
|
||||
# 而 rawptr[list[X]] 得 list[X]*)。
|
||||
# 指针下标(rawptr[T] / CPtr[T] / 裸名 CPtr[T] / 导入别名 X[T]):
|
||||
# 裸类引用吸收一层、其余逐层外包,内层 T 照常解析
|
||||
# (跨模块类由 struct_sha1_map 补 SHA1 前缀)。
|
||||
ValueIsCPtr: bool = (
|
||||
(isinstance(annotation.value, ast.Attribute) and annotation.value.attr == 'CPtr')
|
||||
or (isinstance(annotation.value, ast.Name) and annotation.value.id == 'CPtr')
|
||||
@@ -1390,6 +1287,18 @@ class DeclarationGenerator:
|
||||
if (IsPtrSubscriptNode(annotation, TCAliasMap=self._from_import_aliases)
|
||||
or (ValueIsCPtr and isinstance(annotation.slice, (ast.Attribute, ast.Name, ast.Subscript)))):
|
||||
return self._ptr_subscript_type_str(annotation)
|
||||
MarkerName: str | None = None
|
||||
if isinstance(annotation.value, ast.Name):
|
||||
MarkerName = annotation.value.id
|
||||
elif isinstance(annotation.value, ast.Attribute):
|
||||
MarkerName = annotation.value.attr
|
||||
if MarkerName in ('CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
InnerType: str = self._get_type_str(annotation.slice, embedded=embedded)
|
||||
if self._is_bare_class_ref_annotation(annotation.slice, InnerType):
|
||||
return InnerType
|
||||
if InnerType in ('', 'void', 'void*'):
|
||||
return 'i8*'
|
||||
return f'{InnerType}*'
|
||||
# 内建裸名函数指针构造子 callable[...] / Callable[...]:与 Attribute 分支的
|
||||
# Callable[...] 逐点等价(同为 i8*)。缺此分支时落到下方 Name 泛型特化 /
|
||||
# 兜底返回 'i32'(现场 Repl.vp:307 `ReplFragFn: callable[[rawptr], int]`
|
||||
@@ -1544,11 +1453,9 @@ class DeclarationGenerator:
|
||||
return 'i32'
|
||||
|
||||
def _get_bitfield_width(self, annotation: ast.AST) -> int | None:
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
right_width: int | None = self._get_bitfield_width(annotation.right)
|
||||
if right_width is not None:
|
||||
return right_width
|
||||
return self._get_bitfield_width(annotation.left)
|
||||
BitWidth: int | None = getattr(annotation, 'BitWidth', None)
|
||||
if BitWidth:
|
||||
return BitWidth
|
||||
if isinstance(annotation, ast.Call):
|
||||
if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Bit':
|
||||
if annotation.args:
|
||||
|
||||
@@ -10,8 +10,7 @@ from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
from lib.core import TypeSystem
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotationWithContext,
|
||||
AnnotationContainsName, IsCPtrNode, RequireDefineConstStorable,
|
||||
IsListAnnotation, ParseListAnnotation, RequireDefineConstStorable,
|
||||
FindAutoAddrMode,
|
||||
)
|
||||
|
||||
@@ -461,10 +460,12 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen.builder.call(append_func, adjusted_append, name=f"append_{VarName}_{i}")
|
||||
|
||||
# 10. 创建变量并存储堆指针
|
||||
# 判断变量类型:list[T] | CPtr → i8*;list[T] → Ptr(StructType)
|
||||
is_cptr_union: bool = isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr)
|
||||
# 判断变量类型:解析不出具体基类型的指针(如 CPtr[list[T]] 内层未知)→ i8*;
|
||||
# 其余 → Ptr(StructType)
|
||||
_AnnInfo: CTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation)
|
||||
is_cptr_union: bool = _AnnInfo.IsVoid and _AnnInfo.PtrCount > 0
|
||||
if is_cptr_union:
|
||||
# list[T] | CPtr → 变量类型为 i8*
|
||||
# 变量类型为 i8*
|
||||
i8_ptr_type: ir.PointerType = ir.PointerType(ir.IntType(8))
|
||||
var: ir.AllocaInstr = Gen._allocaEntry(i8_ptr_type, name=VarName)
|
||||
# bitcast heap_ptr (Ptr(StructType)) → i8*
|
||||
@@ -514,6 +515,11 @@ class AnnAssignHandle(BaseHandle):
|
||||
|
||||
def _HandleAnnAssignLlvmInner(self, Node: ast.AnnAssign) -> None:
|
||||
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
Line: int = getattr(Node.annotation, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
# 值引用标记(`&T` / `&temp T`)仅用于函数参数位:局部/全局变量注解出现即 fail-fast。
|
||||
_ref_mode: str | None = FindAutoAddrMode(Node.annotation)
|
||||
if _ref_mode is not None:
|
||||
@@ -591,14 +597,12 @@ class AnnAssignHandle(BaseHandle):
|
||||
_meta_name: str = f"{VarName}__meta__"
|
||||
_meta_var: ir.AllocaInstr = Gen._allocaEntry(Gen.structs['_str'], name=_meta_name)
|
||||
Gen.variables[_meta_name] = _meta_var
|
||||
# 标记指针到 str/bytes 的变量 (BinOp 注解如 str | CPtr)
|
||||
# 标记指向字符串指针的变量(i8**):
|
||||
# elem_ptr[0] 应加载/存储 8 字节 (指针), 而非 1 字节 (字符)
|
||||
# 仅当注解包含 str 或 bytes 时设置(CChar | CPtr 不应设置,它是纯字符指针)
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'):
|
||||
Gen.var_ptr_element[VarName] = True
|
||||
# 同时记录到全局字典,使全局变量在跨函数访问时仍能用 8 字节指针步长
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
if TypeInfo.IsStr and TypeInfo.PtrCount >= 2:
|
||||
Gen.var_ptr_element[VarName] = True
|
||||
# 同时记录到全局字典,使全局变量在跨函数访问时仍能用 8 字节指针步长
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
parse_result = ParseListAnnotation(Node.annotation)
|
||||
if parse_result:
|
||||
elem_type_node: ast.expr = parse_result.elem_type_node
|
||||
@@ -652,20 +656,17 @@ class AnnAssignHandle(BaseHandle):
|
||||
return
|
||||
# list[T] 泛型类注解 + list 字面量值 → 构造 list[T] 对象 + append 序列
|
||||
# (list[str] = ["a", "b"] 不应走 C 数组路径,而应构造 list[str] 对象)
|
||||
# 支持两种注解形式:list[T] 和 list[T] | CPtr
|
||||
# 支持注解形式:list[T] 与 CPtr[list[T]]
|
||||
list_sub: ast.Subscript | None = None
|
||||
if (isinstance(Node.annotation, ast.Subscript)
|
||||
and isinstance(Node.annotation.value, ast.Name)
|
||||
and Node.annotation.value.id == 'list'):
|
||||
list_sub = Node.annotation
|
||||
elif (isinstance(Node.annotation, ast.BinOp)
|
||||
and isinstance(Node.annotation.op, ast.BitOr)):
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
if (isinstance(side, ast.Subscript)
|
||||
and isinstance(side.value, ast.Name)
|
||||
and side.value.id == 'list'):
|
||||
list_sub = side
|
||||
break
|
||||
elif (isinstance(Node.annotation, ast.Subscript)
|
||||
and isinstance(Node.annotation.slice, ast.Subscript)
|
||||
and isinstance(Node.annotation.slice.value, ast.Name)
|
||||
and Node.annotation.slice.value.id == 'list'):
|
||||
list_sub = Node.annotation.slice
|
||||
if (list_sub is not None
|
||||
and not isinstance(list_sub.slice, ast.Tuple)
|
||||
and Node.value is not None
|
||||
@@ -674,27 +675,7 @@ class AnnAssignHandle(BaseHandle):
|
||||
and 'list' in self.Trans.ClassHandler._generic_class_templates):
|
||||
self._HandleGenericListLiteralAssign(VarName, Node, Gen, list_sub)
|
||||
return
|
||||
# Only fall back to the left operand when the union neither resolved a base
|
||||
# type nor accumulated multi-level pointers. A pointer-marker based union
|
||||
# (`CPtr*` = `CPtr | CPtr` => CVoid/2) is already a fully resolved
|
||||
# multi-level pointer; falling back to its left operand (`CPtr` => 1 layer)
|
||||
# used to silently degrade it to i8*. Keep PtrCount > 1 untouched.
|
||||
if (TypeInfo.IsVoid and TypeInfo.PtrCount <= 1
|
||||
and isinstance(Node.annotation, ast.BinOp)):
|
||||
found: str | None = FindStructNameInAnnotationWithContext(
|
||||
Node.annotation, self.Trans, Gen)
|
||||
if found:
|
||||
TypeInfo = CTypeInfo()
|
||||
TypeInfo.BaseType = TypeSystem.CStruct(name=found)
|
||||
TypeInfo.PtrCount = 1
|
||||
IsPtr = True
|
||||
elif isinstance(Node.annotation.left, ast.Attribute):
|
||||
AttrTypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation.left)
|
||||
if AttrTypeInfo and AttrTypeInfo.BaseType:
|
||||
TypeInfo = AttrTypeInfo
|
||||
TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1)
|
||||
IsPtr = True
|
||||
# 对于局部变量声明 s: TestStruct(不带 | CPtr),应为栈上结构体而非指针
|
||||
# 对于局部变量声明 s: TestStruct,应为栈上结构体而非指针
|
||||
# GetCTypeInfo 默认设置 PtrCount=1,但纯结构体名注解应为值类型
|
||||
if (isinstance(Node.annotation, ast.Name)
|
||||
and Node.annotation.id in Gen.structs
|
||||
@@ -724,36 +705,13 @@ class AnnAssignHandle(BaseHandle):
|
||||
if isinstance(VarType, ir.VoidType):
|
||||
VarType = ir.IntType(32)
|
||||
IsUnsigned: bool = TypeInfo.IsUInt
|
||||
# 修复 3: BinOp 注解(如 ast.Arguments | CPtr)的 var_struct_class 设置
|
||||
# TypeInfo.Name 由 _HandleSubscript 设置(特化名如 list[sha1.ASTptr])或
|
||||
# GetCTypeInfo 设置(普通结构体名),经 _MergeCTypeInfoInto 传播后保留。
|
||||
# 此处确保 BinOp 注解的变量也能被 _get_var_class 识别,避免方法调用分派
|
||||
# fallthrough 到 char pointer fallback 错误匹配其他类(如 AST.__len__)。
|
||||
# 使用 not in 条件,不覆盖后续 L337-339/L396-398 对 ast.Name 注解的精确设置。
|
||||
# 结构体注解的 var_struct_class 设置:TypeInfo.Name 由 _HandleSubscript
|
||||
# 设置(泛型特化名)或 GetCTypeInfo 设置(普通结构体名)。
|
||||
# 使用 not in 条件,不覆盖后续对 ast.Name 注解的精确设置。
|
||||
if TypeInfo.IsStruct and TypeInfo.Name and TypeInfo.Name in Gen.structs:
|
||||
if VarName not in Gen.var_struct_class:
|
||||
Gen.var_struct_class[VarName] = TypeInfo.Name
|
||||
Gen.global_struct_class[VarName] = TypeInfo.Name
|
||||
# 联合指针注解(X | CPtr)短名回退:resolver 对模块限定 struct
|
||||
# 段(如 llvmlite.Value)无法精确 in Gen.structs(键可能是 'Value'
|
||||
# 或带 sha1 前缀),Name 常退化为指针别名 'rawptr'(被注册成 opaque
|
||||
# struct)→ 变量 var_struct_class 登记为 rawptr → 字段访问
|
||||
# "属性 'Next' 在类 'rawptr' 中找不到"(FuncGenMixin.vp L307)。
|
||||
# FindStructNameInAnnotation 以 attr/短名命中,找回真实类名。
|
||||
if (isinstance(Node.annotation, ast.BinOp)
|
||||
and isinstance(Node.annotation.op, ast.BitOr)):
|
||||
_union_struct_name2: str | None = FindStructNameInAnnotationWithContext(
|
||||
Node.annotation, self.Trans, Gen)
|
||||
# resolver 对模块限定 struct 联合(llvmlite.Value | CPtr)常给出
|
||||
# 指针占位名(如 '{sha1}.rawptr')且该占位恰好注册在 Gen.structs,
|
||||
# 使上方 TypeInfo.Name in Gen.structs 通过并登记错误类名 → 字段
|
||||
# 访问 "属性 'Next' 在类 'rawptr' 中找不到"。凡短名命中真实类
|
||||
# (attr 精确 in structs),一律覆盖为真实类名(Value)。
|
||||
if _union_struct_name2 and _union_struct_name2 in Gen.structs:
|
||||
if Gen.var_struct_class.get(VarName) != _union_struct_name2:
|
||||
Gen.var_struct_class[VarName] = _union_struct_name2
|
||||
if getattr(Gen, 'global_struct_class', None) is not None:
|
||||
Gen.global_struct_class[VarName] = _union_struct_name2
|
||||
# Subscript rawptr[X] / CPtr[X] 注解的本地结构指针变量(如
|
||||
# includes/ast/parser.vp _fix_store_ctx 里 `tp: rawptr[Tuple] =
|
||||
# (rawptr[Tuple])(node)`,随后 `tp_elts = tp.elts`):TypeMerge 的
|
||||
@@ -771,7 +729,7 @@ class AnnAssignHandle(BaseHandle):
|
||||
_rst_nm = _rst_v.id
|
||||
elif isinstance(_rst_v, ast.Attribute) and isinstance(_rst_v.value, ast.Name):
|
||||
_rst_nm = f'{_rst_v.value.id}.{_rst_v.attr}'
|
||||
if _rst_nm in ('rawptr', 'CPtr'):
|
||||
if _rst_nm in ('rawptr', 'CPtr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
_rst_sub = Node.annotation
|
||||
if _rst_sub is not None:
|
||||
_rst_sl: ast.AST = _rst_sub.slice
|
||||
@@ -804,31 +762,16 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen.var_struct_class[VarName] = _rst_tk
|
||||
if getattr(Gen, 'global_struct_class', None) is not None:
|
||||
Gen.global_struct_class[VarName] = _rst_tk
|
||||
# 检测指针到指针缓冲区变量:注解为 StructName | CPtr,且赋值来自 CPtr(...) 调用。
|
||||
# 这种变量(如 list[T].__getitem__ 中的 elem_ptr: T | CPtr = CPtr(...))
|
||||
# 实际指向存储结构体指针的缓冲区(T=AST|CPtr 时特化为 AST*,缓冲区存 AST* 数组)。
|
||||
# [index] 应 bitcast 为 AST** 后 GEP 指针数组再 load,而非 GEP 结构体数组。
|
||||
# 泛型特化将 T|CPtr 降级为 StructName|CPtr(丢失一层指针),故通过赋值来源区分:
|
||||
# elem_ptr 的值是 CPtr(buf + idx*elem_size)(原始指针运算,缓冲区内容未知),
|
||||
# pts 的值是 (Point|CPtr)(...)(类型转换,明确指向 Point 结构体)。
|
||||
# 检测指针到指针缓冲区变量:注解为指针下标(如 CPtr[T]),且赋值来自
|
||||
# CPtr(...) 调用。这种变量实际指向存储结构体指针的缓冲区,
|
||||
# [index] 应 bitcast 为 T** 后 GEP 指针数组再 load。
|
||||
_is_cptr_assign: bool = (
|
||||
isinstance(Node.value, ast.Call)
|
||||
and isinstance(Node.value.func, ast.Name)
|
||||
and Node.value.func.id == 'CPtr'
|
||||
)
|
||||
_is_struct_ptr_union: bool = (
|
||||
isinstance(Node.annotation, ast.BinOp)
|
||||
and isinstance(Node.annotation.op, ast.BitOr)
|
||||
and ((IsCPtrNode(Node.annotation.left)
|
||||
and isinstance(Node.annotation.right, ast.Name)
|
||||
and (Node.annotation.right.id in Gen.structs
|
||||
or _IsGenericTpName(Node.annotation.right.id)))
|
||||
or (IsCPtrNode(Node.annotation.right)
|
||||
and isinstance(Node.annotation.left, ast.Name)
|
||||
and (Node.annotation.left.id in Gen.structs
|
||||
or _IsGenericTpName(Node.annotation.left.id))))
|
||||
)
|
||||
if _is_cptr_assign and _is_struct_ptr_union:
|
||||
_is_struct_ptr_annotation: bool = _rst_sub is not None and TypeInfo.IsPtr
|
||||
if _is_cptr_assign and _is_struct_ptr_annotation:
|
||||
Gen.var_ptr_element[VarName] = True
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
if VarName in Gen._reg_values:
|
||||
@@ -959,20 +902,23 @@ class AnnAssignHandle(BaseHandle):
|
||||
Gen.global_struct_class[VarName] = Node.annotation.id
|
||||
Gen._record_var_signedness(VarName, IsUnsigned)
|
||||
return
|
||||
# 方向判定用:取注解一侧的泛型基名(`Base[...]` 或 `Base[...] | CPtr`
|
||||
# 方向判定用:取注解中的泛型基名(`Base[...]` 或 `CPtr[Base[...]]`
|
||||
# 形态中的 Base)。此判据**不依赖泛型模板注册表**(list/dict 等内建
|
||||
# 容器可能未登记),只做结构性识别;仅 Name 形态可识别,属性链
|
||||
# (如 CPtr[...])不参与。
|
||||
# 容器可能未登记),只做结构性识别;仅 Name 形态可识别。
|
||||
_ann_gen_base: str | None = None
|
||||
_ann_sub_side: ast.expr | None = None
|
||||
if isinstance(Node.annotation, ast.Subscript):
|
||||
_ann_sub_side = Node.annotation
|
||||
elif (isinstance(Node.annotation, ast.BinOp)
|
||||
and isinstance(Node.annotation.op, ast.BitOr)):
|
||||
for _ann_side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(_ann_side, ast.Subscript):
|
||||
_ann_sub_side = _ann_side
|
||||
break
|
||||
_ann_side: ast.expr = Node.annotation
|
||||
_ann_probe: ast.expr = _ann_side.value
|
||||
while isinstance(_ann_probe, ast.Subscript):
|
||||
_ann_probe = _ann_probe.value
|
||||
_ann_probe_nm: str | None = (
|
||||
_ann_probe.id if isinstance(_ann_probe, ast.Name)
|
||||
else (_ann_probe.attr if isinstance(_ann_probe, ast.Attribute) else None))
|
||||
if (_ann_probe_nm in ('CPtr', 'rawptr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr')
|
||||
and isinstance(_ann_side.slice, ast.Subscript)):
|
||||
_ann_side = _ann_side.slice
|
||||
_ann_sub_side = _ann_side
|
||||
if _ann_sub_side is not None:
|
||||
_ann_base_v: ast.expr = _ann_sub_side.value
|
||||
# 兼容嵌套下标链(Base[...][...]):逐层剥到最内层 Name
|
||||
@@ -1010,27 +956,24 @@ class AnnAssignHandle(BaseHandle):
|
||||
if CN == 'rawptr' or CN.endswith('.rawptr') or CN.startswith('rawptr['):
|
||||
continue
|
||||
if pointee is ST or pointee == ST:
|
||||
# 若注解是泛型特化(如 ndarray[CDouble] | CPtr),
|
||||
# 若注解是泛型特化(如 CPtr[ndarray[CDouble]]),
|
||||
# 构造正确的特化名(如 ndarray[double]),而非用 opaque 基础名
|
||||
resolved_cn: str = CN
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr) and '[' not in CN:
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(side, ast.Subscript):
|
||||
bn: ast.expr = side.value
|
||||
bnm: str | None = bn.id if isinstance(bn, ast.Name) else (bn.attr if isinstance(bn, ast.Attribute) else None)
|
||||
# 归一化比较:CN 可能带 16 位 sha1 模块前缀
|
||||
# (如 'e94ef9e139461915.list'),注解侧裸名为
|
||||
# 'list',直接与 CN 比较恒不等 ⇒ 特化名恢复失败
|
||||
# ⇒ 写入裸泛型基名 ⇒ .get() 按错误元素类型
|
||||
# 分派崩溃。用 _cn_short(已去前缀)比较。
|
||||
if bnm and bnm == _cn_short:
|
||||
sn2: ast.AST = side.slice
|
||||
if hasattr(ast, 'Index') and isinstance(sn2, ast.Index):
|
||||
sn2 = sn2.value
|
||||
r2: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(sn2)
|
||||
if r2:
|
||||
resolved_cn = f'{CN}[{r2[0]}]'
|
||||
break
|
||||
if _ann_sub_side is not None and '[' not in CN:
|
||||
bn: ast.expr = _ann_sub_side.value
|
||||
bnm: str | None = bn.id if isinstance(bn, ast.Name) else (bn.attr if isinstance(bn, ast.Attribute) else None)
|
||||
# 归一化比较:CN 可能带 16 位 sha1 模块前缀
|
||||
# (如 'e94ef9e139461915.list'),注解侧裸名为
|
||||
# 'list',直接与 CN 比较恒不等 ⇒ 特化名恢复失败
|
||||
# ⇒ 写入裸泛型基名 ⇒ .get() 按错误元素类型
|
||||
# 分派崩溃。用 _cn_short(已去前缀)比较。
|
||||
if bnm and bnm == _cn_short:
|
||||
sn2: ast.AST = _ann_sub_side.slice
|
||||
if hasattr(ast, 'Index') and isinstance(sn2, ast.Index):
|
||||
sn2 = sn2.value
|
||||
r2: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(sn2)
|
||||
if r2:
|
||||
resolved_cn = f'{CN}[{r2[0]}]'
|
||||
if resolved_cn != Gen.var_struct_class.get(VarName):
|
||||
Gen.var_struct_class[VarName] = resolved_cn
|
||||
Gen.global_struct_class[VarName] = resolved_cn
|
||||
@@ -1144,34 +1087,6 @@ class AnnAssignHandle(BaseHandle):
|
||||
elif isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width in (16, 32, 64):
|
||||
Gen.local_var_byteorders[VarName] = 'big'
|
||||
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
found_struct: str | None = FindStructNameInAnnotationWithContext(
|
||||
Node.annotation, self.Trans, Gen)
|
||||
# 若 FindStructNameInAnnotation 仅返回裸模板名(如 'ndarray'),但注解中
|
||||
# 含泛型特化(如 numpy.ndarray[CDouble]),用 LLVM 类型名构造特化名
|
||||
# (如 'ndarray[double]')。main.py 的 Gen.structs 可能只有 opaque 'ndarray',
|
||||
# 但 numpy 模块已特化 ndarray[double],方法调用通过 sha1 前缀查找。
|
||||
if found_struct and '[' not in found_struct:
|
||||
for side in (Node.annotation.left, Node.annotation.right):
|
||||
if isinstance(side, ast.Subscript):
|
||||
base_node: ast.expr = side.value
|
||||
base_nm: str | None = None
|
||||
if isinstance(base_node, ast.Name):
|
||||
base_nm = base_node.id
|
||||
elif isinstance(base_node, ast.Attribute):
|
||||
base_nm = base_node.attr
|
||||
if base_nm and base_nm == found_struct:
|
||||
slice_node: ast.AST = side.slice
|
||||
if hasattr(ast, 'Index') and isinstance(slice_node, ast.Index):
|
||||
slice_node = slice_node.value
|
||||
result: tuple[str, str] | None = self.Trans.ExprCallHandle._resolve_generic_slice_type(slice_node)
|
||||
if result:
|
||||
found_struct = f'{base_nm}[{result[0]}]'
|
||||
break
|
||||
if found_struct:
|
||||
Gen.var_struct_class[VarName] = found_struct
|
||||
Gen.global_struct_class[VarName] = found_struct
|
||||
|
||||
if InitValue and isinstance(InitValue.type, ir.PointerType):
|
||||
pointee: ir.Type = InitValue.type.pointee
|
||||
if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
|
||||
|
||||
@@ -11,7 +11,7 @@ from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
|
||||
from lib.constants.config import mode as _config_mode
|
||||
from lib.core import TypeSystem
|
||||
from lib.core.TypeSystem import CTypeRegistry
|
||||
from lib.core.SymbolUtils import ParseListAnnotation, AnnotationContainsName
|
||||
from lib.core.SymbolUtils import ParseListAnnotation
|
||||
|
||||
class AssignHandle(BaseHandle):
|
||||
def __init__(self, translator: "Translator") -> None:
|
||||
@@ -2029,11 +2029,10 @@ class AssignHandle(BaseHandle):
|
||||
Gen.global_struct_class[VarName] = TypeInfo.Name
|
||||
return
|
||||
GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName)
|
||||
# 全局变量指针元素标志:bytes|CPtr 或 str|CPtr 注解的变量,
|
||||
# 全局变量指针元素标志:指向字符串指针(i8**)的变量,
|
||||
# 使 var[index] 使用 8 字节指针步长(而非 1 字节字符步长)
|
||||
if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr):
|
||||
if AnnotationContainsName(Node.annotation, 'str') or AnnotationContainsName(Node.annotation, 'bytes'):
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
if TypeInfo is not None and TypeInfo.IsStr and TypeInfo.PtrCount >= 2:
|
||||
Gen.global_var_ptr_element[VarName] = True
|
||||
if Node.value:
|
||||
if isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str) and isinstance(VarType, ir.PointerType):
|
||||
# 字符串字面量全局:初始化器 = 指向 @{VarName}_str 常量数组首元素
|
||||
@@ -2117,19 +2116,12 @@ class AssignHandle(BaseHandle):
|
||||
def _ScanGlobalTAttr(self, node: ast.AST | None, want_name: str) -> ast.AST | None:
|
||||
"""在全局变量注解中查找 attr.<want_name> 节点,命中返回该节点。
|
||||
|
||||
注解形态是 BinOp(BitOr) 左深链(`A | B | C` = BinOp(BinOp(A,B),C)),
|
||||
递归左右子节点。命中节点形态:Call(attr.aligned(16))或
|
||||
Attribute(attr.weak)。同时兼容包装写法
|
||||
`T | Attribute(attr.section("..."))`(解包参考 ViperC
|
||||
命中节点形态:Call(attr.aligned(16))或 Attribute(attr.weak)。
|
||||
同时兼容包装写法 `Attribute(attr.section("..."))`(解包参考 ViperC
|
||||
ClassGenBase._class_has_tattr,.vp:375-389)。
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
hit_left: ast.AST | None = self._ScanGlobalTAttr(node.left, want_name)
|
||||
if hit_left is not None:
|
||||
return hit_left
|
||||
return self._ScanGlobalTAttr(node.right, want_name)
|
||||
# 包装写法:Attribute(attr.xxx / attr.xxx(...)) → 拆 args 再扫
|
||||
# (与 HandlesFunctions.py 装饰器侧同一判据:func.id == 'Attribute')
|
||||
if (isinstance(node, ast.Call) and isinstance(node.func, ast.Name)
|
||||
@@ -2188,6 +2180,19 @@ class AssignHandle(BaseHandle):
|
||||
f"模块级变量 '{VarName}' 的 {Msg}(位置 {loc})", src_file, lineno, '')
|
||||
sys.exit(1)
|
||||
|
||||
@staticmethod
|
||||
def _ParseAttrText(Raw: object) -> tuple[str, str | None]:
|
||||
"""解析 Attributes 字段中的单条文本(如 'section(".x")' / 'aligned(16)')。"""
|
||||
text: str = str(Raw).strip()
|
||||
name, sep, rest = text.partition('(')
|
||||
name = name.strip()
|
||||
if not sep:
|
||||
return name, None
|
||||
rest = rest.rstrip(')').strip()
|
||||
if len(rest) >= 2 and rest[0] == rest[-1] and rest[0] in ('"', "'"):
|
||||
rest = rest[1:-1]
|
||||
return name, rest
|
||||
|
||||
def _ExtractGlobalAttrs(self, Node: ast.AnnAssign, Gen: "Translator.LlvmGen") -> dict[str, Any]:
|
||||
"""从模块级全局注解提取 attr.section/aligned/weak。
|
||||
|
||||
@@ -2198,6 +2203,28 @@ class AssignHandle(BaseHandle):
|
||||
Attrs: dict[str, Any] = {'section': None, 'align': 0, 'weak': False}
|
||||
Ann: ast.AST = Node.annotation
|
||||
VarName: str = Node.target.id if isinstance(Node.target, ast.Name) else '<anonymous>'
|
||||
RawAttrs: list[object] = list(getattr(Node, 'Attributes', None) or ()) + list(
|
||||
getattr(Ann, 'Attributes', None) or ())
|
||||
for RawAttr in RawAttrs:
|
||||
attr_name, attr_arg = self._ParseAttrText(RawAttr)
|
||||
if attr_name == 'section':
|
||||
if not attr_arg:
|
||||
self._RaiseGlobalAttrError(
|
||||
"attr.section(...) 段名缺失或为空(空段名会生成非法的 section \"\")",
|
||||
Ann, Gen, VarName)
|
||||
Attrs['section'] = attr_arg
|
||||
elif attr_name == 'aligned':
|
||||
align_val: int | None = None
|
||||
try:
|
||||
align_val = int(attr_arg) if attr_arg else None
|
||||
except ValueError:
|
||||
align_val = None
|
||||
if align_val is None or align_val <= 0:
|
||||
self._RaiseGlobalAttrError(
|
||||
"attr.aligned(N) 需要正整数字面量 N", Ann, Gen, VarName)
|
||||
Attrs['align'] = align_val
|
||||
elif attr_name == 'weak':
|
||||
Attrs['weak'] = True
|
||||
sec_node: ast.AST | None = self._ScanGlobalTAttr(Ann, 'section')
|
||||
if sec_node is not None:
|
||||
sec_val: str | None = self._TAttrArgStr(sec_node)
|
||||
@@ -2372,11 +2399,17 @@ class AssignHandle(BaseHandle):
|
||||
return None
|
||||
|
||||
def _IsTypedefAnnotation(self, annotation: ast.expr) -> bool:
|
||||
Markers: tuple[str, ...] = getattr(annotation, 'Markers', None) or ()
|
||||
if 'typedef' in Markers or 'define' in Markers:
|
||||
return True
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
Line: int = getattr(annotation, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
if isinstance(annotation, ast.Attribute):
|
||||
if annotation.attr in ('CTypedef', 'CDefine'):
|
||||
return True
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
return self._IsTypedefAnnotation(annotation.left) or self._IsTypedefAnnotation(annotation.right)
|
||||
if isinstance(annotation, ast.Subscript):
|
||||
return self._IsTypedefAnnotation(annotation.value)
|
||||
return False
|
||||
|
||||
@@ -1043,11 +1043,9 @@ class BaseHandle:
|
||||
# 本方法覆盖函数参数/返回注解与类字段(CollectAnnAssignMember 亦经此)。
|
||||
self._CheckFixedArrayKeyword(annotation)
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
merger: Any = getattr(self.Trans, 'TypeMergeHandler', None)
|
||||
if merger:
|
||||
info: CTypeInfo | None = merger.MergeTypes(annotation)
|
||||
if info is not None and isinstance(info, CTypeInfo):
|
||||
return info
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {getattr(annotation, 'lineno', 0)} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
if IsPtrSubscriptNode(annotation, self.Trans.SymbolTable):
|
||||
merger = getattr(self.Trans, 'TypeMergeHandler', None)
|
||||
if merger:
|
||||
@@ -1146,11 +1144,9 @@ class BaseHandle:
|
||||
改走 TypeMerge 泛型识别路径,其余保持 ResolveAnnotationType 语义。
|
||||
"""
|
||||
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
|
||||
merger: Any = getattr(self.Trans, 'TypeMergeHandler', None)
|
||||
if merger:
|
||||
info: CTypeInfo | None = merger.MergeTypes(annotation)
|
||||
if info is not None and isinstance(info, CTypeInfo):
|
||||
return info
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {getattr(annotation, 'lineno', 0)} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
# 指针下标参数注解(rawptr[T] / CPtr[T] / 裸名 CPtr[T],含
|
||||
# rawptr[list[X]] 等容器:_SubscriptHitsGenericTemplate 也命中,但统一交
|
||||
# ResolveAnnotationType 处理更简单——它已把指针下标路由到 TypeMerge)。
|
||||
|
||||
@@ -13,7 +13,7 @@ from lib.constants.config import mode as _config_mode
|
||||
from lib.core import TypeSystem
|
||||
from lib.core.TypeSystem import CTypeRegistry
|
||||
from lib.core.SymbolUtils import (
|
||||
ExtractTypeNameFromBinOp, IsPtrSubscriptNode, DesugarPtrSubscriptToUnion,
|
||||
ExtractTypeNameFromBinOp, IsPtrSubscriptNode,
|
||||
ResolveTypeArgStr, GenericArgRawName,
|
||||
ClassHasFuncLevelCVTable, IsVtableSlotMethod)
|
||||
from lib.core.Handles.HandlesExpr import DefineUseWidthFromLLVMType
|
||||
@@ -2066,7 +2066,7 @@ class ExprCallHandle(BaseHandle):
|
||||
type_info = None
|
||||
MergeException = None
|
||||
try:
|
||||
type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.func)
|
||||
type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.GetCTypeInfo(Node.func)
|
||||
except Exception as _e:
|
||||
MergeException = _e
|
||||
if _config_mode == "strict":
|
||||
@@ -4233,8 +4233,6 @@ class ExprCallHandle(BaseHandle):
|
||||
会拼出 'rawptr[ast.AST]' 实参串(内层未混淆)→ 与 list[ast.AST | CPtr]
|
||||
的 '<sha1>.AST*' 分裂成两个特化名(结构体/方法声明/调用点三端不一致)。
|
||||
"""
|
||||
if IsPtrSubscriptNode(sn, self.Trans.SymbolTable):
|
||||
sn = DesugarPtrSubscriptToUnion(sn, self.Trans.SymbolTable)
|
||||
if isinstance(sn, ast.Name):
|
||||
# type_arg 走唯一规则源(命中注册类加 SHA1 前缀,裸名与
|
||||
# `list[X]`/`rawptr[X]` 内层收敛到同一名字);
|
||||
|
||||
@@ -8,9 +8,7 @@ import copy
|
||||
import traceback
|
||||
import llvmlite.ir as ir
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta
|
||||
from lib.core.SymbolUtils import (
|
||||
FindStructNameInAnnotationWithContext, AnnotationContainsName,
|
||||
IsPtrSubscriptNode, DesugarPtrSubscriptToUnion, FindAutoAddrMode)
|
||||
from lib.core.SymbolUtils import FindAutoAddrMode
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
from lib.constants.config import mode as _config_mode
|
||||
from lib.core import TypeSystem
|
||||
@@ -53,36 +51,24 @@ def _RejectRefReturnAnnotation(node: ast.AST) -> None:
|
||||
def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
|
||||
"""判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。
|
||||
|
||||
void:None / CVoid,含 `|` 联合形式(注解中 `|` 表示 and),
|
||||
如 `-> CVoid | CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。
|
||||
void:None / CVoid。
|
||||
声明型辅助符号:State(extern)/ CExport(export)/ CExtern——
|
||||
此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明),
|
||||
掉出末尾是正常形态,必须豁免 fail-fast。
|
||||
此类函数 body 为空(extern 声明),掉出末尾是正常形态,必须豁免 fail-fast。
|
||||
"""
|
||||
if isinstance(Annot, ast.BinOp) and isinstance(Annot.op, ast.BitOr):
|
||||
Line: int = getattr(Annot, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
if isinstance(Annot, ast.Constant):
|
||||
return Annot.value is None
|
||||
if isinstance(Annot, ast.Attribute):
|
||||
return getattr(Annot, 'attr', '') in ('CVoid', 'State', 'CExport', 'CExtern')
|
||||
if isinstance(Annot, ast.BinOp) and isinstance(Annot.op, ast.BitOr):
|
||||
return _IsVoidOrDeclAnnotation(Annot.left) or _IsVoidOrDeclAnnotation(Annot.right)
|
||||
return False
|
||||
|
||||
|
||||
def _IsVoidOrDeclAnnotation(Annot: ast.AST) -> bool:
|
||||
"""判断函数返回注解是否为 void 或 extern/export 声明型辅助符号。
|
||||
|
||||
void:None / CVoid,含 `|` 联合形式(注解中 `|` 表示 and),
|
||||
如 `-> CVoid | CExport`(sprintf 先例)→ 掉出末尾 ret void 合法。
|
||||
声明型辅助符号:State(extern)/ CExport(export)/ CExtern——
|
||||
此类函数返回注解被改写为 `<原类型> | 辅助符号` 且 body 为空(extern 声明),
|
||||
掉出末尾是正常形态,必须豁免 fail-fast。
|
||||
"""
|
||||
if isinstance(Annot, ast.Constant):
|
||||
return Annot.value is None
|
||||
if isinstance(Annot, ast.Attribute):
|
||||
return getattr(Annot, 'attr', '') in ('CVoid', 'State', 'CExport', 'CExtern')
|
||||
if isinstance(Annot, ast.BinOp) and isinstance(Annot.op, ast.BitOr):
|
||||
return _IsVoidOrDeclAnnotation(Annot.left) or _IsVoidOrDeclAnnotation(Annot.right)
|
||||
if isinstance(Annot, ast.Name):
|
||||
Markers: tuple[str, ...] = getattr(Annot, 'Markers', None) or ()
|
||||
if 'state' in Markers or 'export' in Markers or 'extern' in Markers:
|
||||
return True
|
||||
return Annot.id in ('CVoid', 'State', 'CExport', 'CExtern')
|
||||
return False
|
||||
|
||||
|
||||
@@ -310,13 +296,14 @@ class FunctionHandle(BaseHandle):
|
||||
|
||||
def _ExtractLLVMAttrs(self, node: ast.AST) -> list[str]:
|
||||
attrs: list[str] = []
|
||||
if isinstance(node, ast.BinOp):
|
||||
attrs.extend(self._ExtractLLVMAttrs(node.left))
|
||||
attrs.extend(self._ExtractLLVMAttrs(node.right))
|
||||
elif isinstance(node, ast.Attribute):
|
||||
attr_name: str | None = self._GetAttrLLVMName(node)
|
||||
if attr_name:
|
||||
for raw_attr in getattr(node, 'Attributes', None) or ():
|
||||
attr_name: str = str(raw_attr).split('(', 1)[0].strip()
|
||||
if attr_name in self._LLVM_ATTR_NAMES:
|
||||
attrs.append(attr_name)
|
||||
if isinstance(node, ast.Attribute):
|
||||
resolved: str | None = self._GetAttrLLVMName(node)
|
||||
if resolved:
|
||||
attrs.append(resolved)
|
||||
return attrs
|
||||
|
||||
def _GetAttrLLVMName(self, node: ast.AST) -> str | None:
|
||||
@@ -535,44 +522,10 @@ class FunctionHandle(BaseHandle):
|
||||
else:
|
||||
try:
|
||||
if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr):
|
||||
ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
|
||||
if not isinstance(ReturnTypeInfo, CTypeInfo):
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CVoid()
|
||||
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
|
||||
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
|
||||
def _FindNonVoidCTypeInfo(node: ast.AST) -> Any:
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
results: list[Any] = []
|
||||
for child in [node.left, node.right]:
|
||||
r: Any = _FindNonVoidCTypeInfo(child)
|
||||
if r and not r.IsVoid:
|
||||
results.append(r)
|
||||
for r in results:
|
||||
if not r.IsPtr and not r.IsStruct:
|
||||
return r
|
||||
return results[0] if results else None
|
||||
try:
|
||||
SideInfo: Any = CTypeInfo.FromNode(node, self.Trans.SymbolTable)
|
||||
if SideInfo:
|
||||
return SideInfo
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
return None
|
||||
found: Any = _FindNonVoidCTypeInfo(Node.returns)
|
||||
if found and not found.IsVoid:
|
||||
ReturnTypeInfo = found
|
||||
if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
# define 宏函数(返回注解含 CDefine,如 `int | CDefine`):
|
||||
# 标记为编译期内联宏(alwaysinline),对齐裸 `-> CDefine` 路径
|
||||
# (合并路径丢失 IsDefine 时仍能命中)
|
||||
if AnnotationContainsName(Node.returns, 'CDefine'):
|
||||
if not hasattr(self, '_cdefine_funcs'):
|
||||
self._cdefine_funcs = set()
|
||||
self._cdefine_funcs.add(FuncName)
|
||||
Line: int = getattr(Node.returns, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
else:
|
||||
is_str_type: bool = False
|
||||
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
|
||||
@@ -648,6 +601,8 @@ class FunctionHandle(BaseHandle):
|
||||
if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
except TypeError:
|
||||
raise
|
||||
except Exception: # 回退:设置默认返回类型为 CInt
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
@@ -834,12 +789,10 @@ class FunctionHandle(BaseHandle):
|
||||
replacement: str = type_map[node.id]
|
||||
return self._make_replacement_node(replacement)
|
||||
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
if isinstance(node.left, ast.Name) and node.left.id in type_map:
|
||||
replacement: str = type_map[node.left.id]
|
||||
node.left = self._make_replacement_node(replacement)
|
||||
return node
|
||||
node.left = self._replace_type_in_annotation(node.left, type_map, cptr_params)
|
||||
node.right = self._replace_type_in_annotation(node.right, type_map, cptr_params)
|
||||
Line: int = getattr(node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
elif isinstance(node, ast.Attribute):
|
||||
if hasattr(node, 'attr') and node.attr in type_map:
|
||||
replacement: str = type_map[node.attr]
|
||||
@@ -884,10 +837,10 @@ class FunctionHandle(BaseHandle):
|
||||
base_node = self._make_name_node(BaseName)
|
||||
node: ast.AST = base_node
|
||||
for _ in range(StarCount):
|
||||
node = ast.BinOp(
|
||||
left=node,
|
||||
op=ast.BitOr(),
|
||||
right=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
node = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=node,
|
||||
ctx=ast.Load(),
|
||||
)
|
||||
return node
|
||||
if replacement.endswith('ptr'):
|
||||
@@ -899,10 +852,10 @@ class FunctionHandle(BaseHandle):
|
||||
levels += 1
|
||||
node: ast.AST = self._make_name_node(base)
|
||||
for _ in range(levels):
|
||||
node = ast.BinOp(
|
||||
left=node,
|
||||
op=ast.BitOr(),
|
||||
right=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
node = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=node,
|
||||
ctx=ast.Load(),
|
||||
)
|
||||
return node
|
||||
if '[' in replacement:
|
||||
@@ -914,8 +867,6 @@ class FunctionHandle(BaseHandle):
|
||||
if not isinstance(SubNode, ast.Subscript):
|
||||
SubNode = self._parse_subscript_manually(replacement)
|
||||
if isinstance(SubNode, ast.Subscript):
|
||||
if IsPtrSubscriptNode(SubNode, self.Trans.SymbolTable):
|
||||
return DesugarPtrSubscriptToUnion(SubNode, self.Trans.SymbolTable)
|
||||
return SubNode
|
||||
return self._make_name_node(replacement)
|
||||
|
||||
@@ -1051,10 +1002,10 @@ class FunctionHandle(BaseHandle):
|
||||
# 需替换为 BinOp(AST | CPtr),使 __sizeof__ 等处理器能正确识别
|
||||
# 指针语义并直接返回 8,避免触发 struct 加载和重入编译
|
||||
if cptr_params and node.func.value.id in cptr_params:
|
||||
node.func.value = ast.BinOp(
|
||||
left=self._make_name_node(replacement),
|
||||
op=ast.BitOr(),
|
||||
right=ast.Name(id='CPtr', ctx=ast.Load())
|
||||
node.func.value = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=self._make_name_node(replacement),
|
||||
ctx=ast.Load()
|
||||
)
|
||||
else:
|
||||
node.func.value = self._make_name_node(replacement)
|
||||
@@ -1066,10 +1017,10 @@ class FunctionHandle(BaseHandle):
|
||||
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.BinOp(
|
||||
left=self._make_name_node(replacement),
|
||||
op=ast.BitOr(),
|
||||
right=ast.Name(id='CPtr', ctx=ast.Load())
|
||||
node.value = ast.Subscript(
|
||||
value=ast.Name(id='CPtr', ctx=ast.Load()),
|
||||
slice=self._make_name_node(replacement),
|
||||
ctx=ast.Load()
|
||||
)
|
||||
else:
|
||||
node.value = ast.Name(id=replacement, ctx=ast.Load())
|
||||
@@ -1134,11 +1085,7 @@ class FunctionHandle(BaseHandle):
|
||||
has_cexport: bool = False
|
||||
if Node.returns:
|
||||
try:
|
||||
RetTypeInfo: Any = None
|
||||
if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr):
|
||||
RetTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
|
||||
else:
|
||||
RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
|
||||
RetTypeInfo: Any = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable)
|
||||
if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, TypeSystem.CExport):
|
||||
has_cexport = True
|
||||
except Exception as _e:
|
||||
@@ -1495,43 +1442,10 @@ class FunctionHandle(BaseHandle):
|
||||
else:
|
||||
try:
|
||||
if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr):
|
||||
ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns)
|
||||
if not isinstance(ReturnTypeInfo, CTypeInfo):
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CVoid()
|
||||
if ((ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState)
|
||||
or (ReturnTypeInfo.PtrCount >= 2 and ReturnTypeInfo.BaseType is None)):
|
||||
def _FindNonVoidCTypeInfo(node):
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
results = []
|
||||
for child in [node.left, node.right]:
|
||||
r = _FindNonVoidCTypeInfo(child)
|
||||
if r and not r.IsVoid:
|
||||
results.append(r)
|
||||
for r in results:
|
||||
if not r.IsPtr and not r.IsStruct:
|
||||
return r
|
||||
return results[0] if results else None
|
||||
try:
|
||||
SideInfo = CTypeInfo.FromNode(node, self.Trans.SymbolTable)
|
||||
if SideInfo:
|
||||
return SideInfo
|
||||
except Exception as _e:
|
||||
if _config_mode == "strict":
|
||||
self.Trans.LogWarning(f"异常被忽略: {_e}")
|
||||
return None
|
||||
found = _FindNonVoidCTypeInfo(Node.returns)
|
||||
if found and not found.IsVoid:
|
||||
ReturnTypeInfo = found
|
||||
if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
# define 宏函数(返回注解含 CDefine,如 `int | CDefine`):
|
||||
# 标记为编译期内联宏(alwaysinline),对齐裸 `-> CDefine` 路径
|
||||
if AnnotationContainsName(Node.returns, 'CDefine'):
|
||||
if not hasattr(self, '_cdefine_funcs'):
|
||||
self._cdefine_funcs = set()
|
||||
self._cdefine_funcs.add(FuncName)
|
||||
Line: int = getattr(Node.returns, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
else:
|
||||
is_str_type = False
|
||||
if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'):
|
||||
@@ -1602,6 +1516,8 @@ class FunctionHandle(BaseHandle):
|
||||
if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState:
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
except TypeError:
|
||||
raise
|
||||
except Exception: # 回退:设置默认返回类型为 CInt
|
||||
ReturnTypeInfo = CTypeInfo()
|
||||
ReturnTypeInfo.BaseType = TypeSystem.CInt()
|
||||
@@ -1977,31 +1893,7 @@ class FunctionHandle(BaseHandle):
|
||||
var = Gen._allocaEntry(param.type, name=param_name)
|
||||
Gen._store(param, var)
|
||||
Gen.variables[param_name] = var
|
||||
# 为联合类型注解(如 Function | CPtr)的参数设置 var_struct_class,
|
||||
# 确保编译器能正确生成 GEP 访问结构体成员(如 func.Blocks、func.Params)
|
||||
for i, arg in enumerate(Node.args.args):
|
||||
if arg.annotation and isinstance(arg.annotation, ast.BinOp) and isinstance(arg.annotation.op, ast.BitOr):
|
||||
param_name: str = ParamNames[i] if i < len(ParamNames) else arg.arg
|
||||
if param_name in Gen.variables:
|
||||
# 若 L1650-1657 已根据 param.type.pointee 匹配到正确的特化名
|
||||
# (如 ndarray[double]),不覆盖:FindStructNameInAnnotation 对
|
||||
# 泛型注解 ndarray[CDouble] 会构造 ndarray[CDouble](与实际
|
||||
# ndarray[double] 不匹配),回退到裸模板类名 ndarray(opaque),
|
||||
# 导致方法调用查找 ndarray.sum 而非 ndarray[double].sum。
|
||||
if param_name in Gen.var_struct_class:
|
||||
_existing_ps: str = Gen.var_struct_class[param_name]
|
||||
# 指针占位名(rawptr / {sha1}.rawptr / rawptr[...])是模块限定
|
||||
# struct 联合(llvmlite.Function | CPtr)被 resolver 退化
|
||||
# 的产物,必须允许 FindStructNameInAnnotation 短名修正
|
||||
# (否则 func.IsVarArg → "属性在类 'rawptr' 中找不到")。
|
||||
if not (_existing_ps == 'rawptr' or '.rawptr' in _existing_ps
|
||||
or _existing_ps.startswith('rawptr[')):
|
||||
continue
|
||||
found_struct: str | None = FindStructNameInAnnotationWithContext(
|
||||
arg.annotation, self.Trans, Gen)
|
||||
if found_struct:
|
||||
Gen.var_struct_class[param_name] = found_struct
|
||||
# 普通类注解形参(非 BinOp 联合):rawptr[X] / CPtr[X] / X / X
|
||||
# 类注释形参:rawptr[X] / CPtr[X] / X
|
||||
# 一律按"声明类"登记 var_struct_class。避免按 param.type.pointee 匹配
|
||||
# 到泛型父特化(如 class Function(GSListNode[Function]) 的形参 func 被
|
||||
# 登记成 GSListNode[Function],其 struct 仅含 Next → func.Blocks 访问
|
||||
@@ -2011,7 +1903,10 @@ class FunctionHandle(BaseHandle):
|
||||
if arg.annotation is None:
|
||||
continue
|
||||
if isinstance(arg.annotation, ast.BinOp) and isinstance(arg.annotation.op, ast.BitOr):
|
||||
continue # 联合注解由上方循环处理
|
||||
Line: int = getattr(arg.annotation, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
param_name = ParamNames[i] if i < len(ParamNames) else arg.arg
|
||||
if param_name not in Gen.variables:
|
||||
continue
|
||||
@@ -2024,8 +1919,10 @@ class FunctionHandle(BaseHandle):
|
||||
elif isinstance(ann, ast.Subscript):
|
||||
subv = ann.value
|
||||
subname = getattr(subv, 'id', None) or getattr(subv, 'attr', '')
|
||||
if subname in ('rawptr', 'CPtr', 'Ptr'):
|
||||
if subname in ('rawptr', 'CPtr', 'Ptr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
slc = ann.slice
|
||||
while isinstance(slc, ast.Subscript):
|
||||
slc = slc.value
|
||||
if isinstance(slc, ast.Name):
|
||||
target = slc.id
|
||||
elif isinstance(slc, ast.Attribute):
|
||||
@@ -2184,9 +2081,11 @@ class FunctionHandle(BaseHandle):
|
||||
_is_ret_or_ctrl_tail: bool = isinstance(_last_stmt, (
|
||||
ast.Return, ast.If, ast.Match, ast.While, ast.For, ast.Try, ast.With))
|
||||
if Node.returns is not None and not _is_ret_or_ctrl_tail:
|
||||
# void(None / CVoid,含 | 联合)/ extern|export 声明型辅助符号
|
||||
# void(None / CVoid)/ extern|export 声明型辅助符号
|
||||
# (State / CExport / CExtern)→ 掉出合法,不 fail-fast
|
||||
if not _IsVoidOrDeclAnnotation(Node.returns):
|
||||
_DeclMarkers: tuple[str, ...] = getattr(Node, 'Markers', None) or ()
|
||||
_IsDecl: bool = any(m in ('state', 'export', 'extern') for m in _DeclMarkers)
|
||||
if not _IsDecl and not _IsVoidOrDeclAnnotation(Node.returns):
|
||||
raise Exception(
|
||||
f"函数 {Node.name} 声明了返回类型但函数体可能掉出末尾(缺少 return 语句);"
|
||||
f"普通语句掉出末尾 + 有返回注解属于定义缺陷,请补显式 return")
|
||||
|
||||
@@ -1404,7 +1404,7 @@ class ImportHandle(BaseHandle):
|
||||
if Node.value:
|
||||
ValueTypeInfo = None
|
||||
if isinstance(Node.value, ast.BinOp) and isinstance(Node.value.op, ast.BitOr):
|
||||
ValueTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.value)
|
||||
ValueTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.value)
|
||||
else:
|
||||
ValueTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.value)
|
||||
if isinstance(ValueTypeInfo, CTypeInfo) and (ValueTypeInfo.BaseType or ValueTypeInfo.PtrCount > 0):
|
||||
|
||||
@@ -2,11 +2,9 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
from typing import List
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode, RejectTypeUnion,
|
||||
DesugarPtrSubscriptToUnion)
|
||||
IsListAnnotation, IsPtrSubscriptNode, IsCPtrMarkerNode)
|
||||
from lib.core import TypeSystem
|
||||
import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib)
|
||||
import vast as ast
|
||||
@@ -25,19 +23,67 @@ class HandlesTypeMerge(BaseHandle):
|
||||
"""直接从类型名构造 CTypeInfo,不经过 FromStr/字符串解析"""
|
||||
return CTypeInfo.FromTypeName(TypeName)
|
||||
|
||||
_STORAGE_MARKER_CLASSES: dict[str, str] = {
|
||||
'static': 'CStatic',
|
||||
'export': 'CExport',
|
||||
'extern': 'CExtern',
|
||||
'inline': 'CInline',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _ApplyTypeModifiers(Info: CTypeInfo, Node: ast.AST) -> CTypeInfo:
|
||||
"""把注解节点上的 Markers / ByteOrder / BitWidth 写入 CTypeInfo。"""
|
||||
Markers: tuple[str, ...] = getattr(Node, 'Markers', None) or ()
|
||||
ByteOrder: str | None = getattr(Node, 'ByteOrder', None)
|
||||
BitWidth: int | None = getattr(Node, 'BitWidth', None)
|
||||
if not Markers and not ByteOrder and not BitWidth:
|
||||
return Info
|
||||
Info = Info.Copy()
|
||||
for Marker in Markers:
|
||||
if Marker == 'const':
|
||||
Info.DataConst = True
|
||||
elif Marker == 'volatile':
|
||||
Info.DataVolatile = True
|
||||
elif Marker == 'state':
|
||||
Info.IsState = True
|
||||
elif Marker == 'define':
|
||||
Info.IsDefine = True
|
||||
elif Marker == 'typedef':
|
||||
Info.IsTypedef = True
|
||||
else:
|
||||
StorageClassName: str | None = HandlesTypeMerge._STORAGE_MARKER_CLASSES.get(Marker)
|
||||
if StorageClassName:
|
||||
Info.Storage = getattr(TypeSystem, StorageClassName)()
|
||||
if ByteOrder:
|
||||
Info.ByteOrder = ByteOrder
|
||||
if BitWidth:
|
||||
Info.IsBitField = True
|
||||
Info.BitWidth = BitWidth
|
||||
return Info
|
||||
|
||||
def GetCTypeInfo(self, Node: ast.AST) -> CTypeInfo:
|
||||
"""获取 CTypeInfo 对象"""
|
||||
RejectTypeUnion(Node)
|
||||
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
Result = self._GetCTypeInfoInternal(Node)
|
||||
if isinstance(Result, CTypeInfo):
|
||||
return Result
|
||||
Info = Result
|
||||
elif isinstance(Result, str):
|
||||
return self._MakeCTypeInfoFromName(Result)
|
||||
Info = self._MakeCTypeInfoFromName(Result)
|
||||
else:
|
||||
return self._MakeVoidCTypeInfo()
|
||||
Info = self._MakeVoidCTypeInfo()
|
||||
return self._ApplyTypeModifiers(Info, Node)
|
||||
|
||||
def _GetCTypeInfoInternal(self, Node: ast.AST) -> CTypeInfo | str | None:
|
||||
"""鍐呴儴鏂规硶锛岃繑鍥?CTypeInfo"""
|
||||
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
LineNum = getattr(Node, 'lineno', None)
|
||||
|
||||
if getattr(self.Trans, 'DebugFile', None):
|
||||
@@ -409,9 +455,6 @@ class HandlesTypeMerge(BaseHandle):
|
||||
return Result
|
||||
return self._HandleSubscript(Node)
|
||||
|
||||
elif isinstance(Node, ast.BinOp):
|
||||
return self.MergeTypes(Node)
|
||||
|
||||
elif isinstance(Node, ast.List):
|
||||
if Node.elts:
|
||||
BaseTypes = []
|
||||
@@ -427,6 +470,27 @@ class HandlesTypeMerge(BaseHandle):
|
||||
|
||||
return self._MakeVoidCTypeInfo()
|
||||
|
||||
def _ResolvePtrSubscript(self, Node: ast.Subscript) -> CTypeInfo:
|
||||
"""`CPtr[T]` / `rawptr[T]` → Ptr(T):struct 基类型吸收一层,其余逐层外包。"""
|
||||
Inner: CTypeInfo = self.GetCTypeInfo(Node.slice)
|
||||
Result: CTypeInfo = Inner.Copy()
|
||||
if not Result.BaseType:
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
if not (Result.IsStruct and Result.PtrCount > 0):
|
||||
Result.PtrCount += 1
|
||||
return Result
|
||||
|
||||
def _ResolveRefSubscript(self, Node: ast.Subscript, MarkerName: str) -> CTypeInfo:
|
||||
"""`CRef[T]` / `CTempRef[T]` / `CArrayPtr[T]` / `CAutoPtr[T]` → Ptr(T)。"""
|
||||
Inner: CTypeInfo = self.GetCTypeInfo(Node.slice)
|
||||
Result: CTypeInfo = Inner.Copy()
|
||||
if not Result.BaseType:
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
Result.PtrCount += 1
|
||||
if MarkerName == 'CArrayPtr':
|
||||
Result.IsArrayPtr = True
|
||||
return Result
|
||||
|
||||
def _HandleSubscript(self, Node: ast.Subscript) -> CTypeInfo:
|
||||
"""澶勭悊 Subscript 鑺傜偣锛屼娇鐢?CTypeInfo 鏍戝舰缁撴瀯鍒嗘瀽 AST
|
||||
|
||||
@@ -437,13 +501,17 @@ class HandlesTypeMerge(BaseHandle):
|
||||
CPtr[CArrayPtr[CArrayPtr]] -> void *(*(*))[]
|
||||
"""
|
||||
# 指针下标(rawptr[T] 内置裸指针 / CPtr[T] 下标指针,含裸名 CPtr[T])
|
||||
# 折叠为等价的联合写法 `T | CPtr` 后交给 MergeTypes 统一解析:内层 T
|
||||
# 因此走通用解析路径(含跨模块类经 Gen.structs 反查 SHA1 前缀),指针
|
||||
# 层数与源码 `T | CPtr` 完全一致(此前 CPtr[ast.AST] 在此得
|
||||
# AST**(比 declare/`AST | CPtr` 多一层)、rawptr[ast.AST] 退化为
|
||||
# CVoid/1 → i8*)。
|
||||
# 内层 T 走通用解析路径(含跨模块类经 Gen.structs 反查 SHA1 前缀);
|
||||
# 裸类引用自身即指针,吸收这一层,其余逐层外包。
|
||||
if IsPtrSubscriptNode(Node, self.Trans.SymbolTable):
|
||||
return self.MergeTypes(DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable))
|
||||
return self._ResolvePtrSubscript(Node)
|
||||
MarkerName: str | None = None
|
||||
if isinstance(Node.value, ast.Name):
|
||||
MarkerName = Node.value.id
|
||||
elif isinstance(Node.value, ast.Attribute):
|
||||
MarkerName = Node.value.attr
|
||||
if MarkerName in ('CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
return self._ResolveRefSubscript(Node, MarkerName)
|
||||
|
||||
# 判据自洽守卫(fail-fast):base 是指针标记(`rawptr` / `CPtr` / 裸名
|
||||
# `CPtr` / 别名 `X[...]`,见 IsPtrSubscriptNode)却被上面那条判据漏掉 ⇒
|
||||
@@ -571,14 +639,6 @@ class HandlesTypeMerge(BaseHandle):
|
||||
ResultInfo.ArrayPtr = inner
|
||||
else:
|
||||
ResultInfo.BaseType = CTypeInfo.CreateFromTypeName(slice_node.id).BaseType
|
||||
elif isinstance(slice_node, ast.BinOp):
|
||||
merged = self.MergeTypes(slice_node)
|
||||
if merged:
|
||||
ResultInfo.PtrCount += merged.PtrCount
|
||||
if merged.BaseType and not isinstance(merged.BaseType, TypeSystem.CVoid):
|
||||
ResultInfo.BaseType = merged.BaseType
|
||||
if merged.ArrayPtr:
|
||||
ResultInfo.ArrayPtr = merged.ArrayPtr
|
||||
elif isinstance(slice_node, ast.Constant):
|
||||
ResultInfo.ArrayDims.append(str(slice_node.value))
|
||||
elif VtInfo:
|
||||
@@ -809,279 +869,9 @@ class HandlesTypeMerge(BaseHandle):
|
||||
|
||||
return CollectAll(Node)
|
||||
|
||||
def _CollectAllOperandTypes(self, Node: ast.AST) -> List:
|
||||
"""递归收集所有操作数的类型(用于一次性合并)"""
|
||||
Types = []
|
||||
|
||||
# 指针下标(rawptr[T] / CPtr[T])先折叠成等价的 `T | CPtr`:使
|
||||
# `rawptr[T] | CPtr` 与 `T | CPtr | CPtr` 拉平成同一组操作数
|
||||
# (否则折叠结果作为单个 Subscript 操作数参与合并,指针层数少算一层);
|
||||
# CPtr[T] 与 rawptr[T] 同一条规则(见 SymbolUtils.IsPtrSubscriptNode)。
|
||||
if IsPtrSubscriptNode(Node, self.Trans.SymbolTable):
|
||||
Node = DesugarPtrSubscriptToUnion(Node, self.Trans.SymbolTable)
|
||||
|
||||
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
|
||||
Types.extend(self._CollectAllOperandTypes(Node.left))
|
||||
Types.extend(self._CollectAllOperandTypes(Node.right))
|
||||
else:
|
||||
Types.append(Node)
|
||||
|
||||
return Types
|
||||
|
||||
def _GetTypeFromNode(self, Node: ast.AST) -> CTypeInfo:
|
||||
"""浠?AST 鑺傜偣鑾峰彇绫诲瀷"""
|
||||
if isinstance(Node, ast.Call):
|
||||
if isinstance(Node.func, ast.Name) and Node.func.id == 'callable':
|
||||
return self.GetCTypeInfo(Node)
|
||||
elif isinstance(Node.func, ast.Attribute) and CTypeHelper.GetTModuleCType(Node.func.attr) == TypeSystem._CTypedef:
|
||||
return self.GetCTypeInfo(Node)
|
||||
elif isinstance(Node.func, ast.Attribute) and Node.func.attr == 'Bit':
|
||||
if Node.args and isinstance(Node.args[0], ast.Constant):
|
||||
Result = CTypeInfo()
|
||||
Result.BaseType = TypeSystem.CInt
|
||||
Result.IsBitField = True
|
||||
Result.BitWidth = Node.args[0].value
|
||||
return Result
|
||||
return self._MakeVoidCTypeInfo()
|
||||
elif isinstance(Node, ast.Subscript):
|
||||
if (isinstance(Node.value, ast.Attribute)
|
||||
and isinstance(Node.value.value, ast.Name)
|
||||
|
||||
and Node.value.attr == 'Bit'):
|
||||
if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int):
|
||||
Result = CTypeInfo()
|
||||
Result.BaseType = TypeSystem.CInt
|
||||
Result.IsBitField = True
|
||||
Result.BitWidth = Node.slice.value
|
||||
return Result
|
||||
return self.GetCTypeInfo(Node)
|
||||
else:
|
||||
return self.GetCTypeInfo(Node)
|
||||
|
||||
def MergeTypes(self, Node: ast.BinOp):
|
||||
"""处理类型组合,如 CInt | CPtr ?CStatic | CInt
|
||||
|
||||
这是 | 运算符的类型合并处理函数
|
||||
收集所有操作数,一次性合?
|
||||
"""
|
||||
if not isinstance(Node, ast.BinOp) or not isinstance(Node.op, ast.BitOr):
|
||||
return None
|
||||
|
||||
AllOperands = self._CollectAllOperandTypes(Node)
|
||||
|
||||
AllTypes = []
|
||||
for Operand in AllOperands:
|
||||
TypeItem = self._GetTypeFromNode(Operand)
|
||||
AllTypes.append(TypeItem)
|
||||
|
||||
if isinstance(Node.left, ast.Attribute):
|
||||
LeftParts = []
|
||||
current = Node.left
|
||||
while isinstance(current, ast.Attribute):
|
||||
attr_type = getattr(TypeSystem, current.attr, None)
|
||||
if attr_type and isinstance(attr_type, type) and issubclass(attr_type, TypeSystem.CType):
|
||||
LeftParts.insert(0, attr_type)
|
||||
current = current.value
|
||||
if isinstance(current, ast.Name):
|
||||
name_type = getattr(TypeSystem, current.id, None)
|
||||
if name_type and isinstance(name_type, type) and issubclass(name_type, TypeSystem.CType):
|
||||
LeftParts.insert(0, name_type)
|
||||
if LeftParts and LeftParts[-1] == TypeSystem._CTypedef:
|
||||
for type_item in AllTypes:
|
||||
if isinstance(type_item, CTypeInfo) and type_item.IsFuncPtr:
|
||||
type_item.IsTypedef = True
|
||||
type_item.OriginalType = CTypeInfo()
|
||||
type_item.OriginalType.IsFuncPtr = True
|
||||
type_item.OriginalType.FuncPtrReturn = type_item.FuncPtrReturn or CTypeInfo.VoidTypeInfo()
|
||||
type_item.OriginalType.FuncPtrParams = list(type_item.FuncPtrParams) if type_item.FuncPtrParams else []
|
||||
return type_item
|
||||
Result = CTypeInfo()
|
||||
if isinstance(AllTypes[-1], CTypeInfo):
|
||||
Result.BaseType = AllTypes[-1].BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CInt
|
||||
Result.IsTypedef = True
|
||||
return Result
|
||||
|
||||
return self._MergeAllComponentTypes(*AllTypes)
|
||||
|
||||
def _MergeAllComponentTypes(self, *Types: CTypeInfo) -> CTypeInfo:
|
||||
"""合并多个类型 - 直接使用 CTypeInfo 类"""
|
||||
if not Types:
|
||||
return CTypeInfo()
|
||||
|
||||
Result = CTypeInfo()
|
||||
# 统计 CPtr(CVoid + PtrCount=1)的个数,用于正确累加指针层数
|
||||
# 因为 (AST | CPtr) | CPtr 展开后会包含多个 CPtr,每个都需要累加
|
||||
cptr_count: int = 0
|
||||
|
||||
for TypeItem in Types:
|
||||
if TypeItem is None:
|
||||
continue
|
||||
if TypeItem.IsDefine:
|
||||
# CDefine 标记在 | 合并中传播(对齐 IsState):
|
||||
# `int | CDefine`(define 宏函数返回注解)合并后仍保持
|
||||
# IsDefine=True,下游才能识别为编译期宏(alwaysinline/#define)
|
||||
Result.IsDefine = True
|
||||
if TypeItem.IsState:
|
||||
Result.IsState = True
|
||||
if not Result.Storage:
|
||||
Result.Storage = TypeSystem.CExport()
|
||||
continue
|
||||
if TypeItem.IsBitField:
|
||||
Result.BaseType = TypeSystem.CInt
|
||||
Result.IsBitField = True
|
||||
Result.BitWidth = TypeItem.BitWidth
|
||||
return Result
|
||||
if TypeItem.IsFuncPtr:
|
||||
Result.BaseType = TypeSystem.CVoid
|
||||
Result.IsFuncPtr = True
|
||||
Result.FuncPtrParams = TypeItem.FuncPtrParams
|
||||
Result.FuncPtrReturn = TypeItem.FuncPtrReturn
|
||||
return Result
|
||||
if TypeItem.IsTypedef:
|
||||
if TypeItem.BaseType and (not isinstance(TypeItem.BaseType, (TypeSystem._CTypedef,)) or TypeItem.PtrCount > 0):
|
||||
if Result.BaseType is None or isinstance(Result.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
|
||||
Result.BaseType = TypeItem.BaseType
|
||||
Result.Name = TypeItem.Name
|
||||
Result.IsTypedef = True
|
||||
Result.PtrCount = max(Result.PtrCount, TypeItem.PtrCount)
|
||||
if TypeItem.OriginalType:
|
||||
Result.OriginalType = TypeItem.OriginalType
|
||||
else:
|
||||
Result.IsTypedef = True
|
||||
Result.Name = TypeItem.Name
|
||||
if TypeItem.OriginalType:
|
||||
Result.OriginalType = TypeItem.OriginalType
|
||||
continue
|
||||
# 统计 CPtr(CVoid + PtrCount>0)
|
||||
# 注意: CPtr[CPtr] 的 PtrCount=2(双重指针),需要完整累加
|
||||
if TypeItem.PtrCount > 0 and TypeItem.BaseType and (TypeItem.BaseType is TypeSystem.CVoid or isinstance(TypeItem.BaseType, TypeSystem.CVoid)):
|
||||
cptr_count += TypeItem.PtrCount
|
||||
# BaseType 保持不变,只计数,后续统一累加
|
||||
if TypeItem.IsRenum and TypeItem.Name:
|
||||
Result.IsRenum = True
|
||||
Result.IsEnum = True
|
||||
Result.IsStruct = True
|
||||
if not Result.Name:
|
||||
Result.Name = TypeItem.Name
|
||||
continue
|
||||
self._MergeCTypeInfoInto(Result, TypeItem)
|
||||
|
||||
# 对所有 CPtr 统一累加指针层数
|
||||
# 仅对 struct 类型吸收第一个 CPtr(struct 变量默认是指针,AST | CPtr = AST*)。
|
||||
# 对于本身已是指针的类型(如 bytes=CChar*),bytes | CPtr = i8**(不吸收)。
|
||||
base_ptr_count: int = Result.PtrCount
|
||||
Result.PtrCount += cptr_count
|
||||
if Result.IsStruct and base_ptr_count > 0 and cptr_count > 0:
|
||||
Result.PtrCount -= 1
|
||||
|
||||
if Result.BaseType is None:
|
||||
Result.BaseType = TypeSystem.CVoid
|
||||
|
||||
return Result
|
||||
|
||||
def _MergeCTypeInfoInto(self, Target: CTypeInfo, Source: CTypeInfo):
|
||||
if Source.PtrCount > 0 and Source.BaseType and (Source.BaseType is TypeSystem.CVoid or isinstance(Source.BaseType, TypeSystem.CVoid)):
|
||||
# CPtr 的处理已提升到 _MergeAllComponentTypes 中统一计数累加,
|
||||
# 此处保留仅作为兜底(从其他路径直接调用 _MergeCTypeInfoInto 时)
|
||||
if Target.PtrCount < Source.PtrCount:
|
||||
Target.PtrCount = Source.PtrCount
|
||||
elif Source.PtrCount > 0 and Source.BaseType and Source.BaseType is not TypeSystem.CVoid and not isinstance(Source.BaseType, TypeSystem.CVoid):
|
||||
if Target.BaseType is None or Target.BaseType is TypeSystem.CVoid or isinstance(Target.BaseType, TypeSystem.CVoid):
|
||||
Target.BaseType = Source.BaseType
|
||||
# 当 Target 已有 PtrCount(来自之前的 CPtr),累加而非替换
|
||||
Target.PtrCount = Source.PtrCount + Target.PtrCount
|
||||
elif Target.PtrCount == 0:
|
||||
Target.PtrCount = Source.PtrCount
|
||||
elif Source.PtrCount > Target.PtrCount:
|
||||
Target.PtrCount = Source.PtrCount
|
||||
elif Source.PtrCount > Target.PtrCount:
|
||||
Target.PtrCount = Source.PtrCount
|
||||
if Source.BaseType and Source.BaseType is not TypeSystem.CVoid and not isinstance(Source.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
|
||||
if Target.BaseType is None:
|
||||
Target.BaseType = Source.BaseType
|
||||
elif (Target.BaseType is TypeSystem.CVoid or isinstance(Target.BaseType, TypeSystem.CVoid)) and Target.PtrCount == 0:
|
||||
Target.BaseType = Source.BaseType
|
||||
elif (Source.BaseType is TypeSystem.CVoid or isinstance(Source.BaseType, TypeSystem.CVoid)) and Target.BaseType is None:
|
||||
Target.BaseType = Source.BaseType
|
||||
# Struct 名称保留:BinOp `list[AST | CPtr] | CPtr` 合并时,
|
||||
# _HandleSubscript 已在 Source.Name 设置了特化名(如 'list[5dab8cb390496d22.ASTptr]'),
|
||||
# 合并后 Target.Name 必须保留此名称,否则 class_member_element_class
|
||||
# 无法获取正确的特化类名 → 方法分派 fallback 到错误的类
|
||||
if Source.IsStruct and Source.Name and not Target.Name:
|
||||
Target.Name = Source.Name
|
||||
# 【IsStruct 必须随 Name 一起传播】`_MergeAllComponentTypes` 的
|
||||
# "struct 吸收第一个 CPtr"规则(见该函数 :1022-1027 的注释:
|
||||
# struct 变量默认是指针 ⇒ `AST | CPtr = AST*`)以 `Result.IsStruct` 为**闸门**:
|
||||
# 此前本函数只复制 Name、从不置 IsStruct ⇒ 闸门恒假 ⇒ 闸门后的
|
||||
# `Result.PtrCount -= 1` 永不执行 ⇒ 「类 + CPtr」的联合(如
|
||||
# `list[str] | CPtr`)合并后指针层数**多算一层**(得 `list[str]**`,应为
|
||||
# `list[str]*`)⇒ 调用点/字段拿到的值类型 pointee 是指针而不是结构体 ⇒
|
||||
# 类名在下游被当作通用指针处理(现场:`parts = s1.split(',')` 的返回值
|
||||
# pointee 非结构体 ⇒ HandlesAssign 的类名推断整块跳过 ⇒ 随后 `parts[0]`
|
||||
# 退化成按字节索引并得到整数)。
|
||||
# 语义上这两个标志同源(合并结果就是那个 struct),故成对传播。
|
||||
if Source.IsStruct:
|
||||
Target.IsStruct = True
|
||||
# REnum 标志和名称保留(BinOp `LLVMType | CPtr` 合并时不能丢失 REnum 语义)
|
||||
# 同时传播 IsStruct=True,让 CPtr 吸收逻辑生效(REnum 在内存布局上是 struct)
|
||||
if Source.IsRenum and Source.Name:
|
||||
Target.IsRenum = True
|
||||
Target.IsEnum = True
|
||||
Target.IsStruct = True
|
||||
if not Target.Name:
|
||||
Target.Name = Source.Name
|
||||
if Source.IsTypedef and Source.Name:
|
||||
if Source.BaseType and (not isinstance(Source.BaseType, (TypeSystem._CTypedef,)) or Source.PtrCount > 0):
|
||||
if Target.BaseType is None or isinstance(Target.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
|
||||
Target.BaseType = Source.BaseType
|
||||
Target.IsTypedef = True
|
||||
Target.Name = Source.Name
|
||||
if Source.OriginalType:
|
||||
Target.OriginalType = Source.OriginalType
|
||||
elif Target.BaseType is None or isinstance(Target.BaseType, (TypeSystem.CVoid, TypeSystem._CTypedef)):
|
||||
if Source.OriginalType:
|
||||
if isinstance(Source.OriginalType, CTypeInfo) and Source.OriginalType.BaseType:
|
||||
Target.BaseType = Source.OriginalType.BaseType
|
||||
Target.PtrCount = max(Target.PtrCount, Source.OriginalType.PtrCount)
|
||||
Target.IsTypedef = True
|
||||
Target.Name = Source.Name
|
||||
Target.OriginalType = Source.OriginalType
|
||||
elif isinstance(Source.OriginalType, CTypeInfo):
|
||||
Target.IsTypedef = True
|
||||
Target.Name = Source.Name
|
||||
Target.OriginalType = Source.OriginalType
|
||||
else:
|
||||
Target.BaseType = TypeSystem.CStruct(name=Source.Name)
|
||||
Target.IsStruct = True
|
||||
else:
|
||||
Target.BaseType = TypeSystem.CStruct(name=Source.Name)
|
||||
Target.IsStruct = True
|
||||
if Source.ArrayPtr:
|
||||
if Target.ArrayPtr is None:
|
||||
Target.ArrayPtr = Source.ArrayPtr
|
||||
else:
|
||||
if Source.PtrCount > Target.PtrCount:
|
||||
Target.PtrCount = Source.PtrCount
|
||||
Target.ArrayPtr = Source.ArrayPtr
|
||||
if Source.PtrCount > 0:
|
||||
Target.ArrayDims = []
|
||||
elif Source.ArrayDims:
|
||||
Target.ArrayDims.extend(Source.ArrayDims)
|
||||
if Source.VarConst:
|
||||
Target.VarConst = True
|
||||
if Source.VarVolatile:
|
||||
Target.VarVolatile = True
|
||||
if Source.DataConst:
|
||||
Target.DataConst = True
|
||||
if Source.DataVolatile:
|
||||
Target.DataVolatile = True
|
||||
if Source.IsFuncPtr:
|
||||
Target.IsFuncPtr = True
|
||||
Target.FuncPtrParams = Source.FuncPtrParams
|
||||
Target.FuncPtrReturn = Source.FuncPtrReturn
|
||||
if Source.Storage and not Target.Storage:
|
||||
Target.Storage = Source.Storage
|
||||
if Source.ByteOrder and not Target.ByteOrder:
|
||||
Target.ByteOrder = Source.ByteOrder
|
||||
def MergeTypes(self, Node: ast.BinOp) -> None:
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
+63
-121
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
|
||||
from lib.core.SymbolUtils import (
|
||||
IsListAnnotation, RejectTypeUnion, IsCPtrNode, IsCPtrSubscriptNode,
|
||||
IsListAnnotation, IsCPtrSubscriptNode,
|
||||
IsRawPtrSubscriptNode, EnumIntWidth,
|
||||
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
|
||||
from lib.core import TypeSystem as _t
|
||||
@@ -116,61 +116,63 @@ class LLVMTypeMapper:
|
||||
# 公共 API
|
||||
# ==================================================================
|
||||
|
||||
@staticmethod
|
||||
def _RejectTypeUnion(node: ast.AST) -> None:
|
||||
"""遇到 `T1 | T2` 类型联合立即 fail-fast。"""
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
Line: int = getattr(node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
|
||||
def get_llvm_type_str(self, node: ast.AST | None) -> str:
|
||||
"""将 AST 注解节点转换为 LLVM IR 类型字符串"""
|
||||
if node is None:
|
||||
self._symtab.diagnostics.warn('', 0, "类型注解为 None,回退到 i32")
|
||||
return 'i32'
|
||||
RejectTypeUnion(node)
|
||||
self._RejectTypeUnion(node)
|
||||
result: str
|
||||
if isinstance(node, ast.Name):
|
||||
return self._resolve_name(node)
|
||||
result = self._resolve_name(node)
|
||||
elif isinstance(node, ast.Attribute):
|
||||
return self._resolve_attribute(node)
|
||||
result = self._resolve_attribute(node)
|
||||
elif isinstance(node, ast.Subscript):
|
||||
return self._resolve_subscript(node)
|
||||
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
return self._resolve_bitor(node)
|
||||
result = self._resolve_subscript(node)
|
||||
elif isinstance(node, ast.Constant):
|
||||
if isinstance(node.value, bool):
|
||||
return 'i8'
|
||||
return 'i32'
|
||||
result = 'i8' if isinstance(node.value, bool) else 'i32'
|
||||
elif isinstance(node, ast.Call):
|
||||
return self._resolve_call(node)
|
||||
self._symtab.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32")
|
||||
return 'i32'
|
||||
result = self._resolve_call(node)
|
||||
else:
|
||||
self._symtab.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32")
|
||||
result = 'i32'
|
||||
if not result and getattr(node, 'BitWidth', None):
|
||||
return 'i32'
|
||||
return result
|
||||
|
||||
def get_func_ret_type_str(self, returns_node: ast.AST | None) -> str:
|
||||
"""提取函数返回类型的 LLVM 字符串"""
|
||||
if returns_node is None:
|
||||
return 'i32'
|
||||
if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr):
|
||||
# 统一走 CPtr 感知的联合解析(int | CPtr → i32*、str | CPtr → i8**)
|
||||
return self._resolve_bitor(returns_node)
|
||||
result: str = self.get_llvm_type_str(returns_node)
|
||||
return result if result else 'i32'
|
||||
|
||||
def get_func_param_type_str(self, annotation_node: ast.AST | None) -> str:
|
||||
"""提取函数参数类型的 LLVM 字符串。
|
||||
|
||||
末尾的「不许静默变 i32」守卫:`Subscript` / 联合(`|`)形态的形参注解若解析结果
|
||||
末尾的「不许静默变 i32」守卫:`Subscript` 形态的形参注解若解析结果
|
||||
是 `'i32'`,只可能是**解析失败后的兜底** —— 合法的下标注解是容器 / 泛型 / 定长数组
|
||||
(解析出指针、数组或结构体指针),合法的联合写法是 `T | CPtr` 这类指针叠加,都
|
||||
不会是 i32。该串会被 `_InsertFuncSymbol` 原样存进符号表(`FuncPtrParams`),再由
|
||||
`BuildLLVMFuncTypeFromSig` 物化成形参类型 —— 一旦是 i32,调用点就在 `_adjust_args`
|
||||
报「实参 %X* 不能隐式转为 i32」,把真因(**注解没解析出来**)掩盖成"调用点类型
|
||||
不匹配"(现场:CallGenMixin.vp:149 调用 `_specialize_generic_class` 的
|
||||
`type_args: list[str]*`)。故此处响亮失败,并带上注解原文。
|
||||
(解析出指针、数组或结构体指针),不会是 i32。该串会被 `_InsertFuncSymbol` 原样存进
|
||||
符号表(`FuncPtrParams`),再由 `BuildLLVMFuncTypeFromSig` 物化成形参类型 —— 一旦是
|
||||
i32,调用点就在 `_adjust_args` 报「实参 %X* 不能隐式转为 i32」,把真因(**注解没
|
||||
解析出来**)掩盖成"调用点类型不匹配"(现场:CallGenMixin.vp:149 调用
|
||||
`_specialize_generic_class` 的 `type_args: list[str]*`)。故此处响亮失败,并带上
|
||||
注解原文。
|
||||
"""
|
||||
if annotation_node is None:
|
||||
return 'i8*'
|
||||
result: str
|
||||
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
|
||||
# 统一走 CPtr 感知的联合解析
|
||||
result = self._resolve_bitor(annotation_node)
|
||||
else:
|
||||
result = self.get_llvm_type_str(annotation_node)
|
||||
if not result:
|
||||
result = 'i8*'
|
||||
result: str = self.get_llvm_type_str(annotation_node)
|
||||
if not result:
|
||||
result = 'i8*'
|
||||
if result == 'i32' and isinstance(annotation_node, (ast.Subscript, ast.BinOp)):
|
||||
_text: str
|
||||
try:
|
||||
@@ -178,7 +180,7 @@ class LLVMTypeMapper:
|
||||
except Exception:
|
||||
_text = f'<{type(annotation_node).__name__}>'
|
||||
raise TypeNameUnresolvedError(
|
||||
f"形参注解 '{_text}' 解析失败并落到 i32(下标 / 联合形态的合法结果应为"
|
||||
f"形参注解 '{_text}' 解析失败并落到 i32(下标形态的合法结果应为"
|
||||
f"指针、数组或结构体指针,不会是 i32)—— 拒绝静默降级为 i32")
|
||||
return result
|
||||
|
||||
@@ -186,6 +188,7 @@ class LLVMTypeMapper:
|
||||
"""解析 typedef 值表达式的 C 类型字符串"""
|
||||
if node is None:
|
||||
return ''
|
||||
self._RejectTypeUnion(node)
|
||||
if isinstance(node, ast.Name):
|
||||
if node.id in self._symtab:
|
||||
Entry: CTypeInfo = self._symtab[node.id]
|
||||
@@ -217,10 +220,7 @@ class LLVMTypeMapper:
|
||||
if node.attr == 'CPtr':
|
||||
return 'ptr'
|
||||
if node.attr in _TYPEDEF_VALUE_QUALIFIERS:
|
||||
# 类型限定符标记(const/volatile)本身不是类型:它只修饰 `|` 另一侧。
|
||||
# 旧写法 `CConst | char | CPtr` 靠 char 一侧掩盖了这一点;一旦写成
|
||||
# `CConst | str`(`const str`),把 'CConst' 当基类型会得到 'CConst *',
|
||||
# 于是别名登记失败、所有使用处报「裸名 … 无法解析为类型」。
|
||||
# 类型限定符标记(const/volatile)本身不是类型
|
||||
return ''
|
||||
CName: str | None = CTypeHelper.GetCName(node.attr)
|
||||
if CName == 'CPtr':
|
||||
@@ -228,28 +228,21 @@ class LLVMTypeMapper:
|
||||
if CName:
|
||||
return CName
|
||||
return ''
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
left_str: str = self.resolve_typedef_value_type(node.left)
|
||||
right_str: str = self.resolve_typedef_value_type(node.right)
|
||||
# 限定符侧解析为空串 ⇒ 另一侧就是完整类型(见 _TYPEDEF_VALUE_QUALIFIERS)。
|
||||
# 只在两侧都有类型信息时才按"基类型 + 指针标记"合并。
|
||||
if not left_str:
|
||||
return 'void *' if right_str == 'ptr' else right_str
|
||||
if not right_str:
|
||||
return 'void *' if left_str == 'ptr' else left_str
|
||||
if right_str == 'ptr' or right_str.endswith('*'):
|
||||
if left_str != 'ptr':
|
||||
return left_str + ' *'
|
||||
return right_str if right_str.endswith('*') else 'void *'
|
||||
if left_str == 'ptr' or left_str.endswith('*'):
|
||||
if right_str != 'ptr':
|
||||
return right_str + ' *'
|
||||
return left_str if left_str.endswith('*') else 'void *'
|
||||
if right_str not in ('ptr', 'void', 'i32', 'i64'):
|
||||
return right_str
|
||||
if left_str not in ('ptr', 'void', 'i32', 'i64'):
|
||||
return left_str
|
||||
return left_str if left_str else right_str
|
||||
if isinstance(node, ast.Subscript):
|
||||
BaseNode: ast.AST = node.value
|
||||
BaseName: str = ''
|
||||
if isinstance(BaseNode, ast.Name):
|
||||
BaseName = BaseNode.id
|
||||
elif isinstance(BaseNode, ast.Attribute):
|
||||
BaseName = BaseNode.attr
|
||||
if BaseName in ('CPtr', 'rawptr', 'CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
InnerType: str = self.resolve_typedef_value_type(node.slice)
|
||||
if not InnerType or InnerType == 'ptr':
|
||||
return 'void *'
|
||||
return InnerType + ' *'
|
||||
return ''
|
||||
if getattr(node, 'BitWidth', None):
|
||||
return 'CInt'
|
||||
return ''
|
||||
|
||||
# ==================================================================
|
||||
@@ -387,12 +380,9 @@ class LLVMTypeMapper:
|
||||
return builtin_llvm
|
||||
# 存储类 / 类型限定符标记(CExport/CExtern/CStatic/CInline/CConst/
|
||||
# CVolatile/State 等,均以 `from t import ...` 裸名出现):自身不是类型,
|
||||
# 只作标记 ⇒ 贡献空串,由 _resolve_bitor 取另一侧真实类型
|
||||
# (`CInt | CExport` → i32)。与 _resolve_attribute 的 marker 分支、
|
||||
# 只作标记 ⇒ 贡献空串。与 _resolve_attribute 的 marker 分支、
|
||||
# TypeAnnotationResolver._ResolveNameNode 的 STORAGE_CLASS/TYPE_QUALIFIER
|
||||
# 判定同口径。缺此分支时裸名标记会落到下方 fail-fast —— 而带前缀写作
|
||||
# `CExport` 时却能通过(走 Attribute 路径),同一语义两种写法结果不同。
|
||||
# 现场:Test/AstTest `def main() -> CInt | CExport`(第 108 行)。
|
||||
# 判定同口径。
|
||||
_marker_cls: object = getattr(_t, node.id, None)
|
||||
if (isinstance(_marker_cls, type) and _marker_cls is not _t.CType
|
||||
and issubclass(_marker_cls, _t.CType)):
|
||||
@@ -455,10 +445,16 @@ class LLVMTypeMapper:
|
||||
# TypeGenResolve.vp:2769-2790;void 首层归一化为 i8*)
|
||||
return self._add_pointer_level(self.get_llvm_type_str(node.slice))
|
||||
if IsRawPtrSubscriptNode(node):
|
||||
# rawptr[T](内置裸指针下标)≡ `T | CPtr`:与定义端 TypeMerge 的
|
||||
# 合并语义同口径(裸类引用自身即指针,吸收这一层;其余逐层外包)。
|
||||
# 此前只认 IsCPtrSubscriptNode → rawptr[T] 落到下方 warn 并退化成 i32。
|
||||
# rawptr[T](内置裸指针下标):裸类引用自身即指针,吸收这一层;
|
||||
# 其余逐层外包。
|
||||
return self._rawptr_subscript_type_str(node)
|
||||
MarkerName: str | None = None
|
||||
if isinstance(node.value, ast.Name):
|
||||
MarkerName = node.value.id
|
||||
elif isinstance(node.value, ast.Attribute):
|
||||
MarkerName = node.value.attr
|
||||
if MarkerName in ('CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
return self._add_pointer_level(self.get_llvm_type_str(node.slice))
|
||||
if IsListAnnotation(node):
|
||||
slice_node: ast.AST = node.slice
|
||||
elem_type: str
|
||||
@@ -484,41 +480,6 @@ class LLVMTypeMapper:
|
||||
self._symtab.diagnostics.warn('', 0, "无法解析 Subscript 类型,回退到 i32")
|
||||
return 'i32'
|
||||
|
||||
def _resolve_bitor(self, node: ast.BinOp) -> str:
|
||||
"""解析 ast.BinOp(BitOr) 节点(CPtr 感知的指针层级叠加)。
|
||||
|
||||
T | CPtr 一侧为 CPtr 标记时,另一侧追加一层 '*':
|
||||
int | CPtr → i32* (原逻辑误降级为 i8*)
|
||||
str | CPtr → i8** (原逻辑误降级为 i8*)
|
||||
(int | CPtr) | CPtr → i32**(嵌套递归叠加)
|
||||
T | CPtr[...] 一侧为下标指针类型时,另一侧叠加该下标的指针层级 N
|
||||
(N = 1 + 切片自身层数,不含 struct 吸收,对齐 VPC BinOp 下标分支
|
||||
TypeGenResolve.vp:2596-2639):
|
||||
CUInt8T | CPtr[CPtr] → i8**(原逻辑误降级为首段 i8)
|
||||
"""
|
||||
left: str = self.get_llvm_type_str(node.left)
|
||||
right: str = self.get_llvm_type_str(node.right)
|
||||
left_is_cptr: bool = IsCPtrNode(node.left)
|
||||
right_is_cptr: bool = IsCPtrNode(node.right)
|
||||
if right_is_cptr:
|
||||
return self._add_pointer_level(left)
|
||||
if left_is_cptr:
|
||||
return self._add_pointer_level(right)
|
||||
# CPtr[...] 下标指针标记:X | CPtr[...] → Ptr^N(X)
|
||||
if IsCPtrSubscriptNode(node.right):
|
||||
return self._add_pointer_levels(left, self._cptr_subscript_ptr_level(node.right))
|
||||
if IsCPtrSubscriptNode(node.left):
|
||||
return self._add_pointer_levels(right, self._cptr_subscript_ptr_level(node.left))
|
||||
if right and right.endswith('*'):
|
||||
return right
|
||||
if left and left.endswith('*'):
|
||||
return left
|
||||
if left and left not in ('i32', 'void', 'i64'):
|
||||
return left
|
||||
if right and right not in ('i32', 'void', 'i64'):
|
||||
return right
|
||||
return left if left else right
|
||||
|
||||
def _add_pointer_level(self, ty: str) -> str:
|
||||
"""给类型字符串追加一层指针 '*'(void/void* → i8*)。"""
|
||||
if not ty:
|
||||
@@ -539,31 +500,12 @@ class LLVMTypeMapper:
|
||||
"""
|
||||
inner: ast.AST = node.slice
|
||||
inner_type: str = self.get_llvm_type_str(inner)
|
||||
if (not isinstance(inner, ast.BinOp)
|
||||
and not IsRawPtrSubscriptNode(inner)
|
||||
if (not IsRawPtrSubscriptNode(inner)
|
||||
and not IsCPtrSubscriptNode(inner)
|
||||
and inner_type.startswith('%') and inner_type.endswith('*')):
|
||||
return inner_type
|
||||
return self._add_pointer_level(inner_type)
|
||||
|
||||
def _add_pointer_levels(self, ty: str, count: int) -> str:
|
||||
"""给类型字符串叠加 count 层指针(void/void* 首层归一化为 i8*)。"""
|
||||
result: str = ty
|
||||
for _ in range(count):
|
||||
result = self._add_pointer_level(result)
|
||||
return result
|
||||
|
||||
def _cptr_subscript_ptr_level(self, node: ast.AST) -> int:
|
||||
"""CPtr[T] 下标指针标记贡献的指针层级 N(= 1 + 切片自身层数)。
|
||||
|
||||
复用定义侧解析器 TypeAnnotationResolver.from_node(其 _from_node_subscript
|
||||
已实现 CPtr[T] → Ptr(T) 的层级叠加,见 TypeAnnotationResolver.py:756-783),
|
||||
与 HandlesTypeMerge._HandleSubscript(HandlesTypeMerge.py:512-531)同口径。
|
||||
调用前须经 IsCPtrSubscriptNode 判据过滤,故 PtrCount 至少为 1。
|
||||
"""
|
||||
from lib.core.TypeAnnotationResolver import TypeAnnotationResolver as _TAR
|
||||
return _TAR.from_node(node, self._symtab).PtrCount
|
||||
|
||||
def _resolve_call(self, node: ast.Call) -> str:
|
||||
"""解析 ast.Call 节点"""
|
||||
if isinstance(node.func, ast.Name):
|
||||
|
||||
@@ -10,7 +10,7 @@ from lib.core.SymbolData import (
|
||||
FuncSymbolData, DefineSymbolData, AnonymousTypeData
|
||||
)
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
from lib.core.SymbolUtils import AnnotationContainsMarker, CheckAnnotationHasCInline, AnnotationContainsName
|
||||
from lib.core.SymbolUtils import AnnotationContainsMarker
|
||||
from lib.core.SymbolUtils import EnumClassIntWidth, _ENUM_DEFAULT_INT_WIDTH
|
||||
from lib.core import TypeSystem
|
||||
|
||||
@@ -63,10 +63,6 @@ class ASTSymbolExtractor:
|
||||
if member_type is None:
|
||||
member_type = CTypeInfo()
|
||||
member_type.BaseType = TypeSystem.CInt()
|
||||
is_ptr: bool = member_type.IsPtr
|
||||
if isinstance(item.annotation, ast.BinOp):
|
||||
if AnnotationContainsName(item.annotation, 'CPtr'):
|
||||
is_ptr = True
|
||||
members[full_name] = member_type.Copy()
|
||||
|
||||
elif isinstance(item, ast.ClassDef):
|
||||
@@ -272,9 +268,14 @@ class ASTSymbolExtractor:
|
||||
def _extract_ann_assign(self, node: ast.AnnAssign, result: ModuleSymbols) -> None:
|
||||
"""从 AnnAssign 节点提取 typedef 或 define 数据"""
|
||||
var_name: str = node.target.id
|
||||
has_cdefine: bool = AnnotationContainsMarker(node.annotation, 'CDefine') if node.annotation else False
|
||||
has_postdef: bool = AnnotationContainsMarker(node.annotation, 'Postdefinition') if node.annotation else False
|
||||
has_ctypedef: bool = AnnotationContainsMarker(node.annotation, 'CTypedef') if node.annotation else False
|
||||
Markers: tuple[str, ...] = tuple(getattr(node, 'Markers', None) or ()) + tuple(
|
||||
getattr(node.annotation, 'Markers', None) or ())
|
||||
has_cdefine: bool = 'define' in Markers
|
||||
has_ctypedef: bool = 'typedef' in Markers
|
||||
has_postdef: bool = 'postdefinition' in Markers or (
|
||||
isinstance(node.annotation, ast.Call)
|
||||
and isinstance(node.annotation.func, ast.Attribute)
|
||||
and node.annotation.func.attr == 'Postdefinition')
|
||||
|
||||
if has_cdefine:
|
||||
result.defines.append(DefineSymbolData(
|
||||
@@ -305,7 +306,9 @@ class ASTSymbolExtractor:
|
||||
"""从 FunctionDef 节点提取函数符号数据"""
|
||||
params: list[tuple[str, ast.AST | None]] = [(arg.arg, arg.annotation) for arg in node.args.args]
|
||||
is_variadic: bool = node.args.vararg is not None
|
||||
is_inline: bool = CheckAnnotationHasCInline(node.returns)
|
||||
is_inline: bool = 'inline' in (getattr(node, 'Markers', None) or ()) or (
|
||||
node.returns is not None
|
||||
and 'inline' in (getattr(node.returns, 'Markers', None) or ()))
|
||||
|
||||
return FuncSymbolData(
|
||||
name=node.name,
|
||||
|
||||
@@ -146,49 +146,33 @@ class TypeResolver:
|
||||
self._resolve_typedef_from_value(td)
|
||||
|
||||
def _resolve_typedef_from_value(self, td: TypedefSymbolData):
|
||||
"""从值表达式解析 typedef 类型
|
||||
|
||||
BinOp(如 UINT | CPtr)优先于 _find_base_type 处理,
|
||||
因为 _find_base_type 是静态方法无法解析 Name 引用(如 UINT)。
|
||||
"""
|
||||
"""从值表达式解析 typedef 类型"""
|
||||
if not td.value:
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
return
|
||||
|
||||
# 优先处理 BinOp(_find_base_type 无法解析 Name 引用)
|
||||
if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr):
|
||||
left_type: str = self._resolve_type_expr(td.value.left)
|
||||
right_type: str = self._resolve_type_expr(td.value.right)
|
||||
is_ptr_type: bool = right_type == 'ptr' or left_type == 'ptr'
|
||||
if is_ptr_type:
|
||||
base_name: str = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '')
|
||||
original_type: str = (base_name + ' *') if base_name else 'void *'
|
||||
td.original_class = original_type
|
||||
td.original_type_kind = 'typedef'
|
||||
elif left_type:
|
||||
td.original_class = left_type
|
||||
td.original_type_kind = 'typedef'
|
||||
elif right_type:
|
||||
td.original_class = right_type
|
||||
td.original_type_kind = 'typedef'
|
||||
else:
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
return
|
||||
Line: int = getattr(td.value, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
|
||||
if isinstance(td.value, ast.Subscript):
|
||||
resolved_subscript: str = self._type_mapper.resolve_typedef_value_type(td.value)
|
||||
if resolved_subscript:
|
||||
td.original_class = resolved_subscript
|
||||
td.original_type_kind = 'typedef'
|
||||
return
|
||||
|
||||
# 非 BinOp:使用 _find_base_type
|
||||
value_base_type: str | None = self._find_base_type(td.value)
|
||||
_PTR_MODIFIERS: frozenset[str] = frozenset({'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'})
|
||||
|
||||
# 裸 CPtr(无 `|` 联合、无 `[T]` 下标):_find_base_type 把 node.attr == 'CPtr'
|
||||
# 裸 CPtr(无 `[T]` 下标):_find_base_type 把 node.attr == 'CPtr'
|
||||
# 归一化为指针标记 'ptr'(拼写与 _PTR_MODIFIERS 的 'CPtr' 不一致 ⇒ 下方守卫命不中),
|
||||
# 若让 'ptr' 落进 original_class,经 _InsertTypedefSymbol 存入 symtab.OriginalType 后
|
||||
# 会被 CTypeInfo.FromTypeName 当成 CStruct('ptr'),最终 _get_or_create_struct
|
||||
# 建出 %"<模块sha>.ptr" 不透明结构体(VLogger._console_handle: win32base.HANDLE
|
||||
# 报 "cannot store i8* to %"...ptr"*" 的根因)。按指针语义展开为 'void *',
|
||||
# 与改前 `CPtr` 联合分支等价(_InsertTypedefSymbol 同样把
|
||||
# 'CVoid *' 归一化为 'void *')。
|
||||
# 建出 %"<模块sha>.ptr" 不透明结构体。按指针语义展开为 'void *'。
|
||||
if value_base_type == 'ptr':
|
||||
td.original_type_kind = 'typedef'
|
||||
td.original_class = 'void *'
|
||||
@@ -254,17 +238,6 @@ class TypeResolver:
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
|
||||
def _resolve_type_expr(self, node: ast.AST) -> str:
|
||||
"""解析类型表达式为 C 类型名字符串,优先查本模块已解析的 typedef
|
||||
|
||||
解决同模块 typedef 间引用(如 UINTPTR = UINT | CPtr 中的 UINT)
|
||||
在 TypeResolver 阶段尚未插入 symtab 的问题。
|
||||
"""
|
||||
if isinstance(node, ast.Name):
|
||||
if node.id in self._resolved_typedefs:
|
||||
return self._resolved_typedefs[node.id] or ''
|
||||
return self._type_mapper.resolve_typedef_value_type(node)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 函数签名解析
|
||||
# ------------------------------------------------------------------
|
||||
@@ -349,27 +322,10 @@ class TypeResolver:
|
||||
if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and node.value.attr == 'Callable':
|
||||
return 'Callable'
|
||||
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
left_result: str | None = TypeResolver._find_base_type(node.left)
|
||||
if left_result == 'ptr':
|
||||
right_result: str | None = TypeResolver._find_base_type(node.right)
|
||||
return (right_result if right_result and right_result != 'ptr' else 'void') + ' *'
|
||||
if left_result == 'Callable':
|
||||
return 'Callable'
|
||||
right_result: str | None = TypeResolver._find_base_type(node.right)
|
||||
if right_result == 'ptr':
|
||||
return (left_result if left_result and left_result != 'ptr' else 'void') + ' *'
|
||||
if right_result == 'Callable':
|
||||
return 'Callable'
|
||||
# 类型拼接语义:CLong | CLong → CLongLong, CUnsignedLong | CLong → CUnsignedLongLong
|
||||
long_types: frozenset[str] = frozenset({'CLong', 'CUnsignedLong'})
|
||||
if left_result in long_types and right_result in long_types:
|
||||
if left_result == 'CUnsignedLong' or right_result == 'CUnsignedLong':
|
||||
return 'CUnsignedLongLong'
|
||||
return 'CLongLong'
|
||||
if left_result:
|
||||
return left_result
|
||||
if right_result:
|
||||
return right_result
|
||||
Line: int = getattr(node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
@@ -381,10 +337,8 @@ class TypeResolver:
|
||||
if node.args and isinstance(node.args[0], ast.Name):
|
||||
return node.args[0].id
|
||||
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
left_result: str | None = TypeResolver._find_postdef_arg(node.left)
|
||||
if left_result:
|
||||
return left_result
|
||||
right_result: str | None = TypeResolver._find_postdef_arg(node.right)
|
||||
if right_result:
|
||||
return right_result
|
||||
Line: int = getattr(node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
return None
|
||||
+52
-150
@@ -623,8 +623,8 @@ def _DesugarArrayPrefix(Tokens: list, BracketIdx: int, Count: int,
|
||||
|
||||
|
||||
# Bare C-style leading array declarator `[N]T` / `[]T` at annotation positions (no
|
||||
# descriptor), desugared to `CArray[T, N]` / `CArray[T, None]` — same shape as the
|
||||
# const/volatile path and VPC _parse_array_prefix_declarator.
|
||||
# descriptor), desugared to `CArray[T, N]` / `CArray[T, None]` — same shape as
|
||||
# VPC _parse_array_prefix_declarator.
|
||||
_ARRAY_PREFIX_HINT: str = (
|
||||
'`名字: [长度]元素类型`(长度可省略:`[]元素类型`);'
|
||||
'形参 / 返回值写作 `def f(p: [N]T) -> [M]U`'
|
||||
@@ -635,6 +635,14 @@ _ARRAY_PREFIX_EXAMPLE: str = (
|
||||
_ARRAY_STMT_BOUNDARY: tuple[int, ...] = (
|
||||
tokenize.NEWLINE, tokenize.INDENT, tokenize.DEDENT
|
||||
)
|
||||
# 注解位置的前置修饰词(由 vast 解析器原生解析为 AST 字段):数组前缀
|
||||
# `[N]T` 的注解位置判据需要跳过它们,例如 `const [80]uint64` /
|
||||
# `__attribute__(...) [N]T` / `BigEndian [2]uint16`。
|
||||
_ANNOTATION_PREFIX_WORDS: frozenset[str] = frozenset({
|
||||
'const', 'volatile', 'static', 'export', 'extern', 'inline',
|
||||
'BigEndian', 'LittleEndian',
|
||||
})
|
||||
_ANNOTATION_PREFIX_CALLS: frozenset[str] = frozenset({'__attribute__', 'Bit'})
|
||||
|
||||
|
||||
def _ArrayPrefixSyntaxError(Detail: str, Lineno: int, Col: int, Snippet: str) -> SyntaxError:
|
||||
@@ -684,14 +692,11 @@ def _AtAnnotationColon(Tokens: list, ColonIdx: int, Stack: list) -> bool:
|
||||
if BoundIdx < 0:
|
||||
return True
|
||||
Bound = Tokens[BoundIdx]
|
||||
# `export 名字: T` / `extern 名字: T` / `static 名字: T`(变量声明的存储类
|
||||
# 修饰符,见 _ExpandExportExternVar):修饰符与名字之间已构成语句起始,同样算
|
||||
# 注解位置。本判据必须在修饰符展开**之前**成立——`[N]T` 数组前缀与
|
||||
# `__attribute__(...)` 两条路径都先于该展开运行,靠它把
|
||||
# `export 名字: T` / `extern 名字: T` / `static 名字: T`(存储类修饰符,
|
||||
# 由 vast.Parser 原生解析):修饰符与名字之间已构成语句起始,同样算注解位置。
|
||||
# 本判据必须在数组前缀脱糖时成立——靠它把
|
||||
# `export gdt: [7]gdt_entry = []` / `static g: [7]int = []` 正常脱糖成
|
||||
# `CArray[...]` 形态(若等到展开后再插入 ` | CExport` / 前置 `CStatic | `,
|
||||
# `|` 不在 _TYPE_EXPR_STOP_TOKENS 中,会被并进数组元素类型 →
|
||||
# `CArray[gdt_entry | CExport, 7]`)。
|
||||
# `CArray[...]` 形态。
|
||||
if Bound.type == tokenize.NAME and Bound.string in _EXPORT_EXTERN_MODIFIERS:
|
||||
return True
|
||||
return Bound.type in _ARRAY_STMT_BOUNDARY or Bound.string == ';'
|
||||
@@ -703,17 +708,35 @@ def _InArrayAnnotationPosition(Tokens: list, Index: int, Stack: list) -> bool:
|
||||
Stack holds open brackets before Index as (char, open_index). AnnAssign / class
|
||||
field: ':' preceded by a (possibly dotted) target name at a statement boundary.
|
||||
Parameter: ':' inside a def's parameter paren. Return annotation: '->' before '['.
|
||||
Dict / slice / lambda colons are excluded so right-hand `[...]` literals stay put.
|
||||
Annotation prefix modifiers (const/volatile/... / __attribute__(...) / BigEndian /
|
||||
Bit(...)) between the delimiter and '[' are skipped. Dict / slice / lambda colons
|
||||
are excluded so right-hand `[...]` literals stay put.
|
||||
"""
|
||||
PrevIdx: int = _PrevSignificantTokenIndex(Tokens, Index)
|
||||
if PrevIdx < 0:
|
||||
j: int = _PrevSignificantTokenIndex(Tokens, Index)
|
||||
while j >= 0:
|
||||
Prev = Tokens[j]
|
||||
if Prev.type == tokenize.NAME and Prev.string in _ANNOTATION_PREFIX_WORDS:
|
||||
j = _PrevSignificantTokenIndex(Tokens, j)
|
||||
continue
|
||||
if Prev.type == tokenize.OP and Prev.string in (')', ']'):
|
||||
OpenIdx: int = _MatchOpenBracket(Tokens, j)
|
||||
if OpenIdx < 0:
|
||||
return False
|
||||
CalleeIdx: int = _PrevSignificantTokenIndex(Tokens, OpenIdx)
|
||||
if (CalleeIdx >= 0 and Tokens[CalleeIdx].type == tokenize.NAME
|
||||
and Tokens[CalleeIdx].string in _ANNOTATION_PREFIX_CALLS):
|
||||
j = _PrevSignificantTokenIndex(Tokens, CalleeIdx)
|
||||
continue
|
||||
return False
|
||||
break
|
||||
if j < 0:
|
||||
return False
|
||||
Prev = Tokens[PrevIdx]
|
||||
Prev = Tokens[j]
|
||||
if Prev.string == '->':
|
||||
return True
|
||||
if Prev.string != ':':
|
||||
return False
|
||||
return _AtAnnotationColon(Tokens, PrevIdx, Stack)
|
||||
return _AtAnnotationColon(Tokens, j, Stack)
|
||||
|
||||
|
||||
def _ApplySameLineEdits(Code: str, Edits: list[tuple[int, int, int, str, str]]) -> str:
|
||||
@@ -1564,10 +1587,10 @@ def EnumMemberCountMismatchError(ClassName: str, Visible: list[tuple[str, object
|
||||
)
|
||||
|
||||
|
||||
# ExpandSoftKeywords 是 Code 的纯函数(全程无全局可变状态,见其"九种展开"实现):
|
||||
# ExpandSoftKeywords 是 Code 的纯函数(全程无全局可变状态):
|
||||
# 同一文件内容在一次编译里会被多处重复展开(Phase1 / Phase2 / 依赖扫描),
|
||||
# 缓存结果避免重复正则替换与 tokenize(cProfile:_ExpandTypeDescriptors 里的
|
||||
# tokenize.generate_tokens 全程 ~590 万次 TokenInfo._make)。纯函数缓存不改输出;有界防膨胀。
|
||||
# 缓存结果避免重复正则替换与 tokenize(数组前缀展开需要词法切分)。
|
||||
# 纯函数缓存不改输出;有界防膨胀。
|
||||
_EXPAND_CACHE: dict[str, str] = {}
|
||||
_EXPAND_CACHE_LIMIT: int = 256
|
||||
|
||||
@@ -1581,41 +1604,22 @@ def ExpandSoftKeywords(Code: str) -> str:
|
||||
2) `enum Name:` 块 → `class Name(CEnum):` 块(裸成员补 `: State`):
|
||||
与手写继承式枚举产出**同一 AST**,故语义(默认编号 0..N、自定义成员类型、
|
||||
宽度取最宽成员)完全一致。
|
||||
3) `define NAME[: T] = 值` → `NAME: [T |] CDefine = 值`:编译期常量声明,
|
||||
与手写 `NAME: CDefine = 值` 产出**同一 AST/同一注册路径**(见
|
||||
_ExpandDefineConsts)。`define NAME(...)`(宏函数)不受影响。
|
||||
4) `typedef T1 = T2` → `T1: CTypedef = T2`:类型别名声明,与手写
|
||||
`T1: CTypedef = T2` 产出**同一 AST/同一注册路径**(见 _ExpandTypedefs)。
|
||||
行首 `typedef` 的非声明形态**响亮失败**(该词不在任何既有源码中作标识符)。
|
||||
5) 类型描述符 `const T` / `volatile T` → `CConst | T` / `CVolatile | T`:
|
||||
与手写 `CConst | T` 产出**同一 AST/同一解析路径**(见 _ExpandTypeDescriptors)。
|
||||
只在注解位置生效的软关键字(`attr.const()` 等非类型位置原样保留);
|
||||
缺类型 / 后随非类型 / 裸用**响亮失败**(SyntaxError)。`static` 已从注解位置
|
||||
迁出——注解位置出现 `static`(`名字: static 类型`)**响亮失败**。
|
||||
6) `union NAME:` → `class NAME(CUnion):`:与手写 `class NAME(CUnion):` 产出
|
||||
3) `union NAME:` → `class NAME(CUnion):`:与手写 `class NAME(CUnion):` 产出
|
||||
**同一 AST/同一注册路径**(见 _ExpandUnionBlocks)。成员为普通注解字段。
|
||||
行首 `union` 的非 `union 名字:` 形态**响亮失败**(该词不在任何源码中作标识符)。
|
||||
7) 裸数组前缀 `[N]T` / `[]T` → `CArray[T, N]` / `CArray[T, None]`(见
|
||||
_ExpandArrayPrefixAnnotations):只在注解位置生效(AnnAssign 的 ':' 之后 /
|
||||
形参 / '->' 之后 / 类字段),右值列表字面量**绝不改动**;无法脱糖的注解位置
|
||||
数组前缀**响亮失败**(SyntaxError,绝不静默产出 List 注解)。
|
||||
8) `renum NAME:` → `class NAME(REnum):`:与手写 `class NAME(REnum):` 产出
|
||||
4) `renum NAME:` → `class NAME(REnum):`:与手写 `class NAME(REnum):` 产出
|
||||
**同一 AST/同一注册路径**(见 _ExpandRenumBlocks)。成员为普通类体(嵌套
|
||||
`class 变体:` + 无载荷赋值)。行首 `renum` 的非 `renum 名字:` 形态**响亮失败**
|
||||
(该词不在任何源码中作标识符)。
|
||||
9) `export 名字: T [= 初值]` → `名字: T | CExport [= 初值]`;
|
||||
`extern 名字: T` → `名字: T | State`;`static 名字: T [= 初值]` →
|
||||
`名字: CStatic | T [= 初值]`(见 _ExpandExportExternVar)。
|
||||
与 VPC 同一标记、同一消费路径;export/extern 在类型右侧追加标记,static 在
|
||||
类型左侧前置标记(与 VPC `_ParseStaticModified` 的 `pending_static` 同源);
|
||||
函数形态(`export def f()` / `export f()` / `extern def f()` / `static def f()`,
|
||||
后者由 vast.Parser._ParseStaticDef 处理)不受影响;
|
||||
`extern` 带初值**响亮失败**(外部定义不写初值)。
|
||||
5) 裸数组前缀 `[N]T` / `[]T` → `CArray[T, N]` / `CArray[T, None]`(见
|
||||
_ExpandArrayPrefixAnnotations):只在注解位置生效(AnnAssign 的 ':' 之后 /
|
||||
形参 / '->' 之后 / 类字段),右值列表字面量**绝不改动**;无法脱糖的注解位置
|
||||
数组前缀**响亮失败**(SyntaxError,绝不静默产出 List 注解)。
|
||||
|
||||
`define` / `typedef` / `const` / `volatile` / `static` / `export` / `extern` /
|
||||
`inline` / `__attribute__(...)` / 字节序与位宽修饰由 vast 解析器在注解位置原生
|
||||
解析成 AST 字段(Markers / Attributes / ByteOrder / BitWidth),本层不再做文本展开。
|
||||
以上展开都同行替换(长度可增,不增删换行),AST 行号映射保持有效。
|
||||
10) `new [描述符...] T(args)`:**已不在本层展开**——vast 解析器原生解析成 New
|
||||
节点(lib/vast/ExprParser._ParseNewExpr),存储/构造语义由 Handles 落地
|
||||
(HandlesExprCall._HandleNewExprLlvm);`new = 1` / `new.x` / `new(1)` /
|
||||
`for new in` 仍是标识符。
|
||||
"""
|
||||
if not Code:
|
||||
return Code
|
||||
@@ -1632,42 +1636,16 @@ def ExpandSoftKeywords(Code: str) -> str:
|
||||
def _ExpandSoftKeywordsImpl(Code: str) -> str:
|
||||
"""ExpandSoftKeywords 的实现体(无缓存,供缓存未命中时调用)。"""
|
||||
Code = _SOFT_KEYWORD_RE.sub(lambda m: f'{m.group(1)}def{m.group(3)}', Code)
|
||||
# `new` 生命周期软关键字(VPC):**不再**在此层展开——vast 解析器已原生解析成
|
||||
# New 节点(lib/vast/ExprParser._ParseNewExpr),存储语义由 Handles 落地。
|
||||
if 'enum' in Code:
|
||||
Code = _ExpandEnumBlocks(Code)
|
||||
if 'union' in Code:
|
||||
Code = _ExpandUnionBlocks(Code)
|
||||
if 'renum' in Code:
|
||||
Code = _ExpandRenumBlocks(Code)
|
||||
if 'define' in Code:
|
||||
Code = _ExpandDefineConsts(Code)
|
||||
if 'typedef' in Code:
|
||||
Code = _ExpandTypedefs(Code)
|
||||
# 描述符放在最后:先让语句级语法糖(enum/union/define/typedef)落到规范形态,
|
||||
# 本层再看规范注解(如 `define X: const int = 1` → `X: const int | CDefine = 1`
|
||||
# → `X: CConst | int | CDefine = 1`,两种顺序结果相同)。
|
||||
# `__attribute__(...)` 排在 const/volatile 之前:其注解位置判据需能回溯到**原始**
|
||||
# 描述符串(`const __attribute__(x) int` 的 `const` 尚未被改写为 `CConst |`),
|
||||
# 且它自身产出的 `attr.X |` 不会干扰紧随的 const/volatile 展开。
|
||||
if _ATTRIBUTE_CALLEE in Code:
|
||||
Code = _ExpandAttributeDescriptors(Code)
|
||||
# const/volatile 是注解位置的存储类描述符;`static` 已从注解位置迁出为**前置**
|
||||
# 修饰符(`static 名字: 类型 = 值`),本层进入 _ExpandTypeDescriptors 只为让旧位置
|
||||
# `名字: static 类型` 能被扫描到并**响亮失败**(见 _StaticPositionSyntaxError)。
|
||||
if 'const' in Code or 'volatile' in Code or 'static' in Code:
|
||||
Code = _ExpandTypeDescriptors(Code)
|
||||
# 裸 `[N]T` 数组前缀在描述符之后:`const [N]T` 已由 _ExpandTypeDescriptors 消化为
|
||||
# `CConst | CArray[T, N]`(此处不再有注解位置的裸 '['),避免两条路径重复改写。
|
||||
# 裸 `[N]T` 数组前缀(只改注解位置):`const [N]T` 中的 `const` 由解析器
|
||||
# 作为注解前缀消费,本层只需把数组前缀脱糖成 `CArray[T, N]`。
|
||||
if '[' in Code:
|
||||
Code = _ExpandArrayPrefixAnnotations(Code)
|
||||
# export / extern / static 变量声明(语句级软关键字):必须排在**最后**——此时注解
|
||||
# 已由数组前缀 / 描述符两层脱糖成规范形态(`CArray[T, N]` / `CConst | ...`),
|
||||
# 本层只删修饰符 + 插入存储类标记(export/extern 右追加 `| CExport` / `| State`;
|
||||
# static 左前置 `CStatic | `)。顺序若反过来,`|` 会被数组前缀展开并进元素类型
|
||||
# (见 _ExpandExportExternVar)。
|
||||
if 'export' in Code or 'extern' in Code or 'static' in Code:
|
||||
Code = _ExpandExportExternVar(Code)
|
||||
return Code
|
||||
|
||||
|
||||
@@ -2191,20 +2169,6 @@ def _ContainsUnionMarker(node: ast.AST) -> bool:
|
||||
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):
|
||||
@@ -2748,66 +2712,6 @@ def IsPtrSubscriptNode(node: ast.AST, symtable: object | None = None,
|
||||
return IsCPtrMarkerNode(value, symtable, TCAliasMap)
|
||||
|
||||
|
||||
def DesugarPtrSubscriptToUnion(node: ast.AST, symtable: object | None = None,
|
||||
TCAliasMap: dict[str, tuple[str, str]] | None = None) -> ast.AST:
|
||||
"""把指针下标(`rawptr[T]` / `CPtr[T]` / 裸名 `CPtr[T]` / 别名 `X[T]`)
|
||||
折叠成等价的联合写法 `T | CPtr`。
|
||||
|
||||
内层 T 递归折叠(`rawptr[rawptr[X]]` → `(X | CPtr) | CPtr`、
|
||||
`CPtr[rawptr[X]]` → `(X | CPtr) | CPtr`),
|
||||
与 VPC TypeGenResolve.resolve_annotation_type 的 Subscript 分支同语义
|
||||
(T → Ptr(T),层数逐层外包);折叠后交给 HandlesTypeMerge 既有的
|
||||
联合解析(_CollectAllOperandTypes 会把嵌套 BitOr 拉平成 [T, CPtr, ...],
|
||||
struct 基类型吸收一层、其余逐层累加),从而:
|
||||
- 内层 T 走通用类型解析(含跨模块类经 Gen.structs 反查 SHA1 前缀);
|
||||
- `rawptr[X]` / `CPtr[X]` / `X[T]` / `X | CPtr` 得到同一 CTypeInfo
|
||||
(PtrCount/BaseType 一致)与同一泛型实参串(逐层 '*')。
|
||||
|
||||
非指针下标节点原样返回(调用方无需先判类型);symtable/TCAliasMap 透传给
|
||||
判据(识别 `import t as tt` 的 `tt.CPtr[T]` 与 `from t import CPtr as X` 的
|
||||
`X[T]` 内层嵌套)。折叠产物统一用字面 `CPtr` 标记,与源码联合写法同形。
|
||||
"""
|
||||
if not IsPtrSubscriptNode(node, symtable, TCAliasMap):
|
||||
return node
|
||||
inner: ast.AST = DesugarPtrSubscriptToUnion(node.slice, symtable, TCAliasMap)
|
||||
cptr_marker: ast.AST = ast.Name(id='CPtr', ctx=ast.Load())
|
||||
union_node: ast.AST = ast.BinOp(left=inner, op=ast.BitOr(), right=cptr_marker)
|
||||
try:
|
||||
ast.copy_location(union_node, node)
|
||||
except Exception:
|
||||
pass
|
||||
return union_node
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 泛型实参串(mangling):定义端与声明端唯一规则源
|
||||
# ---------------------------------------------------------------------------
|
||||
# 同一泛型特化(如 list[rawptr[ast.AST]])在 define 端发射的结构体名
|
||||
# (HandlesClassDef._mangle_generic_class_name → %"<mod>.list[ast.ASTptr]")、
|
||||
# 各端方法名、以及 declare/stub 端引用的类型名必须逐字一致,否则会出现
|
||||
# Undefined method / 签名错位。此前 DeclarationGenerator._get_type_str 的泛型
|
||||
# 分支自带第二套(只认 Name / Name-Tuple 实参的)规则,其余形态(Attribute /
|
||||
# Subscript / BinOp / 混合 Tuple)退回未特化的 %"<mod>.list"*,与 define 端
|
||||
# 不一致。故此处收拢唯一规则,两端皆调用本组函数。
|
||||
|
||||
# 定义端 _resolve_generic_slice_type 的 ast.Name 规范化表:
|
||||
# 源码里的 C 定长类型名 → 喂给 _mangle_generic_class_name 的 type_arg。
|
||||
_GENERIC_ARG_INT_NAMES: frozenset[str] = frozenset({
|
||||
'CInt', 'CUInt', 'CInt32T', 'CUInt32T', 'CInt64T', 'CUInt64T',
|
||||
'CInt16T', 'CUInt16T', 'CInt8T', 'CUInt8T', 'CChar', 'CShort', 'CLong',
|
||||
})
|
||||
_GENERIC_ARG_FLOAT_NAMES: frozenset[str] = frozenset({
|
||||
'CDouble', 'CFloat', 'CFloat64T', 'CFloat32T',
|
||||
})
|
||||
# 源码名 → 泛型 T 替换用的原始类型名(_resolve_generic_slice_type 的第二返回值)
|
||||
_GENERIC_ARG_RAW_NAMES: dict[str, str] = {
|
||||
'int': 'CInt', 'double': 'CDouble', 'float': 'CFloat',
|
||||
'char': 'CChar', 'bool': 'CBool',
|
||||
}
|
||||
# _mangle_generic_class_name 的浮点归一集合(LLVM 浮点串 → 'f' + Size)
|
||||
_LLVM_FLOAT_STRINGS: frozenset[str] = frozenset({'float', 'double', 'half', 'fp128'})
|
||||
|
||||
|
||||
def NormalizeGenericArgName(NameId: str) -> str:
|
||||
"""ast.Name 泛型实参 → 定义端 type_arg(HandlesExprCall._resolve_generic_slice_type
|
||||
的 ast.Name 分支,逐分支同构):
|
||||
@@ -2925,8 +2829,6 @@ def ResolveTypeArgStr(Node: ast.AST, TCAliasMap: dict[str, tuple[str, str]] | No
|
||||
身份('X' = X 本身、'X*' = 指向 X 的指针),逐层累加,否则
|
||||
`rawptr[X]` 与 `X | CPtr` 会分裂成两个名字。
|
||||
"""
|
||||
if IsPtrSubscriptNode(Node, TCAliasMap=TCAliasMap):
|
||||
Node = DesugarPtrSubscriptToUnion(Node, TCAliasMap=TCAliasMap)
|
||||
if isinstance(Node, ast.Name):
|
||||
tn: str = Node.id
|
||||
if TCAliasMap and tn in TCAliasMap:
|
||||
|
||||
@@ -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, RejectTypeUnion,
|
||||
IsListAnnotation,
|
||||
ResolveGenericClassSpecName, GetStructSha1MapFromSymtab, GetTCAliasMapFromSymtab)
|
||||
from lib.core import TypeSystem
|
||||
from lib.constants.config import mode as _config_mode
|
||||
@@ -83,6 +83,45 @@ class TypeAnnotationResolver:
|
||||
def try_eval_const_expr(node: ast.AST, SymbolTable: SymbolTable) -> int | float | str | None:
|
||||
return ConstEvaluator.eval_with_symtab(node, SymbolTable)
|
||||
|
||||
# 说明符标记('const' / 'volatile' 等)→ 存储类 CType 类名
|
||||
_STORAGE_MARKER_CLASSES: dict[str, str] = {
|
||||
'static': 'CStatic',
|
||||
'export': 'CExport',
|
||||
'extern': 'CExtern',
|
||||
'inline': 'CInline',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _ApplyTypeModifiers(Info: CTypeInfo, Node: ast.AST) -> CTypeInfo:
|
||||
"""把注解节点上的 Markers / ByteOrder / BitWidth 写入 CTypeInfo。"""
|
||||
Markers: tuple[str, ...] = getattr(Node, 'Markers', None) or ()
|
||||
ByteOrder: str | None = getattr(Node, 'ByteOrder', None)
|
||||
BitWidth: int | None = getattr(Node, 'BitWidth', None)
|
||||
if not Markers and not ByteOrder and not BitWidth:
|
||||
return Info
|
||||
Info = Info.Copy()
|
||||
for Marker in Markers:
|
||||
if Marker == 'const':
|
||||
Info.DataConst = True
|
||||
elif Marker == 'volatile':
|
||||
Info.DataVolatile = True
|
||||
elif Marker == 'state':
|
||||
Info.IsState = True
|
||||
elif Marker == 'define':
|
||||
Info.IsDefine = True
|
||||
elif Marker == 'typedef':
|
||||
Info.IsTypedef = True
|
||||
else:
|
||||
StorageClassName: str | None = TypeAnnotationResolver._STORAGE_MARKER_CLASSES.get(Marker)
|
||||
if StorageClassName:
|
||||
Info.Storage = getattr(TypeSystem, StorageClassName)()
|
||||
if ByteOrder:
|
||||
Info.ByteOrder = ByteOrder
|
||||
if BitWidth:
|
||||
Info.IsBitField = True
|
||||
Info.BitWidth = BitWidth
|
||||
return Info
|
||||
|
||||
@staticmethod
|
||||
def from_node(Node: ast.AST, SymbolTable: dict | SymbolTable) -> CTypeInfo:
|
||||
"""从 AST 节点解析 CTypeInfo
|
||||
@@ -91,20 +130,24 @@ 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):
|
||||
return TypeAnnotationResolver._from_node_name(Node, SymbolTable)
|
||||
if isinstance(Node, ast.Call):
|
||||
return TypeAnnotationResolver._from_node_call(Node, SymbolTable)
|
||||
if isinstance(Node, ast.BinOp) and isinstance(Node.op, ast.BitOr):
|
||||
return TypeAnnotationResolver._from_node_binop(Node, SymbolTable)
|
||||
if isinstance(Node, ast.Subscript):
|
||||
return TypeAnnotationResolver._from_node_subscript(Node, SymbolTable)
|
||||
if isinstance(Node, ast.Attribute):
|
||||
return TypeAnnotationResolver._from_node_attribute(Node, SymbolTable)
|
||||
return CTypeInfo()
|
||||
Line: int = getattr(Node, 'lineno', 0) or 0
|
||||
raise TypeError(
|
||||
f"[TPC] 不支持类型联合 'T1 | T2'(第 {Line} 行);"
|
||||
f"类型注解只能是单一类型:指针请写 CPtr[T],修饰符请用关键字")
|
||||
if isinstance(Node, ast.Constant):
|
||||
Info: CTypeInfo = TypeAnnotationResolver._from_node_constant(Node, SymbolTable)
|
||||
elif isinstance(Node, ast.Name):
|
||||
Info = TypeAnnotationResolver._from_node_name(Node, SymbolTable)
|
||||
elif isinstance(Node, ast.Call):
|
||||
Info = TypeAnnotationResolver._from_node_call(Node, SymbolTable)
|
||||
elif isinstance(Node, ast.Subscript):
|
||||
Info = TypeAnnotationResolver._from_node_subscript(Node, SymbolTable)
|
||||
elif isinstance(Node, ast.Attribute):
|
||||
Info = TypeAnnotationResolver._from_node_attribute(Node, SymbolTable)
|
||||
else:
|
||||
Info = CTypeInfo()
|
||||
return TypeAnnotationResolver._ApplyTypeModifiers(Info, Node)
|
||||
|
||||
# ============================================================
|
||||
# builtins 最后匹配(对齐 VPC TypeGenResolve._lookup_builtins_typedef):
|
||||
@@ -718,218 +761,6 @@ class TypeAnnotationResolver:
|
||||
return Result
|
||||
return CTypeInfo()
|
||||
|
||||
@staticmethod
|
||||
def _from_node_binop(Node: ast.BinOp, SymbolTable: dict | SymbolTable) -> CTypeInfo:
|
||||
"""处理 ast.BinOp (BitOr) 节点"""
|
||||
LeftInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.left, SymbolTable)
|
||||
RightInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.right, SymbolTable)
|
||||
|
||||
if LeftInfo.IsState or RightInfo.IsState:
|
||||
Result: CTypeInfo = CTypeInfo()
|
||||
Result.IsState = True
|
||||
NonStateInfo: CTypeInfo = LeftInfo if not LeftInfo.IsState else RightInfo
|
||||
StateInfo: CTypeInfo = LeftInfo if LeftInfo.IsState else RightInfo
|
||||
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (TypeSystem._CTypedef,)) or NonStateInfo.PtrCount > 0):
|
||||
Result.BaseType = NonStateInfo.BaseType
|
||||
elif NonStateInfo.IsTypedef and NonStateInfo.Name:
|
||||
if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (TypeSystem._CTypedef,)) or NonStateInfo.PtrCount > 0):
|
||||
Result.BaseType = NonStateInfo.BaseType
|
||||
Result.PtrCount = NonStateInfo.PtrCount
|
||||
Result.IsTypedef = True
|
||||
Result.Name = NonStateInfo.Name
|
||||
if NonStateInfo.OriginalType:
|
||||
Result.OriginalType = NonStateInfo.OriginalType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CStruct(name=NonStateInfo.Name)
|
||||
Result.IsStruct = True
|
||||
Result.IsTypedef = True
|
||||
Result.Name = NonStateInfo.Name
|
||||
if NonStateInfo.OriginalType:
|
||||
Result.OriginalType = NonStateInfo.OriginalType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if not Result.Storage:
|
||||
Result.Storage = TypeSystem.CExport()
|
||||
if LeftInfo.Storage and not isinstance(LeftInfo.Storage, TypeSystem.CExport):
|
||||
Result.Storage = LeftInfo.Storage
|
||||
elif RightInfo.Storage and not isinstance(RightInfo.Storage, TypeSystem.CExport):
|
||||
Result.Storage = RightInfo.Storage
|
||||
if LeftInfo.DataConst or RightInfo.DataConst:
|
||||
Result.DataConst = True
|
||||
if LeftInfo.VarConst or RightInfo.VarConst:
|
||||
Result.VarConst = True
|
||||
return Result
|
||||
|
||||
if LeftInfo.IsPtr or RightInfo.IsPtr:
|
||||
Result = CTypeInfo()
|
||||
# 当双方都是指针时(如 (AST | CPtr) | CPtr),PtrCount 应相加
|
||||
# 而非取 max,否则 AST** 会被折叠为 AST*,导致对象切片问题
|
||||
if LeftInfo.IsPtr and RightInfo.IsPtr:
|
||||
Result.PtrCount = LeftInfo.PtrCount + RightInfo.PtrCount
|
||||
# BaseType 优先取非 void 侧(如 AST),而非 CPtr 的 void
|
||||
if LeftInfo.BaseType and not isinstance(LeftInfo.BaseType, TypeSystem.CVoid):
|
||||
Result.BaseType = LeftInfo.BaseType
|
||||
elif RightInfo.BaseType and not isinstance(RightInfo.BaseType, TypeSystem.CVoid):
|
||||
Result.BaseType = RightInfo.BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CUnsignedChar()
|
||||
else:
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
NonPtrInfo = LeftInfo if not LeftInfo.IsPtr else RightInfo
|
||||
PtrInfo = RightInfo if RightInfo.IsPtr else LeftInfo
|
||||
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (TypeSystem._CTypedef,)) or NonPtrInfo.PtrCount > 0):
|
||||
Result.BaseType = NonPtrInfo.BaseType
|
||||
elif NonPtrInfo.IsTypedef and NonPtrInfo.Name:
|
||||
if NonPtrInfo.BaseType and (not isinstance(NonPtrInfo.BaseType, (TypeSystem._CTypedef,)) or NonPtrInfo.PtrCount > 0):
|
||||
Result.BaseType = NonPtrInfo.BaseType
|
||||
Result.IsTypedef = True
|
||||
Result.Name = NonPtrInfo.Name
|
||||
if NonPtrInfo.OriginalType:
|
||||
Result.OriginalType = NonPtrInfo.OriginalType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CStruct(name=NonPtrInfo.Name)
|
||||
Result.IsStruct = True
|
||||
elif PtrInfo.BaseType and (not isinstance(PtrInfo.BaseType, (TypeSystem._CTypedef,)) or PtrInfo.PtrCount > 0):
|
||||
Result.BaseType = PtrInfo.BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CUnsignedChar()
|
||||
if LeftInfo.DataConst or RightInfo.DataConst:
|
||||
Result.DataConst = True
|
||||
if LeftInfo.VarConst or RightInfo.VarConst:
|
||||
Result.VarConst = True
|
||||
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
|
||||
Result.DataVolatile = True
|
||||
if LeftInfo.VarVolatile or RightInfo.VarVolatile:
|
||||
Result.VarVolatile = True
|
||||
if LeftInfo.Storage:
|
||||
Result.Storage = LeftInfo.Storage
|
||||
elif RightInfo.Storage:
|
||||
Result.Storage = RightInfo.Storage
|
||||
return Result
|
||||
|
||||
if LeftInfo.DataConst or RightInfo.DataConst:
|
||||
Result = CTypeInfo()
|
||||
BaseTypeSide = LeftInfo if not LeftInfo.DataConst else RightInfo
|
||||
QualSide = LeftInfo if LeftInfo.DataConst else RightInfo
|
||||
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
|
||||
if not Result.BaseType:
|
||||
Result.BaseType = TypeSystem.CInt()
|
||||
Result.DataConst = True
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if LeftInfo.VarConst or RightInfo.VarConst:
|
||||
Result.VarConst = True
|
||||
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
|
||||
Result.DataVolatile = True
|
||||
if LeftInfo.Storage:
|
||||
Result.Storage = LeftInfo.Storage
|
||||
elif RightInfo.Storage:
|
||||
Result.Storage = RightInfo.Storage
|
||||
return Result
|
||||
|
||||
if LeftInfo.DataVolatile or RightInfo.DataVolatile:
|
||||
Result = CTypeInfo()
|
||||
BaseTypeSide = LeftInfo if not LeftInfo.DataVolatile else RightInfo
|
||||
QualSide = LeftInfo if LeftInfo.DataVolatile else RightInfo
|
||||
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else QualSide.BaseType
|
||||
if not Result.BaseType:
|
||||
Result.BaseType = TypeSystem.CInt()
|
||||
Result.DataVolatile = True
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if LeftInfo.VarConst or RightInfo.VarConst:
|
||||
Result.VarConst = True
|
||||
if LeftInfo.Storage:
|
||||
Result.Storage = LeftInfo.Storage
|
||||
elif RightInfo.Storage:
|
||||
Result.Storage = RightInfo.Storage
|
||||
return Result
|
||||
|
||||
if LeftInfo.Storage or RightInfo.Storage:
|
||||
Result = CTypeInfo()
|
||||
BaseTypeSide = LeftInfo if not LeftInfo.Storage else RightInfo
|
||||
StorageSide = LeftInfo if LeftInfo.Storage else RightInfo
|
||||
# CExtern | CExport 等价于 State:两边都有 Storage 时设置 IsState
|
||||
if BaseTypeSide.IsState or StorageSide.IsState or (LeftInfo.Storage and RightInfo.Storage):
|
||||
Result.IsState = True
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
|
||||
return Result
|
||||
Result.BaseType = BaseTypeSide.BaseType if BaseTypeSide.BaseType and (not isinstance(BaseTypeSide.BaseType, TypeSystem.CVoid) or BaseTypeSide.PtrCount > 0) else StorageSide.BaseType
|
||||
if not Result.BaseType:
|
||||
Result.BaseType = TypeSystem.CInt()
|
||||
Result.Storage = LeftInfo.Storage if LeftInfo.Storage else RightInfo.Storage
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if LeftInfo.DataConst or RightInfo.DataConst:
|
||||
Result.DataConst = True
|
||||
if LeftInfo.VarConst or RightInfo.VarConst:
|
||||
Result.VarConst = True
|
||||
return Result
|
||||
|
||||
# 检查是否有位域类型 (Bit)
|
||||
if LeftInfo.IsBitField:
|
||||
Result = CTypeInfo()
|
||||
Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else TypeSystem.CInt()
|
||||
Result.IsBitField = True
|
||||
Result.BitWidth = LeftInfo.BitWidth
|
||||
return Result
|
||||
if RightInfo.IsBitField:
|
||||
Result = CTypeInfo()
|
||||
Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else TypeSystem.CInt()
|
||||
Result.IsBitField = True
|
||||
Result.BitWidth = RightInfo.BitWidth
|
||||
return Result
|
||||
|
||||
# 处理字节序类型 (BigEndian, LittleEndian)
|
||||
# 合并两侧:保留非字节序侧的实际类型(如 CUInt64T),取字节序侧的 ByteOrder
|
||||
if LeftInfo.ByteOrder or RightInfo.ByteOrder:
|
||||
Result = CTypeInfo()
|
||||
ByteOrderSide: CTypeInfo = LeftInfo if LeftInfo.ByteOrder else RightInfo
|
||||
OtherSide: CTypeInfo = RightInfo if LeftInfo.ByteOrder else LeftInfo
|
||||
if OtherSide.BaseType and (not isinstance(OtherSide.BaseType, (TypeSystem._CTypedef,)) or OtherSide.PtrCount > 0):
|
||||
Result.BaseType = OtherSide.BaseType
|
||||
elif ByteOrderSide.BaseType and (not isinstance(ByteOrderSide.BaseType, (TypeSystem._CTypedef,)) or ByteOrderSide.PtrCount > 0):
|
||||
Result.BaseType = ByteOrderSide.BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CInt()
|
||||
Result.ByteOrder = LeftInfo.ByteOrder or RightInfo.ByteOrder
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
return Result
|
||||
|
||||
if LeftInfo.IsFuncPtr or RightInfo.IsFuncPtr:
|
||||
Result = CTypeInfo()
|
||||
FuncPtrSide = LeftInfo if LeftInfo.IsFuncPtr else RightInfo
|
||||
Result.IsFuncPtr = True
|
||||
Result.FuncPtrParams = list(FuncPtrSide.FuncPtrParams)
|
||||
Result.FuncPtrReturn = FuncPtrSide.FuncPtrReturn
|
||||
if LeftInfo.Storage:
|
||||
Result.Storage = LeftInfo.Storage
|
||||
elif RightInfo.Storage:
|
||||
Result.Storage = RightInfo.Storage
|
||||
return Result
|
||||
|
||||
if LeftInfo.IsTypedef and RightInfo.BaseType:
|
||||
if LeftInfo.BaseType and (not isinstance(LeftInfo.BaseType, (TypeSystem._CTypedef,)) or LeftInfo.PtrCount > 0):
|
||||
Result = LeftInfo.Copy()
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if RightInfo.Storage:
|
||||
Result.Storage = RightInfo.Storage
|
||||
return Result
|
||||
return RightInfo
|
||||
if RightInfo.IsTypedef and LeftInfo.BaseType:
|
||||
if RightInfo.BaseType and (not isinstance(RightInfo.BaseType, (TypeSystem._CTypedef,)) or RightInfo.PtrCount > 0):
|
||||
Result = RightInfo.Copy()
|
||||
Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount)
|
||||
if LeftInfo.Storage:
|
||||
Result.Storage = LeftInfo.Storage
|
||||
return Result
|
||||
return LeftInfo
|
||||
|
||||
if LeftInfo.BaseType:
|
||||
return LeftInfo
|
||||
elif RightInfo.BaseType:
|
||||
return RightInfo
|
||||
return CTypeInfo()
|
||||
|
||||
@staticmethod
|
||||
def _from_node_subscript(Node: ast.Subscript, SymbolTable: dict | SymbolTable) -> CTypeInfo:
|
||||
"""处理 ast.Subscript 节点"""
|
||||
@@ -944,6 +775,31 @@ class TypeAnnotationResolver:
|
||||
else:
|
||||
Result.BitWidth = 1
|
||||
return Result
|
||||
MarkerName: str | None = None
|
||||
if isinstance(base, ast.Name):
|
||||
MarkerName = base.id
|
||||
elif isinstance(base, ast.Attribute):
|
||||
MarkerName = base.attr
|
||||
if MarkerName in ('CPtr', 'rawptr'):
|
||||
SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.slice, SymbolTable)
|
||||
Result: CTypeInfo = CTypeInfo()
|
||||
if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, TypeSystem.CVoid):
|
||||
Result.BaseType = SliceInfo.BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
Result.PtrCount = (SliceInfo.PtrCount if SliceInfo else 0) + 1
|
||||
return TypeAnnotationResolver._ApplyTypeModifiers(Result, Node)
|
||||
if MarkerName in ('CRef', 'CTempRef', 'CArrayPtr', 'CAutoPtr'):
|
||||
SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.slice, SymbolTable)
|
||||
Result: CTypeInfo = CTypeInfo()
|
||||
if SliceInfo and SliceInfo.BaseType:
|
||||
Result.BaseType = SliceInfo.BaseType
|
||||
else:
|
||||
Result.BaseType = TypeSystem.CVoid()
|
||||
Result.PtrCount = (SliceInfo.PtrCount if SliceInfo else 0) + 1
|
||||
if MarkerName == 'CArrayPtr':
|
||||
Result.IsArrayPtr = True
|
||||
return Result
|
||||
if IsListAnnotation(Node):
|
||||
slice_node: ast.AST = Node.slice
|
||||
elts: list[ast.AST] = []
|
||||
@@ -1068,12 +924,9 @@ class TypeAnnotationResolver:
|
||||
return Result
|
||||
# 泛型类下标(单/多参):list[str] / dict[str][int] / 用户泛型 Box[Node]。
|
||||
# 特化名与声明端(DeclarationGenerator 泛型分支)同口径,见
|
||||
# SymbolUtils.ResolveGenericClassSpecName。此前单参泛型下标在下方直接落到
|
||||
# "未知类型"空 CTypeInfo ⇒ 形参/成员类型退化成 i32 或 void 指针链
|
||||
# (现场:type_args: list[str]* 的形参 i32;CTypedefNames: list[str] | CPtr → i8*)。
|
||||
# 表示口径与本文件既有结构体 promotion 逐字一致(BaseType=CStruct + IsStruct +
|
||||
# Name,PtrCount 保持 0):`X | CPtr` 由 _from_node_binop 取 max → 1 层,
|
||||
# `rawptr[X]` 由上方分支 +1 → 1 层,均与 declare 侧 %"{sha}.X[*]"* 一致。
|
||||
# SymbolUtils.ResolveGenericClassSpecName。表示口径与本文件既有结构体
|
||||
# promotion 逐字一致(BaseType=CStruct + IsStruct + Name,PtrCount 保持 0),
|
||||
# 与 declare 侧 %"{sha}.X[*]"* 一致。
|
||||
_Spec: str | None = ResolveGenericClassSpecName(
|
||||
Node, SymbolTable,
|
||||
GetStructSha1MapFromSymtab(SymbolTable),
|
||||
|
||||
+190
-21
@@ -110,7 +110,7 @@ class TokenStream:
|
||||
self._PeekCacheIdx: int = -1
|
||||
self._PeekCacheTok: Token | None = None
|
||||
# 类型注解解析模式:为 True 时 '*' / '**' 按 C 风格指针后缀处理
|
||||
# (int* → int | CPtr、int** → 嵌套两层),不按乘法/幂运算消费。
|
||||
# (int* → CPtr[int]、int** → 嵌套两层),不按乘法/幂运算消费。
|
||||
self._InTypeAnnotation: bool = False
|
||||
# 下标实参嵌套层数:'[' 实参内是表达式位置(CArray[T, A * B] 的尺寸),
|
||||
# 此处的 '*' 在有右操作数时按乘法解析(见 _ParseTerm / _AtOperandAfterStarRun)。
|
||||
@@ -463,7 +463,7 @@ class ExprParserMixin(TokenStream):
|
||||
op_type: type | None = None
|
||||
if tok.Type == OP:
|
||||
if tok.Value == '*' and self._AtPtrSuffix(left):
|
||||
# C 风格指针后缀('*' 一层);展开为 base | CPtr 后继续。
|
||||
# C 风格指针后缀('*' 一层);折叠为 CPtr[...] 后继续。
|
||||
left = self._ConsumePtrSuffix(left)
|
||||
continue
|
||||
if self._InTypeAnnotation and tok.Value == '*':
|
||||
@@ -1300,7 +1300,7 @@ class ExprParserMixin(TokenStream):
|
||||
first: N.expr = self.ParseExpr()
|
||||
# Paren-less C cast `(T*)x`: the inner expression ends with a pointer suffix
|
||||
# (_Prev() is that suffix's tail token) and the operand follows ')'. Same
|
||||
# product as `(T*)(x)` / `T*(x)`: a Call whose func is `T | CPtr`.
|
||||
# product as `(T*)(x)` / `T*(x)`: a Call whose func is `CPtr[T]`.
|
||||
is_ptr_cast: bool = self._PtrSuffixTail is not None and self._AtOp(')') and self._Prev() is self._PtrSuffixTail
|
||||
self._SkipNL()
|
||||
# 生成器表达式 (x for ...)
|
||||
@@ -1685,29 +1685,66 @@ class ExprParserMixin(TokenStream):
|
||||
self._FixLoc(a, start)
|
||||
return a
|
||||
|
||||
# 注解起始的修饰词:只在该位置生效,写入类型节点的 Markers 字段。
|
||||
_TYPE_MARKER_WORDS: frozenset[str] = frozenset({
|
||||
'const', 'volatile', 'static', 'export', 'extern', 'inline',
|
||||
})
|
||||
|
||||
def _ParseTypeAnnotation(self) -> N.expr:
|
||||
"""解析类型注解,支持 C 风格指针后缀(* / **)。
|
||||
"""解析类型注解,支持修饰前缀与 C 风格指针后缀(* / **)。
|
||||
|
||||
修饰前缀(任意顺序、可组合)写入类型节点的 AST 字段,不再展开为
|
||||
`T1 | T2` 联合:
|
||||
|
||||
const volatile int → Name('int').Markers = ('const', 'volatile')
|
||||
x: __attribute__((...)) T → T.Attributes = (...)
|
||||
BigEndian uint16 → ByteOrder = 'big'
|
||||
Bit(3) int / Bit[3] int → BitWidth = 3
|
||||
|
||||
注解模式开启后,'_ParseTerm'/'_ParsePower' 不再把 '*' / '**' 当
|
||||
乘法/幂运算消费,而由本方法统一循环消费并展开为嵌套联合类型:
|
||||
乘法/幂运算消费,而由本方法统一循环消费并折叠为 Subscript:
|
||||
|
||||
int* → int | CPtr (i32*)
|
||||
int** → (int | CPtr) | CPtr (i32**)
|
||||
int****** → 6 层嵌套 (i32******)
|
||||
|
||||
展开为 BinOp(BitOr) 链后,TPC/VPC 现有类型解析(TypeAnnotationResolver
|
||||
的 PtrCount 相加、VPC TypeGenResolve 的递归 BinOp 分支)零改动即可
|
||||
生成多级指针 LLVM 类型。
|
||||
int* → CPtr[int] (i32*)
|
||||
int** → CPtr[CPtr[int]] (i32**)
|
||||
int****** → 6 层嵌套 (i32******)
|
||||
|
||||
无法解析的后缀形态**响亮失败**(SyntaxError,含 行:列 + 源码片段 + 形态 +
|
||||
正确写法示例),绝不静默丢弃:注解末尾若仍遗留未被 `_AtPtrSuffix` 接受的
|
||||
'*'/'**'(如 `a: int * 2` / `a: int* | CPtr`),判据拒绝消费即终止编译
|
||||
(历史事故:静默退化会产出错误的指针层数)。
|
||||
(静默退化会产出错误的指针层数)。
|
||||
|
||||
值引用参数注解(仅形参位有效):前导 `&` 为 ref 模式、`&temp` 为 temp 模式,
|
||||
合成联合形态 `T | CRef` / `T | CTempRef` 承载(CRef/CTempRef 非真实类,
|
||||
合成 Subscript 形态 `CRef[T]` / `CTempRef[T]`(CRef/CTempRef 非真实类,
|
||||
仅按名字识别;语义侧见 HandlesFunctions / FuncGen)。表达式位的 `&x` 不受影响。
|
||||
"""
|
||||
markers: list[str] = []
|
||||
attributes: list[str] = []
|
||||
byte_order: str = ''
|
||||
bit_width: int = 0
|
||||
while True:
|
||||
tok: Token = self._Peek()
|
||||
if tok.Type != NAME:
|
||||
break
|
||||
word: str = tok.Value
|
||||
if word in self._TYPE_MARKER_WORDS:
|
||||
self._Next()
|
||||
markers.append(word)
|
||||
continue
|
||||
if word == '__attribute__' and self._Peek(1).Type == OP \
|
||||
and self._Peek(1).Value == '(':
|
||||
self._Next()
|
||||
attributes.extend(self._ParseAttributeSpecifier())
|
||||
continue
|
||||
if word in ('BigEndian', 'LittleEndian') and self._AtTypeStart(1):
|
||||
self._Next()
|
||||
byte_order = 'big' if word == 'BigEndian' else 'little'
|
||||
continue
|
||||
if word == 'Bit' and self._Peek(1).Type == OP \
|
||||
and self._Peek(1).Value in ('(', '['):
|
||||
self._Next()
|
||||
bit_width = self._ParseBitWidth()
|
||||
continue
|
||||
break
|
||||
ref_mode: str | None = None
|
||||
ref_tok: Token = self._Peek()
|
||||
if self._AtOp('&'):
|
||||
@@ -1741,6 +1778,9 @@ class ExprParserMixin(TokenStream):
|
||||
raise SyntaxError(
|
||||
"[vast] 值引用参数注解缺少类型:`&` 后必须紧跟类型 T"
|
||||
"(ref:`&T`;temp:`&temp T`)。")
|
||||
if markers or attributes or byte_order or bit_width:
|
||||
raise SyntaxError(
|
||||
"[vast] 类型注解的修饰词后缺少类型(如 `x: const int`)。")
|
||||
return None
|
||||
if self._AtPtrSuffix(expr):
|
||||
expr = self._ConsumePtrSuffix(expr)
|
||||
@@ -1763,17 +1803,147 @@ class ExprParserMixin(TokenStream):
|
||||
)
|
||||
if ref_mode is not None:
|
||||
expr = self._MakeRefMarker(expr, ref_mode, ref_tok)
|
||||
self._ApplyTypePrefix(expr, markers, attributes, byte_order, bit_width)
|
||||
return expr
|
||||
|
||||
def _AtTypeStart(self, offset: int) -> bool:
|
||||
"""offset 处的 token 是否可作为类型起点(用于识别字节序前缀)。"""
|
||||
tok: Token = self._Peek(offset)
|
||||
if tok.Type in (NAME, NUMBER, STRING):
|
||||
return True
|
||||
return tok.Type == OP and tok.Value in ('[', '(', '&')
|
||||
|
||||
@staticmethod
|
||||
def _SplitTopLevel(text: str, sep: str = ',') -> list[str]:
|
||||
"""按顶层分隔符切分文本(忽略括号/方括号/花括号内与字符串内的分隔符)。"""
|
||||
parts: list[str] = []
|
||||
buf: list[str] = []
|
||||
depth: int = 0
|
||||
quote: str = ''
|
||||
escaped: bool = False
|
||||
for ch in text:
|
||||
if quote:
|
||||
buf.append(ch)
|
||||
if escaped:
|
||||
escaped = False
|
||||
elif ch == '\\':
|
||||
escaped = True
|
||||
elif ch == quote:
|
||||
quote = ''
|
||||
continue
|
||||
if ch in ('"', "'"):
|
||||
quote = ch
|
||||
buf.append(ch)
|
||||
continue
|
||||
if ch in '([{':
|
||||
depth += 1
|
||||
elif ch in ')]}':
|
||||
depth -= 1
|
||||
if ch == sep and depth == 0:
|
||||
parts.append(''.join(buf))
|
||||
buf = []
|
||||
continue
|
||||
buf.append(ch)
|
||||
parts.append(''.join(buf))
|
||||
return parts
|
||||
|
||||
@staticmethod
|
||||
def _StripOuterParens(text: str) -> str:
|
||||
"""去掉一对完整包裹文本的圆括号(`((a), (b))` 不误删)。"""
|
||||
s: str = text.strip()
|
||||
if not (s.startswith('(') and s.endswith(')')):
|
||||
return s
|
||||
depth: int = 0
|
||||
quote: str = ''
|
||||
escaped: bool = False
|
||||
for i, ch in enumerate(s):
|
||||
if quote:
|
||||
if escaped:
|
||||
escaped = False
|
||||
elif ch == '\\':
|
||||
escaped = True
|
||||
elif ch == quote:
|
||||
quote = ''
|
||||
continue
|
||||
if ch in ('"', "'"):
|
||||
quote = ch
|
||||
elif ch == '(':
|
||||
depth += 1
|
||||
elif ch == ')':
|
||||
depth -= 1
|
||||
if depth == 0 and i != len(s) - 1:
|
||||
return s
|
||||
if depth != 0:
|
||||
return s
|
||||
return s[1:-1].strip()
|
||||
|
||||
def _ParseAttributeSpecifier(self) -> tuple[str, ...]:
|
||||
"""解析 `__attribute__(...)` 的括号内容(调用名已消费),返回属性文本元组。"""
|
||||
open_tok: Token = self._ExpectOp('(')
|
||||
depth: int = 1
|
||||
inner: str = ''
|
||||
while True:
|
||||
tok: Token = self._Next()
|
||||
if tok.Type == ENDMARKER:
|
||||
raise SyntaxError(
|
||||
"[vast] __attribute__ 描述符缺少右括号:"
|
||||
"期望 `__attribute__((aligned(16)))` 形态。")
|
||||
if tok.Type == OP and tok.Value == '(':
|
||||
depth += 1
|
||||
elif tok.Type == OP and tok.Value == ')':
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
inner = self.Source[open_tok.End:tok.Start].strip()
|
||||
break
|
||||
inner = self._StripOuterParens(inner)
|
||||
return tuple(part.strip() for part in self._SplitTopLevel(inner) if part.strip())
|
||||
|
||||
def _ParseBitWidth(self) -> int:
|
||||
"""解析 `Bit(N)` / `Bit[N]` 的位宽(调用名已消费)。"""
|
||||
open_tok: Token = self._Next()
|
||||
close: str = ')' if open_tok.Value == '(' else ']'
|
||||
self._SkipNL()
|
||||
width_tok: Token = self._Next()
|
||||
if width_tok.Type != NUMBER:
|
||||
raise SyntaxError(
|
||||
f"[vast] Bit 描述符缺少整数位宽:第 {width_tok.Line} 行"
|
||||
f"第 {width_tok.Col} 列,期望 `Bit(N)` / `Bit[N]`。")
|
||||
try:
|
||||
width: int = int(width_tok.Value.replace('_', ''), 0)
|
||||
except ValueError as exc:
|
||||
raise SyntaxError(
|
||||
f"[vast] Bit 描述符的位宽必须是整数字面量,得到 {width_tok.Value!r}。"
|
||||
) from exc
|
||||
self._SkipNL()
|
||||
self._ExpectOp(close)
|
||||
return width
|
||||
|
||||
@staticmethod
|
||||
def _ApplyTypePrefix(node: N.expr, markers: list[str], attributes: list[str],
|
||||
byte_order: str, bit_width: int) -> None:
|
||||
"""把注解前缀写入类型节点的 Markers / Attributes / ByteOrder / BitWidth。"""
|
||||
if not hasattr(type(node), 'Markers'):
|
||||
return
|
||||
if markers:
|
||||
existing: tuple[str, ...] = tuple(getattr(node, 'Markers', ()) or ())
|
||||
node.Markers = tuple(markers) + tuple(m for m in existing if m not in markers)
|
||||
if attributes:
|
||||
existing_attrs: tuple[str, ...] = tuple(getattr(node, 'Attributes', ()) or ())
|
||||
node.Attributes = existing_attrs + tuple(attributes)
|
||||
if byte_order:
|
||||
node.ByteOrder = byte_order
|
||||
if bit_width:
|
||||
node.BitWidth = bit_width
|
||||
|
||||
def _MakeRefMarker(self, base: N.expr, mode: str, tok: Token) -> N.expr:
|
||||
"""构造值引用标记联合:`base | CRef`(ref)/ `base | CTempRef`(temp)。
|
||||
"""构造值引用包装:`CRef[T]`(ref)/ `CTempRef[T]`(temp)。
|
||||
|
||||
CRef / CTempRef 非真实类,仅作为注解 AST 内的名字标记(语义侧按名字识别)。
|
||||
"""
|
||||
marker: N.expr = N.Name(
|
||||
id='CRef' if mode == 'ref' else 'CTempRef',
|
||||
ctx=N.Load())
|
||||
node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=marker)
|
||||
node: N.Subscript = N.Subscript(value=marker, slice=base, ctx=N.Load())
|
||||
self._FixLoc(node, tok)
|
||||
return node
|
||||
|
||||
@@ -1828,7 +1998,7 @@ class ExprParserMixin(TokenStream):
|
||||
return False
|
||||
|
||||
def _ConsumePtrSuffix(self, expr: N.expr) -> N.expr:
|
||||
"""消费连续的 C 风格指针后缀('*' 一层 / '**' 两层),展开为 base | CPtr 链。"""
|
||||
"""消费连续的 C 风格指针后缀('*' 一层 / '**' 两层),折叠为 CPtr[...] 嵌套。"""
|
||||
while True:
|
||||
tok: Token = self._Peek()
|
||||
if tok.Type == OP and tok.Value == '*':
|
||||
@@ -1921,16 +2091,15 @@ class ExprParserMixin(TokenStream):
|
||||
def _ConsumePtrSuffixCall(self, base: N.expr, start: Token) -> N.expr:
|
||||
"""把已认定为 `T*(...)` 的指针后缀强转解析为**调用**。
|
||||
|
||||
产物与既有强转形态 `(T | CPtr)(...)` 逐字同形:同为 `ast.Call`
|
||||
(func = `T` 展开的 `base | CPtr` 链,args/keywords = 括号实参),
|
||||
产物为 `ast.Call`(func = `CPtr[T]` 指针包装,args/keywords = 括号实参),
|
||||
不新造第二套 cast 表示。
|
||||
"""
|
||||
func: N.expr = self._ConsumePtrSuffix(base)
|
||||
return self._ParseCallTail(func, start)
|
||||
|
||||
def _MakePtrType(self, base: N.expr, tok: Token) -> N.expr:
|
||||
"""构造一层指针包装:base | CPtr。"""
|
||||
"""构造一层指针包装:`CPtr[base]`。"""
|
||||
cptr: N.expr = N.Name(id='CPtr', ctx=N.Load())
|
||||
node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=cptr)
|
||||
node: N.Subscript = N.Subscript(value=cptr, slice=base, ctx=N.Load())
|
||||
self._FixLoc(node, tok)
|
||||
return node
|
||||
+15
-9
@@ -53,6 +53,12 @@ _POS_ATTRS: tuple[str, ...] = ('lineno', 'col_offset', 'end_lineno', 'end_col_of
|
||||
# 写入,unparse 还原)。__slots__ 类无 __dict__,必须纳入槽位,否则
|
||||
# node.Extern = True 抛 AttributeError。
|
||||
_FUNC_ATTRS: tuple[str, ...] = _POS_ATTRS + ('Extern', 'Export', 'Define')
|
||||
# 类型注解修饰(由 Parser 直接写入注解节点,不再用 `T1 | T2` 组合表示):
|
||||
# Markers: ('const','volatile','static','export','extern','inline','state','define','typedef')
|
||||
# Attributes: ('section(".x")', 'aligned(16)', ...)
|
||||
# ByteOrder: '' | 'big' | 'little'
|
||||
# BitWidth: 0 = 非位域
|
||||
_TYPE_ATTRS: tuple[str, ...] = _POS_ATTRS + ('Markers', 'Attributes', 'ByteOrder', 'BitWidth')
|
||||
|
||||
_NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = {
|
||||
# ---- 模块/交互/表达式顶层 ----
|
||||
@@ -63,14 +69,14 @@ _NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = {
|
||||
'Suite': ((), ()),
|
||||
|
||||
# ---- 语句 ----
|
||||
'FunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS),
|
||||
'AsyncFunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS),
|
||||
'FunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS + _TYPE_ATTRS),
|
||||
'AsyncFunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS + _TYPE_ATTRS),
|
||||
'ClassDef': (('name', 'bases', 'keywords', 'body', 'decorator_list', 'type_params'), _POS_ATTRS),
|
||||
'Return': (('value',), _POS_ATTRS),
|
||||
'Delete': (('targets',), _POS_ATTRS),
|
||||
'Assign': (('targets', 'value', 'type_comment'), _POS_ATTRS),
|
||||
'AugAssign': (('target', 'op', 'value'), _POS_ATTRS),
|
||||
'AnnAssign': (('target', 'annotation', 'value', 'simple'), _POS_ATTRS),
|
||||
'AnnAssign': (('target', 'annotation', 'value', 'simple'), _TYPE_ATTRS),
|
||||
'For': (('target', 'iter', 'body', 'orelse', 'type_comment'), _POS_ATTRS),
|
||||
'AsyncFor': (('target', 'iter', 'body', 'orelse', 'type_comment'), _POS_ATTRS),
|
||||
'While': (('test', 'body', 'orelse'), _POS_ATTRS),
|
||||
@@ -108,7 +114,7 @@ _NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = {
|
||||
'Yield': (('value',), _POS_ATTRS),
|
||||
'YieldFrom': (('value',), _POS_ATTRS),
|
||||
'Compare': (('left', 'ops', 'comparators'), _POS_ATTRS),
|
||||
'Call': (('func', 'args', 'keywords'), _POS_ATTRS),
|
||||
'Call': (('func', 'args', 'keywords'), _TYPE_ATTRS),
|
||||
# Viper `new` 生命周期分配表达式(软关键字):new [描述符...] T(args)。
|
||||
# Source/Life 为描述符整数(见 NEW_SRC_*/NEW_LIFE_*);memgr 为 `memgr(x)` 的 x
|
||||
# (无 memgr 描述符时为 None);func 是被构造的 callee(Name/Attribute/Subscript),
|
||||
@@ -116,11 +122,11 @@ _NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = {
|
||||
'New': (('Source', 'Life', 'memgr', 'func', 'args'), _POS_ATTRS),
|
||||
'FormattedValue': (('value', 'conversion', 'format_spec'), _POS_ATTRS),
|
||||
'JoinedStr': (('values',), _POS_ATTRS),
|
||||
'Constant': (('value', 'kind'), _POS_ATTRS + ('int_width', 'int_unsigned')),
|
||||
'Attribute': (('value', 'attr', 'ctx'), _POS_ATTRS),
|
||||
'Subscript': (('value', 'slice', 'ctx'), _POS_ATTRS),
|
||||
'Constant': (('value', 'kind'), _TYPE_ATTRS + ('int_width', 'int_unsigned')),
|
||||
'Attribute': (('value', 'attr', 'ctx'), _TYPE_ATTRS),
|
||||
'Subscript': (('value', 'slice', 'ctx'), _TYPE_ATTRS),
|
||||
'Starred': (('value', 'ctx'), _POS_ATTRS),
|
||||
'Name': (('id', 'ctx'), _POS_ATTRS),
|
||||
'Name': (('id', 'ctx'), _TYPE_ATTRS),
|
||||
'List': (('elts', 'ctx'), _POS_ATTRS),
|
||||
'Tuple': (('elts', 'ctx'), _POS_ATTRS),
|
||||
'Slice': (('lower', 'upper', 'step'), _POS_ATTRS),
|
||||
@@ -145,7 +151,7 @@ _NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = {
|
||||
'comprehension': (('target', 'iter', 'ifs', 'is_async'), ()),
|
||||
'ExceptHandler': (('type', 'name', 'body'), _POS_ATTRS),
|
||||
'arguments': (('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), ()),
|
||||
'arg': (('arg', 'annotation', 'type_comment'), _POS_ATTRS),
|
||||
'arg': (('arg', 'annotation', 'type_comment'), _TYPE_ATTRS),
|
||||
'keyword': (('arg', 'value'), _POS_ATTRS),
|
||||
'alias': (('name', 'asname'), _POS_ATTRS),
|
||||
'withitem': (('context_expr', 'optional_vars'), ()),
|
||||
|
||||
+132
-52
@@ -166,27 +166,37 @@ class Parser(ExprParserMixin):
|
||||
tok: Token = self._Peek()
|
||||
if tok.Type == NAME:
|
||||
v: str = tok.Value
|
||||
# extern 函数声明(FFI,等价 State)——必须在软关键字 def 分派之前
|
||||
# extern:变量声明 `extern 名字: 类型`(禁止初值)与函数声明
|
||||
# `extern [def] 名字(...)` 共用起始关键字;第二个 token 是 NAME 且
|
||||
# 再后随 ':' / '=' 时按变量声明解析,否则按函数声明解析。
|
||||
if v == 'extern':
|
||||
if self._IsStorageVarStart():
|
||||
return self._ParseStorageVar('extern')
|
||||
return self._ParseExternDef()
|
||||
# export 函数声明(等价 CExport,裸名导出不增加 SHA1 头)——
|
||||
# 必须在软关键字 def 分派之前
|
||||
# export:变量声明 `export 名字: 类型 [= 初值]` 与函数声明
|
||||
# `export [def] 名字(...)` 同理分派。
|
||||
if v == 'export':
|
||||
if self._IsStorageVarStart():
|
||||
return self._ParseStorageVar('export')
|
||||
return self._ParseExportDef()
|
||||
# static 存储类软关键字(已从"注解位置"迁出为**语句起始前置**修饰符):
|
||||
# 仅 `static def 名字` 形态判定为函数定义——判据必须同时要求第二个 token
|
||||
# 是 `def`,故 `static = 5` / `static x = 5` 不会被误吃成函数定义。
|
||||
# 变量形式 `static 名字: 类型 = 值` 不在本层处理,由 SymbolUtils 的前置
|
||||
# 修饰符展开统一脱糖为 `名字: CStatic | 类型 = 值`。
|
||||
if (v == 'static' and self._Peek(1).Type == NAME
|
||||
and self._Peek(1).Value == 'def'):
|
||||
return self._ParseStaticDef()
|
||||
# define 宏函数定义(与 def 语义一致,返回注解自动追加 CDefine
|
||||
# 标记为宏函数;软关键字:仅"define + 标识符"形态才判定为函数定义,
|
||||
# 变量名/调用(define = 5、define(x))不受影响)——必须在软关键字
|
||||
# def 分派之前
|
||||
# static:`static def 名字` 为函数定义;`static 名字: 类型` 为变量声明。
|
||||
# 判据要求第二个 token 是 NAME 且再后随 ':' / '=',故
|
||||
# `static = 5` / `static x` 不会被误吃成修饰声明。
|
||||
if v == 'static':
|
||||
if (self._Peek(1).Type == NAME
|
||||
and self._Peek(1).Value == 'def'):
|
||||
return self._ParseStaticDef()
|
||||
if self._IsStorageVarStart():
|
||||
return self._ParseStorageVar('static')
|
||||
# define:`define 名字 = 值` / `define 名字: 类型 = 值` 为编译期常量
|
||||
# 声明;`define 名字(...)` / `define 名字[T](...)` 为宏函数定义。
|
||||
if v == 'define' and self._Peek(1).Type == NAME:
|
||||
if self._IsStorageVarStart():
|
||||
return self._ParseDefineVar()
|
||||
return self._ParseDefineDef()
|
||||
# typedef 名字 = 类型:类型别名声明(右值按类型注解解析)。
|
||||
if v == 'typedef' and self._Peek(1).Type == NAME:
|
||||
return self._ParseTypedefVar()
|
||||
# virtual / novirtual 修饰符(软关键字):只在"语句起始 + 紧跟 class/def"
|
||||
# 时生效,合成既有装饰器 @CVTable / @NoVTable(见 _ParseVirtualModified)。
|
||||
# 放在 def/class 分派之前:修饰符必须先被消费,class/def 才能照常分派。
|
||||
@@ -285,6 +295,102 @@ class Parser(ExprParserMixin):
|
||||
return self._ParseDecorated()
|
||||
return self._ParseSimpleStmt()
|
||||
|
||||
# ==================================================================
|
||||
# 语句级变量修饰形态(static / export / extern / define / typedef)
|
||||
# ==================================================================
|
||||
def _IsStorageVarStart(self) -> bool:
|
||||
"""当前修饰词之后是否为变量声明形态:`修饰词 名字 :` 或 `修饰词 名字 =`。"""
|
||||
if self._Peek(1).Type != NAME:
|
||||
return False
|
||||
nxt: Token = self._Peek(2)
|
||||
return nxt.Type == OP and nxt.Value in (':', '=')
|
||||
|
||||
@staticmethod
|
||||
def _AddTypeMarkers(node: N.AST, marker: str) -> None:
|
||||
"""把修饰词追加到类型节点的 Markers 字段(保持出现顺序、去重)。"""
|
||||
if not hasattr(type(node), 'Markers'):
|
||||
return
|
||||
existing: tuple[str, ...] = tuple(getattr(node, 'Markers', ()) or ())
|
||||
if marker not in existing:
|
||||
node.Markers = existing + (marker,)
|
||||
|
||||
def _ParseStorageVar(self, marker: str) -> N.AnnAssign:
|
||||
"""解析 `static|export|extern 名字: 类型 [= 初值]` 为 AnnAssign。
|
||||
|
||||
`extern` 变量只声明不定义,禁止初值。
|
||||
"""
|
||||
start: Token = self._Next() # 修饰词
|
||||
name_tok: Token = self._ExpectName()
|
||||
if not self._AtOp(':'):
|
||||
raise SyntaxError(
|
||||
f"[vast] `{marker} 名字` 变量声明必须带类型注解:"
|
||||
f"期望 `{marker} {name_tok.Value}: 类型"
|
||||
f"{' [= 初值]' if marker != 'extern' else ''}`。")
|
||||
self._Next() # ':'
|
||||
annotation: N.expr = self._ParseTypeAnnotation()
|
||||
value: N.expr | None = None
|
||||
if self._AtOp('='):
|
||||
if marker == 'extern':
|
||||
raise SyntaxError(
|
||||
f"[vast] extern 变量声明不能带初始值(符号定义在外部):"
|
||||
f"`extern {name_tok.Value}: 类型`。")
|
||||
self._Next()
|
||||
value = self.ParseExpr()
|
||||
self._AddTypeMarkers(annotation, marker)
|
||||
target: N.Name = N.Name(id=name_tok.Value, ctx=N.Store())
|
||||
self._FixLoc(target, name_tok)
|
||||
node: N.AnnAssign = N.AnnAssign(
|
||||
target=target, annotation=annotation, value=value, simple=1)
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
def _ParseDefineVar(self) -> N.AnnAssign:
|
||||
"""解析 `define 名字[: 类型] = 值` 为编译期常量声明(Markers += 'define')。"""
|
||||
start: Token = self._Next() # 'define'
|
||||
name_tok: Token = self._ExpectName()
|
||||
annotation: N.expr | None = None
|
||||
if self._AtOp(':'):
|
||||
self._Next()
|
||||
annotation = self._ParseTypeAnnotation()
|
||||
if not self._AtOp('='):
|
||||
raise SyntaxError(
|
||||
f"[vast] define 常量声明缺少初值:"
|
||||
f"期望 `define {name_tok.Value}[: 类型] = 值`。")
|
||||
self._Next() # '='
|
||||
value: N.expr = self.ParseExpr()
|
||||
if annotation is None:
|
||||
# 未标注类型:注解占位为 CDefine(Markers 仍承载 'define')。
|
||||
annotation = N.Name(id='CDefine', ctx=N.Load())
|
||||
self._FixLoc(annotation, start)
|
||||
self._AddTypeMarkers(annotation, 'define')
|
||||
target: N.Name = N.Name(id=name_tok.Value, ctx=N.Store())
|
||||
self._FixLoc(target, name_tok)
|
||||
node: N.AnnAssign = N.AnnAssign(
|
||||
target=target, annotation=annotation, value=value, simple=1)
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
def _ParseTypedefVar(self) -> N.AnnAssign:
|
||||
"""解析 `typedef 名字 = 类型` 为类型别名声明(Markers += 'typedef')。
|
||||
|
||||
右值按类型注解解析(支持 `T*` 等 C 风格后缀)。
|
||||
"""
|
||||
start: Token = self._Next() # 'typedef'
|
||||
name_tok: Token = self._ExpectName()
|
||||
if not self._AtOp('='):
|
||||
raise SyntaxError(
|
||||
f"[vast] typedef 语法错误:"
|
||||
f"期望 `typedef {name_tok.Value} = 类型`。")
|
||||
self._Next() # '='
|
||||
type_node: N.expr = self._ParseTypeAnnotation()
|
||||
self._AddTypeMarkers(type_node, 'typedef')
|
||||
target: N.Name = N.Name(id=name_tok.Value, ctx=N.Store())
|
||||
self._FixLoc(target, name_tok)
|
||||
node: N.AnnAssign = N.AnnAssign(
|
||||
target=target, annotation=type_node, value=type_node, simple=1)
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
# ==================================================================
|
||||
# fallthrough 关键字(语句级)
|
||||
# ==================================================================
|
||||
@@ -422,12 +528,11 @@ class Parser(ExprParserMixin):
|
||||
|
||||
@staticmethod
|
||||
def _IsCTypedefAnnotation(annotation: N.expr | None) -> bool:
|
||||
"""注解是否为 typedef 标记(裸 `CTypedef` / `CTypedef` / 含它的 `|` 联合)。
|
||||
"""注解是否为 typedef 标记(裸 `CTypedef` / 含它的 `|` 联合)。
|
||||
|
||||
用于把 typedef 的右值按**类型位置**解析(`X: CTypedef = const uint16*`
|
||||
里的 `*` 后缀由 _ParseTypeAnnotation 消费,与注解位同一规则;描述符
|
||||
`const`/`volatile` 已由 SymbolUtils._ExpandTypeDescriptors 在文本层展开)。
|
||||
仅按标记名判定,不依赖 import 别名表(与 VPC `_IsCTypedefAnnotation` 同口径)。
|
||||
用于把 typedef 的右值按**类型位置**解析(`X: CTypedef = T` 里的 `*`
|
||||
后缀由 _ParseTypeAnnotation 消费,与注解位同一规则)。仅按标记名判定,
|
||||
不依赖 import 别名表(与 VPC `_IsCTypedefAnnotation` 同口径)。
|
||||
"""
|
||||
if annotation is None:
|
||||
return False
|
||||
@@ -921,7 +1026,7 @@ class Parser(ExprParserMixin):
|
||||
return node
|
||||
|
||||
def _ParseExternDef(self, decorators: list[N.expr] | None = None) -> N.FunctionDef:
|
||||
"""解析 extern 函数声明(FFI,与 State 作用相当)。
|
||||
"""解析 extern 函数声明(FFI,仅声明不定义)。
|
||||
|
||||
允许语法(均声明不定义,不生成函数体):
|
||||
extern def A(x: int) -> int: pass
|
||||
@@ -929,9 +1034,8 @@ class Parser(ExprParserMixin):
|
||||
extern def A(x: int) -> int
|
||||
extern A(x: int) -> int
|
||||
|
||||
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | State``
|
||||
以复用 TPC 的 IsState 路径;并设自定义属性 ``Extern = True``
|
||||
供 Unparser 还原 extern 语法。
|
||||
产出标准 FunctionDef 节点,``Extern = True`` 供 Unparser 还原 extern 语法;
|
||||
返回注解保持源码原样(不追加 `| State`)。
|
||||
"""
|
||||
start: Token = self._Next() # 'extern'
|
||||
if self._AtName('def'):
|
||||
@@ -955,12 +1059,6 @@ class Parser(ExprParserMixin):
|
||||
type_comment=None, type_params=type_params,
|
||||
)
|
||||
node.Extern = True
|
||||
# 返回注解改写为 <原类型> | State,使 TPC 识别为 State 函数(仅声明)
|
||||
state_attr: N.expr = N.Name(id='State', ctx=N.Load())
|
||||
if returns is not None:
|
||||
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=state_attr)
|
||||
else:
|
||||
node.returns = state_attr
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
@@ -973,9 +1071,8 @@ class Parser(ExprParserMixin):
|
||||
export def A(x: int) -> int
|
||||
export A(x: int) -> int
|
||||
|
||||
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | CExport``
|
||||
以复用 TPC 的 CExport 路径(符号名不增加 SHA1 前缀);并设自定义
|
||||
属性 ``Export = True`` 供 Unparser 还原 export 语法。
|
||||
产出标准 FunctionDef 节点,``Export = True`` 供 Unparser 还原 export 语法;
|
||||
返回注解保持源码原样(不追加 `| CExport`)。
|
||||
"""
|
||||
start: Token = self._Next() # 'export'
|
||||
if self._AtName('def'):
|
||||
@@ -999,13 +1096,6 @@ class Parser(ExprParserMixin):
|
||||
type_comment=None, type_params=type_params,
|
||||
)
|
||||
node.Export = True
|
||||
# 返回注解改写为 <原类型> | CExport,使 TPC 识别为 CExport 函数
|
||||
# (导出裸名,不增加模块 SHA1 头;有条件情况下导出)
|
||||
export_attr: N.expr = N.Name(id='CExport', ctx=N.Load())
|
||||
if returns is not None:
|
||||
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=export_attr)
|
||||
else:
|
||||
node.returns = export_attr
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
@@ -1072,11 +1162,8 @@ class Parser(ExprParserMixin):
|
||||
define A(x: int) -> int: ...
|
||||
define A(x: int): ...
|
||||
|
||||
产出标准 FunctionDef 节点,返回注解改写为 ``<原类型> | CDefine``
|
||||
(无显式返回注解时单独 ``CDefine``),使 TPC/VPC 复用既有的
|
||||
CDefine 宏函数识别路径(StubGen 原样保留生成 C #define、
|
||||
alwaysinline 内联);并设自定义属性 ``Define = True`` 供
|
||||
Unparser 还原 define 语法。
|
||||
产出标准 FunctionDef 节点,``Define = True`` 供 Unparser 还原 define 语法;
|
||||
返回注解保持源码原样(不追加 `| CDefine`)。
|
||||
"""
|
||||
start: Token = self._Next() # 'define'
|
||||
name_tok: Token = self._ExpectName()
|
||||
@@ -1096,13 +1183,6 @@ class Parser(ExprParserMixin):
|
||||
type_comment=None, type_params=type_params,
|
||||
)
|
||||
node.Define = True
|
||||
# 返回注解改写为 <原类型> | CDefine,使下游识别为宏函数
|
||||
# (StubGen 保留原样输出 C #define;TPC 标记 alwaysinline 内联)
|
||||
define_attr: N.expr = N.Name(id='CDefine', ctx=N.Load())
|
||||
if returns is not None:
|
||||
node.returns = N.BinOp(left=returns, op=N.BitOr(), right=define_attr)
|
||||
else:
|
||||
node.returns = define_attr
|
||||
self._FixLoc(node, start)
|
||||
return node
|
||||
|
||||
|
||||
+74
-36
@@ -12,8 +12,17 @@ from lib.vast import Nodes as N
|
||||
class Unparser:
|
||||
"""递归将 vast 节点还原为源码文本。"""
|
||||
|
||||
# 语句级修饰词:由 _AnnAssign 渲染在目标名之前(而非类型前)。
|
||||
_STATEMENT_MARKERS: frozenset[str] = frozenset({
|
||||
'static', 'export', 'extern', 'define', 'typedef',
|
||||
})
|
||||
# 未显式标注类型的 define 常量以 CDefine 作为注解占位,还原时省略类型部分。
|
||||
_IMPLICIT_ANNOTATION_NAMES: frozenset[str] = frozenset({'CDefine'})
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._Depth: int = 0
|
||||
# 当前正在渲染的注解上被语句级修饰词消费掉的 Markers(不再输出为类型前缀)。
|
||||
self._SuppressedMarkers: frozenset[str] = frozenset()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 顶层
|
||||
@@ -87,21 +96,6 @@ class Unparser:
|
||||
params: str = self._Arguments(node.args)
|
||||
ret: str = ''
|
||||
returns: N.expr | None = node.returns
|
||||
if is_extern and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
|
||||
# 还原 extern 原始注解:去掉改写时追加的 | State
|
||||
right: N.expr = returns.right
|
||||
if isinstance(right, N.Name) and right.id == 'State':
|
||||
returns = returns.left
|
||||
if is_export and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
|
||||
# 还原 export 原始注解:去掉改写时追加的 | CExport
|
||||
right = returns.right
|
||||
if isinstance(right, N.Name) and right.id == 'CExport':
|
||||
returns = returns.left
|
||||
if is_define and isinstance(returns, N.BinOp) and isinstance(returns.op, N.BitOr):
|
||||
# 还原 define 原始注解:去掉改写时追加的 | CDefine
|
||||
right = returns.right
|
||||
if isinstance(right, N.Name) and right.id == 'CDefine':
|
||||
returns = returns.left
|
||||
if returns is not None:
|
||||
ret = f' -> {self._expr(returns)}'
|
||||
body: str = self._Block(node.body)
|
||||
@@ -134,8 +128,56 @@ class Unparser:
|
||||
return f'{self._expr(node.target)} {op}= {self._expr(node.value)}'
|
||||
|
||||
def _AnnAssign(self, node: N.AnnAssign) -> str:
|
||||
val: str = f' = {self._expr(node.value)}' if node.value is not None else ''
|
||||
return f'{self._expr(node.target)}: {self._expr(node.annotation)}{val}'
|
||||
annotation: N.expr = node.annotation
|
||||
markers: tuple[str, ...] = tuple(getattr(annotation, 'Markers', ()) or ())
|
||||
saved: frozenset[str] = self._SuppressedMarkers
|
||||
self._SuppressedMarkers = frozenset(
|
||||
m for m in markers if m in self._STATEMENT_MARKERS)
|
||||
try:
|
||||
type_text: str = self._expr(annotation)
|
||||
target_text: str = self._expr(node.target)
|
||||
if 'typedef' in markers:
|
||||
rhs: str = (self._expr(node.value) if node.value is not None
|
||||
else type_text)
|
||||
return f'typedef {target_text} = {rhs}'
|
||||
if 'define' in markers:
|
||||
head: str = f'define {target_text}'
|
||||
implicit: bool = (
|
||||
isinstance(annotation, N.Name)
|
||||
and annotation.id in self._IMPLICIT_ANNOTATION_NAMES)
|
||||
if not implicit:
|
||||
head += f': {type_text}'
|
||||
if node.value is not None:
|
||||
head += f' = {self._expr(node.value)}'
|
||||
return head
|
||||
stmt_prefix: str = ''.join(
|
||||
f'{m} ' for m in ('extern', 'export', 'static') if m in markers)
|
||||
val: str = f' = {self._expr(node.value)}' if node.value is not None else ''
|
||||
return f'{stmt_prefix}{target_text}: {type_text}{val}'
|
||||
finally:
|
||||
self._SuppressedMarkers = saved
|
||||
|
||||
def _TypeModifierPrefix(self, node: N.AST) -> str:
|
||||
"""把注解节点的 Markers / Attributes / ByteOrder / BitWidth 还原为前缀关键字。"""
|
||||
parts: list[str] = [
|
||||
m for m in (getattr(node, 'Markers', ()) or ())
|
||||
if m not in self._SuppressedMarkers
|
||||
]
|
||||
attrs: tuple[str, ...] = tuple(getattr(node, 'Attributes', ()) or ())
|
||||
if attrs:
|
||||
parts.append('__attribute__((' + ', '.join(attrs) + '))')
|
||||
order: str = getattr(node, 'ByteOrder', '') or ''
|
||||
if order == 'big':
|
||||
parts.append('BigEndian')
|
||||
elif order == 'little':
|
||||
parts.append('LittleEndian')
|
||||
width: int = getattr(node, 'BitWidth', 0) or 0
|
||||
if width:
|
||||
parts.append(f'Bit({width})')
|
||||
return ''.join(f'{p} ' for p in parts)
|
||||
|
||||
def _WithTypeModifiers(self, node: N.AST, text: str) -> str:
|
||||
return self._TypeModifierPrefix(node) + text
|
||||
|
||||
def _For(self, node: N.For) -> str:
|
||||
kw: str = 'async for' if isinstance(node, N.AsyncFor) else 'for'
|
||||
@@ -344,29 +386,24 @@ class Unparser:
|
||||
return f'{out} {callee}'
|
||||
|
||||
def _Name(self, node: N.Name) -> str:
|
||||
return node.id
|
||||
return self._WithTypeModifiers(node, node.id)
|
||||
|
||||
def _Constant(self, node: N.Constant) -> str:
|
||||
v = node.value
|
||||
if v is Ellipsis:
|
||||
return '...'
|
||||
if v is None:
|
||||
return 'None'
|
||||
if v is True:
|
||||
return 'True'
|
||||
if v is False:
|
||||
return 'False'
|
||||
if isinstance(v, str):
|
||||
return repr(v)
|
||||
if isinstance(v, bytes):
|
||||
return repr(v)
|
||||
if isinstance(v, complex):
|
||||
# 复数文本
|
||||
return repr(v)
|
||||
return repr(v)
|
||||
text = '...'
|
||||
elif v is None:
|
||||
text = 'None'
|
||||
elif v is True:
|
||||
text = 'True'
|
||||
elif v is False:
|
||||
text = 'False'
|
||||
else:
|
||||
text = repr(v)
|
||||
return self._WithTypeModifiers(node, text)
|
||||
|
||||
def _Attribute(self, node: N.Attribute) -> str:
|
||||
return f'{self._expr(node.value)}.{node.attr}'
|
||||
return self._WithTypeModifiers(node, f'{self._expr(node.value)}.{node.attr}')
|
||||
|
||||
def _Call(self, node: N.Call) -> str:
|
||||
args: list[str] = [self._expr(a) for a in node.args]
|
||||
@@ -375,7 +412,7 @@ class Unparser:
|
||||
args.append(f'**{self._expr(kw.value)}')
|
||||
else:
|
||||
args.append(f'{kw.arg}={self._expr(kw.value)}')
|
||||
return f'{self._expr(node.func)}({", ".join(args)})'
|
||||
return self._WithTypeModifiers(node, f'{self._expr(node.func)}({", ".join(args)})')
|
||||
|
||||
_BINOP_OPS: dict[type, str] = {
|
||||
N.Add: '+', N.Sub: '-', N.Mult: '*', N.Div: '/', N.FloorDiv: '//',
|
||||
@@ -410,7 +447,8 @@ class Unparser:
|
||||
return ' '.join(parts)
|
||||
|
||||
def _Subscript(self, node: N.Subscript) -> str:
|
||||
return f'{self._expr(node.value)}[{self._SliceLike(node.slice)}]'
|
||||
return self._WithTypeModifiers(
|
||||
node, f'{self._expr(node.value)}[{self._SliceLike(node.slice)}]')
|
||||
|
||||
def _SliceLike(self, node: N.AST) -> str:
|
||||
if isinstance(node, N.Slice):
|
||||
|
||||
+14
-2
@@ -62,10 +62,22 @@ def _ParsePure(source: str, mode: str) -> AST:
|
||||
# 信息(文件名 + 异常)。该回退**不会**改变产出——纯 Python 是本包语义基准,
|
||||
# 故绝不静默产出与纯 Python 不同的 AST。连续相同的(文件, 异常)只打印一次。
|
||||
_VAST_C_PARSE = None
|
||||
_VAST_C_STALE = False
|
||||
try:
|
||||
from lib.vast_c import parse as _VAST_C_PARSE
|
||||
import glob as _glob
|
||||
_vast_c_dir: str = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), '..', 'vast_c')
|
||||
_vast_c_src: str = _os.path.join(_vast_c_dir, 'vast_c.c')
|
||||
_vast_c_pyd: list[str] = _glob.glob(_os.path.join(_vast_c_dir, '_parser*.pyd'))
|
||||
if _vast_c_pyd and _os.path.exists(_vast_c_src):
|
||||
if max(_os.path.getmtime(_f) for _f in _vast_c_pyd) < _os.path.getmtime(_vast_c_src):
|
||||
_VAST_C_STALE = True
|
||||
except Exception:
|
||||
_VAST_C_PARSE = None
|
||||
_VAST_C_STALE = False
|
||||
if not _VAST_C_STALE:
|
||||
try:
|
||||
from lib.vast_c import parse as _VAST_C_PARSE
|
||||
except Exception:
|
||||
_VAST_C_PARSE = None
|
||||
|
||||
_CFallbackSeen: set = set()
|
||||
|
||||
|
||||
+322
-83
@@ -2557,27 +2557,33 @@ static PyObject *ParseArith(Parser *P) {
|
||||
|
||||
/* ============ C 风格指针后缀(* / **,对齐 vast ExprParser) ============ */
|
||||
|
||||
/* 构造一层指针包装 base | t.CPtr(对齐 Python _MakePtrType)。 */
|
||||
static PyObject *MakePtrType(Parser *P, PyObject *Base, Token *Tok) {
|
||||
PyObject *CPtr = MakeTAttrNode(P, "CPtr");
|
||||
if (CPtr == NULL) {
|
||||
/* 构造类型包装 Subscript(Name(WrapperName), Inner):CPtr[T] / CRef[T] / CTempRef[T]。 */
|
||||
static PyObject *MakeTypeWrapperSubscript(Parser *P, const char *WrapperName,
|
||||
PyObject *Inner, Token *Tok) {
|
||||
PyObject *Wrapper = MakeTAttrNode(P, WrapperName);
|
||||
if (Wrapper == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *Op = MakeSingleton(P, "BitOr");
|
||||
if (Op == NULL) {
|
||||
Py_DECREF(CPtr);
|
||||
PyObject *Load = MakeCtx(P, "Load");
|
||||
if (Load == NULL) {
|
||||
Py_DECREF(Wrapper);
|
||||
return NULL;
|
||||
}
|
||||
PyObject *Argv[3] = { Base, Op, CPtr };
|
||||
PyObject *Node = NewNode(P, "BinOp", Argv, 3);
|
||||
Py_DECREF(Op);
|
||||
Py_DECREF(CPtr);
|
||||
PyObject *Argv[3] = { Wrapper, Inner, Load };
|
||||
PyObject *Node = NewNode(P, "Subscript", Argv, 3);
|
||||
Py_DECREF(Wrapper);
|
||||
Py_DECREF(Load);
|
||||
if (Node != NULL) {
|
||||
FixLoc(P, Node, Tok);
|
||||
}
|
||||
return Node;
|
||||
}
|
||||
|
||||
/* 构造一层指针包装 CPtr[T](对齐 Python _MakePtrType)。 */
|
||||
static PyObject *MakePtrType(Parser *P, PyObject *Base, Token *Tok) {
|
||||
return MakeTypeWrapperSubscript(P, "CPtr", Base, Tok);
|
||||
}
|
||||
|
||||
/* 判定当前位置的 '*'/'**' 串是否为 C 风格指针后缀(作用于"类型原子"节点)。
|
||||
*
|
||||
* 判据(两条同时成立,对齐 Python ExprParser._AtPtrSuffix):
|
||||
@@ -2712,13 +2718,295 @@ static PyObject *ConsumePtrSuffixCall(Parser *P, PyObject *Base, Token *Start) {
|
||||
return Call;
|
||||
}
|
||||
|
||||
/* ============ 类型注解修饰前缀(const/volatile/... / __attribute__ / 字节序) ============ */
|
||||
|
||||
static int IsSpaceByte(char C) {
|
||||
return C == ' ' || C == '\t' || C == '\r' || C == '\n';
|
||||
}
|
||||
|
||||
/* 追加一个字符串到惰性创建的 Python list;失败返回 0。 */
|
||||
static int AppendStringItem(PyObject **List, const char *Text, Py_ssize_t Len) {
|
||||
if (*List == NULL) {
|
||||
*List = NewList();
|
||||
if (*List == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PyObject *Item = PyUnicode_FromStringAndSize(Text, Len);
|
||||
if (Item == NULL) {
|
||||
return 0;
|
||||
}
|
||||
int Rc = PyList_Append(*List, Item);
|
||||
Py_DECREF(Item);
|
||||
return Rc == 0;
|
||||
}
|
||||
|
||||
/* 追加单个 __attribute__ 属性(去掉首尾空白)。 */
|
||||
static int AppendAttributeSlice(PyObject **List, const char *Text, Py_ssize_t Len) {
|
||||
while (Len > 0 && IsSpaceByte(*Text)) {
|
||||
Text++;
|
||||
Len--;
|
||||
}
|
||||
while (Len > 0 && IsSpaceByte(Text[Len - 1])) {
|
||||
Len--;
|
||||
}
|
||||
if (Len == 0) {
|
||||
return 1;
|
||||
}
|
||||
return AppendStringItem(List, Text, Len);
|
||||
}
|
||||
|
||||
/* 从 `__attribute__((...))` 源码片段提取属性列表,按顶层逗号拆分后写入 List。
|
||||
* 例:__attribute__((section(".x"), aligned(16))) -> ["section(\".x\")", "aligned(16)"] */
|
||||
static int AppendAttributesFromText(PyObject **List, const char *Text, Py_ssize_t Len) {
|
||||
Py_ssize_t I = 0;
|
||||
while (I < Len && Text[I] != '(') {
|
||||
I++;
|
||||
}
|
||||
if (I >= Len) {
|
||||
return 1;
|
||||
}
|
||||
I++; /* 跳过 __attribute__ 后的 '(' */
|
||||
Py_ssize_t J = Len;
|
||||
while (J > I && Text[J - 1] != ')') {
|
||||
J--;
|
||||
}
|
||||
if (J <= I) {
|
||||
return 1;
|
||||
}
|
||||
J--; /* 去掉与之配对的 ')' */
|
||||
while (I < J && IsSpaceByte(Text[I])) {
|
||||
I++;
|
||||
}
|
||||
while (J > I && IsSpaceByte(Text[J - 1])) {
|
||||
J--;
|
||||
}
|
||||
/* GNU 双括号形式 __attribute__((...)):剥掉内层一对括号 */
|
||||
if (J - I >= 2 && Text[I] == '(' && Text[J - 1] == ')') {
|
||||
I++;
|
||||
J--;
|
||||
}
|
||||
Py_ssize_t Start = I;
|
||||
int Depth = 0;
|
||||
char Quote = 0;
|
||||
for (Py_ssize_t K = I; K < J; K++) {
|
||||
char C = Text[K];
|
||||
if (Quote != 0) {
|
||||
if (C == '\\' && K + 1 < J) {
|
||||
K++;
|
||||
} else if (C == Quote) {
|
||||
Quote = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (C == '"' || C == '\'') {
|
||||
Quote = C;
|
||||
} else if (C == '(' || C == '[' || C == '{') {
|
||||
Depth++;
|
||||
} else if (C == ')' || C == ']' || C == '}') {
|
||||
if (Depth > 0) {
|
||||
Depth--;
|
||||
}
|
||||
} else if (C == ',' && Depth == 0) {
|
||||
if (!AppendAttributeSlice(List, Text + Start, K - Start)) {
|
||||
return 0;
|
||||
}
|
||||
Start = K + 1;
|
||||
}
|
||||
}
|
||||
return AppendAttributeSlice(List, Text + Start, J - Start);
|
||||
}
|
||||
|
||||
/* 下一 token 能否作为类型起点(前缀修饰后必须仍跟着实际类型)。 */
|
||||
static int TokStartsType(Parser *P, int Off) {
|
||||
Token *T = PeekTok(P, Off);
|
||||
if (T->Kind == TK_NAME) {
|
||||
return 1;
|
||||
}
|
||||
return T->Kind == TK_OP
|
||||
&& (TokIsOp(T, "&") || TokIsOp(T, "[") || TokIsOp(T, "("));
|
||||
}
|
||||
|
||||
/* 消费注解前缀:const/volatile/static/export/extern/inline/state/define/typedef、
|
||||
* __attribute__((...))、BigEndian/bigend、LittleEndian/littlend。
|
||||
* 裸标记名(后面没有类型)不消费,按普通类型名解析。 */
|
||||
static int ParseTypePrefixes(Parser *P, PyObject **Markers, PyObject **Attributes,
|
||||
const char **ByteOrder) {
|
||||
for (;;) {
|
||||
Token *T = PeekTok(P, 0);
|
||||
if (T->Kind != TK_NAME || !TokStartsType(P, 1)) {
|
||||
break;
|
||||
}
|
||||
if (TokIsName(T, "__attribute__")) {
|
||||
if (!TokIsOp(PeekTok(P, 1), "(")) {
|
||||
break;
|
||||
}
|
||||
Token *AttrTok = NextTok(P);
|
||||
const char *End = NULL;
|
||||
int Depth = 0;
|
||||
for (;;) {
|
||||
Token *U = PeekTok(P, 0);
|
||||
if (U->Kind == TK_ENDMARKER) {
|
||||
SyntaxErrorAt(P, U, "`__attribute__(...)` 括号未闭合");
|
||||
return 0;
|
||||
}
|
||||
NextTok(P);
|
||||
if (TokIsOp(U, "(")) {
|
||||
Depth++;
|
||||
} else if (TokIsOp(U, ")")) {
|
||||
Depth--;
|
||||
if (Depth == 0) {
|
||||
End = U->End;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!AppendAttributesFromText(Attributes, AttrTok->Start, End - AttrTok->Start)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
static const char *MarkerNames[] = {
|
||||
"const", "volatile", "static", "export", "extern",
|
||||
"inline", "state", "define", "typedef"
|
||||
};
|
||||
const char *Marker = NULL;
|
||||
for (size_t I = 0; I < sizeof(MarkerNames) / sizeof(MarkerNames[0]); I++) {
|
||||
if (TokIsName(T, MarkerNames[I])) {
|
||||
Marker = MarkerNames[I];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Marker != NULL) {
|
||||
if (!AppendStringItem(Markers, Marker, (Py_ssize_t)strlen(Marker))) {
|
||||
return 0;
|
||||
}
|
||||
NextTok(P);
|
||||
continue;
|
||||
}
|
||||
if (TokIsName(T, "BigEndian") || TokIsName(T, "bigend")) {
|
||||
*ByteOrder = "big";
|
||||
NextTok(P);
|
||||
continue;
|
||||
}
|
||||
if (TokIsName(T, "LittleEndian") || TokIsName(T, "littlend")) {
|
||||
*ByteOrder = "little";
|
||||
NextTok(P);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 名称或属性名是否等于 Name(Name.id / Attribute.attr)。 */
|
||||
static int IsNameOrAttrNamed(PyObject *Node, const char *Name) {
|
||||
const char *Field = NodeIs(Node, "Name") ? "id"
|
||||
: (NodeIs(Node, "Attribute") ? "attr" : NULL);
|
||||
if (Field == NULL) {
|
||||
return 0;
|
||||
}
|
||||
PyObject *V = PyObject_GetAttrString(Node, Field);
|
||||
if (V == NULL) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
int Hit = PyUnicode_Check(V) && PyUnicode_CompareWithASCIIString(V, Name) == 0;
|
||||
Py_DECREF(V);
|
||||
return Hit;
|
||||
}
|
||||
|
||||
/* Constant 节点的整数值;非整数返回 0。 */
|
||||
static int ConstantIntValue(PyObject *Node, long *Out) {
|
||||
if (Node == NULL || !NodeIs(Node, "Constant")) {
|
||||
return 0;
|
||||
}
|
||||
PyObject *V = PyObject_GetAttrString(Node, "value");
|
||||
if (V == NULL) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
int Ok = 0;
|
||||
if (PyLong_Check(V)) {
|
||||
long L = PyLong_AsLong(V);
|
||||
if (L == -1 && PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
} else {
|
||||
*Out = L;
|
||||
Ok = 1;
|
||||
}
|
||||
}
|
||||
Py_DECREF(V);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
/* Bit(N) / Bit[N] 注解:设 BitWidth(无法求值宽度时记 1)。 */
|
||||
static void ApplyBitWidthAttr(PyObject *Node) {
|
||||
PyObject *Value = NULL;
|
||||
PyObject *WidthNode = NULL;
|
||||
if (NodeIs(Node, "Call")) {
|
||||
Value = PyObject_GetAttrString(Node, "func");
|
||||
if (Value != NULL && IsNameOrAttrNamed(Value, "Bit")) {
|
||||
PyObject *Args = PyObject_GetAttrString(Node, "args");
|
||||
if (Args != NULL && PyList_Check(Args) && PyList_GET_SIZE(Args) > 0) {
|
||||
WidthNode = PyList_GET_ITEM(Args, 0);
|
||||
Py_INCREF(WidthNode);
|
||||
}
|
||||
Py_XDECREF(Args);
|
||||
}
|
||||
} else if (NodeIs(Node, "Subscript")) {
|
||||
Value = PyObject_GetAttrString(Node, "value");
|
||||
if (Value != NULL && IsNameOrAttrNamed(Value, "Bit")) {
|
||||
WidthNode = PyObject_GetAttrString(Node, "slice");
|
||||
}
|
||||
}
|
||||
if (WidthNode != NULL) {
|
||||
long Width = 0;
|
||||
SetAttrLong(Node, "BitWidth", ConstantIntValue(WidthNode, &Width) ? Width : 1);
|
||||
Py_DECREF(WidthNode);
|
||||
}
|
||||
Py_XDECREF(Value);
|
||||
}
|
||||
|
||||
/* 把前缀修饰写入注解节点的 Markers / Attributes / ByteOrder。 */
|
||||
static void ApplyTypeModifiers(PyObject *Node, PyObject *Markers, PyObject *Attributes,
|
||||
const char *ByteOrder) {
|
||||
if (Markers != NULL && PyList_GET_SIZE(Markers) > 0) {
|
||||
if (PyObject_SetAttrString(Node, "Markers", Markers) < 0) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
if (Attributes != NULL && PyList_GET_SIZE(Attributes) > 0) {
|
||||
if (PyObject_SetAttrString(Node, "Attributes", Attributes) < 0) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
if (ByteOrder != NULL) {
|
||||
PyObject *Order = PyUnicode_FromString(ByteOrder);
|
||||
if (Order != NULL) {
|
||||
if (PyObject_SetAttrString(Node, "ByteOrder", Order) < 0) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
Py_DECREF(Order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 类型注解入口:置注解模式标志(对齐 Python ExprParser._ParseTypeAnnotation)。
|
||||
*
|
||||
* 值引用参数注解(仅形参位有效,对齐纯 Python 端):
|
||||
* 前导 '&' + 可选名 'temp',合成联合形态 base | t.CRef(ref)/ base | t.CTempRef(temp)。
|
||||
* 前导 '&' + 可选名 'temp',构造 Subscript(Name('CRef'), T) / Subscript(Name('CTempRef'), T)。
|
||||
* CRef/CTempRef 非真实类,仅作注解 AST 内的名字标记(语义侧按名字识别)。
|
||||
* '&'/'&temp' 之后缺类型(行尾 / ')' / ',' / ':' / '=' / ']' / '}' / ';')时响亮失败。 */
|
||||
static PyObject *ParseTypeAnnotation(Parser *P) {
|
||||
PyObject *Markers = NULL;
|
||||
PyObject *Attributes = NULL;
|
||||
const char *ByteOrder = NULL;
|
||||
if (!ParseTypePrefixes(P, &Markers, &Attributes, &ByteOrder)) {
|
||||
Py_XDECREF(Markers);
|
||||
Py_XDECREF(Attributes);
|
||||
return NULL;
|
||||
}
|
||||
int RefTemp = 0; /* 0=非值引用 1=ref 2=temp */
|
||||
Token *RefTok = PeekTok(P, 0);
|
||||
if (AtOp(P, "&")) {
|
||||
@@ -2737,6 +3025,8 @@ static PyObject *ParseTypeAnnotation(Parser *P) {
|
||||
|| TokIsOp(End, ";")) {
|
||||
SyntaxErrorAt(P, End,
|
||||
"值引用参数注解缺少类型:`&` 后必须紧跟类型 T(ref:`&T`;temp:`&temp T`)");
|
||||
Py_XDECREF(Markers);
|
||||
Py_XDECREF(Attributes);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -2745,31 +3035,26 @@ static PyObject *ParseTypeAnnotation(Parser *P) {
|
||||
PyObject *Node = ParseExpr(P);
|
||||
P->InTypeAnnotation = Saved;
|
||||
if (Node == NULL) {
|
||||
Py_XDECREF(Markers);
|
||||
Py_XDECREF(Attributes);
|
||||
return NULL;
|
||||
}
|
||||
if (RefTemp == 0) {
|
||||
return Node;
|
||||
}
|
||||
PyObject *Marker = MakeTAttrNode(P, RefTemp == 2 ? "CTempRef" : "CRef");
|
||||
if (Marker == NULL) {
|
||||
if (RefTemp != 0) {
|
||||
PyObject *Wrap = MakeTypeWrapperSubscript(
|
||||
P, RefTemp == 2 ? "CTempRef" : "CRef", Node, RefTok);
|
||||
Py_DECREF(Node);
|
||||
return NULL;
|
||||
if (Wrap == NULL) {
|
||||
Py_XDECREF(Markers);
|
||||
Py_XDECREF(Attributes);
|
||||
return NULL;
|
||||
}
|
||||
Node = Wrap;
|
||||
}
|
||||
PyObject *Op = MakeSingleton(P, "BitOr");
|
||||
if (Op == NULL) {
|
||||
Py_DECREF(Node);
|
||||
Py_DECREF(Marker);
|
||||
return NULL;
|
||||
}
|
||||
PyObject *Argv[3] = { Node, Op, Marker };
|
||||
PyObject *Wrap = NewNode(P, "BinOp", Argv, 3);
|
||||
Py_DECREF(Op);
|
||||
Py_DECREF(Marker);
|
||||
Py_DECREF(Node);
|
||||
if (Wrap != NULL) {
|
||||
FixLoc(P, Wrap, RefTok);
|
||||
}
|
||||
return Wrap;
|
||||
ApplyTypeModifiers(Node, Markers, Attributes, ByteOrder);
|
||||
ApplyBitWidthAttr(Node);
|
||||
Py_XDECREF(Markers);
|
||||
Py_XDECREF(Attributes);
|
||||
return Node;
|
||||
}
|
||||
|
||||
/* term:factor (*|/|//|%|@ factor)* */
|
||||
@@ -5489,7 +5774,7 @@ static PyObject *ParseFunctionDef(Parser *P, int IsAsync, PyObject *Decorators)
|
||||
if (Start->Kind == TK_NAME && TokIsName(Start, "async")) {
|
||||
Start = NextTok(P); /* def */
|
||||
}
|
||||
/* define 宏函数关键字(语法与 def 一致,返回注解自动追加 t.CDefine) */
|
||||
/* define 宏函数关键字(语法与 def 一致,产出 FunctionDef.Define=True) */
|
||||
int IsDefine = (Start->Kind == TK_NAME && TokIsName(Start, "define"));
|
||||
Token *NameTok = ExpectName(P, NULL);
|
||||
if (NameTok == NULL) {
|
||||
@@ -5566,31 +5851,8 @@ static PyObject *ParseFunctionDef(Parser *P, int IsAsync, PyObject *Decorators)
|
||||
Py_DECREF(Argv[3]);
|
||||
}
|
||||
if (Node != NULL && IsDefine) {
|
||||
/* 标记 define 宏函数(Unparser 据此还原语法) */
|
||||
/* 标记 define 宏函数(Unparser 据此还原语法);返回注解保持原样 */
|
||||
PyObject_SetAttrString(Node, "Define", Py_True);
|
||||
/* 返回注解改写:<原类型> | t.CDefine / 单独 t.CDefine(宏函数标记,
|
||||
NewNode 后 Returns 引用仍有效,此处仅替换 Node.returns) */
|
||||
PyObject *TAttr = MakeTAttrNode(P, "CDefine");
|
||||
if (TAttr != NULL) {
|
||||
if (Returns != NULL) {
|
||||
PyObject *Op = MakeSingleton(P, "BitOr");
|
||||
if (Op != NULL) {
|
||||
PyObject *ArgvB[3];
|
||||
ArgvB[0] = Returns;
|
||||
ArgvB[1] = Op;
|
||||
ArgvB[2] = TAttr;
|
||||
PyObject *Bin = NewNode(P, "BinOp", ArgvB, 3);
|
||||
if (Bin != NULL) {
|
||||
PyObject_SetAttrString(Node, "returns", Bin);
|
||||
Py_DECREF(Bin);
|
||||
}
|
||||
Py_DECREF(Op);
|
||||
}
|
||||
} else {
|
||||
PyObject_SetAttrString(Node, "returns", TAttr);
|
||||
}
|
||||
Py_DECREF(TAttr);
|
||||
}
|
||||
}
|
||||
Py_XDECREF(Returns);
|
||||
Py_DECREF(TypeParams);
|
||||
@@ -5619,8 +5881,7 @@ static PyObject *MakeTAttrNode(Parser *P, const char *AttrName) {
|
||||
/* extern/export 函数声明(FFI/裸名导出,对齐 vast Parser._ParseExternDef/_ParseExportDef)。
|
||||
* 允许语法(4 种,配不配 def 都一样,无 `:` 时 body 为空):
|
||||
* extern [def] A(x: int) -> int [': pass']
|
||||
* 产出标准 FunctionDef:返回注解改写为 <原类型> | t.State(extern)/ <原类型> | t.CExport(export),
|
||||
* 并设 Extern=True / Export=True 供 Unparser 还原。 */
|
||||
* 产出标准 FunctionDef:返回注解保持原样,设 Extern=True / Export=True 供 Unparser 还原。 */
|
||||
static PyObject *ParseExternDef(Parser *P, int IsExport, PyObject *Decorators) {
|
||||
Token *Start = NextTok(P); /* 'extern' / 'export' */
|
||||
if (AtName(P, "def")) {
|
||||
@@ -5710,30 +5971,8 @@ static PyObject *ParseExternDef(Parser *P, int IsExport, PyObject *Decorators) {
|
||||
Py_XDECREF(Returns);
|
||||
return NULL;
|
||||
}
|
||||
/* 标记 extern/export(Unparser 据此还原语法) */
|
||||
/* 标记 extern/export(Unparser 据此还原语法);返回注解保持原样 */
|
||||
PyObject_SetAttrString(Node, IsExport ? "Export" : "Extern", Py_True);
|
||||
/* 返回注解改写:<原类型> | t.State / <原类型> | t.CExport(NewNode 后 Returns 引用仍有效) */
|
||||
PyObject *TAttr = MakeTAttrNode(P, IsExport ? "CExport" : "State");
|
||||
if (TAttr != NULL) {
|
||||
if (Returns != NULL) {
|
||||
PyObject *Op = MakeSingleton(P, "BitOr");
|
||||
if (Op != NULL) {
|
||||
PyObject *ArgvB[3];
|
||||
ArgvB[0] = Returns;
|
||||
ArgvB[1] = Op;
|
||||
ArgvB[2] = TAttr;
|
||||
PyObject *Bin = NewNode(P, "BinOp", ArgvB, 3);
|
||||
if (Bin != NULL) {
|
||||
PyObject_SetAttrString(Node, "returns", Bin);
|
||||
Py_DECREF(Bin);
|
||||
}
|
||||
Py_DECREF(Op);
|
||||
}
|
||||
} else {
|
||||
PyObject_SetAttrString(Node, "returns", TAttr);
|
||||
}
|
||||
Py_DECREF(TAttr);
|
||||
}
|
||||
Py_XDECREF(Returns);
|
||||
FixLoc(P, Node, Start);
|
||||
return Node;
|
||||
|
||||
Reference in new issue
Block a user