修复了大量存在的问题,增加了假鸭子类型等等机制

This commit is contained in:
2026-06-25 14:49:46 +08:00
parent 19f2787db0
commit d88d11b646
827 changed files with 32617 additions and 18316 deletions

View File

@@ -3,26 +3,51 @@ from __future__ import annotations
import ast
from lib.includes import t
_T_MODULE_NAMES: frozenset[str] = frozenset({'t', t.__name__})
def IsTModule(module_id: str, symtable: object | None = None) -> bool:
"""检查模块标识符是否指向 t 类型模块(支持别名如 import t as tt"""
if module_id in _T_MODULE_NAMES:
return True
if symtable is not None and hasattr(symtable, 'import_aliases'):
resolved: str = symtable.import_aliases.get(module_id, module_id)
if resolved in _T_MODULE_NAMES:
return True
return False
def IsTModulePath(module_path: str) -> bool:
"""检查模块路径是否指向 t 类型模块"""
if module_path in _T_MODULE_NAMES:
return True
if module_path:
t_name: str
for t_name in _T_MODULE_NAMES:
if module_path == t_name or module_path.startswith(t_name + '.'):
return True
return False
def IsTModuleType(TypeName: str) -> bool:
"""检测类型名称是否是 t 模块中的类型CType 或其他特殊类型)"""
if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'):
return True
TypeClass = getattr(t, TypeName, None)
TypeClass: type | None = getattr(t, TypeName, None)
if TypeClass and isinstance(TypeClass, type):
if issubclass(TypeClass, t.CType):
return True
FallbackClass = getattr(t, f'_{TypeName}', None)
FallbackClass: type | None = getattr(t, f'_{TypeName}', None)
if FallbackClass and isinstance(FallbackClass, type):
if issubclass(FallbackClass, t.CType):
return True
return False
def AnnotationContainsTType(node, TypeName: str) -> bool:
def AnnotationContainsTType(node: ast.AST, TypeName: str) -> bool:
"""检测 AST 节点中是否包含指定名称的 t 模块类型"""
if isinstance(node, ast.Attribute):
if (hasattr(node.value, 'id') and node.value.id == 't' and
if (hasattr(node.value, 'id') and IsTModule(node.value.id) and
node.attr == TypeName):
return True
elif isinstance(node, ast.BinOp):
@@ -41,12 +66,70 @@ def AnnotationContainsTType(node, TypeName: str) -> bool:
return False
def CheckAnnotationHasCInline(annotation_node) -> bool:
def IsListAnnotation(annotation: ast.expr) -> bool:
"""检查注解是否为 t.CArray[...] 类型(栈上固定数组)"""
if not isinstance(annotation, ast.Subscript):
return False
value = annotation.value
# t.CArray[...]
if (isinstance(value, ast.Attribute)
and isinstance(value.value, ast.Name)
and value.value.id == 't'
and value.attr == 'CArray'):
return True
return False
def ExtractListFromBinOp(annotation: ast.expr) -> ast.Subscript | None:
"""从 BinOp(BitOr) 注解中提取 list[...] 部分,如 list[i32] | t.CPtr"""
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
for side in (annotation.left, annotation.right):
if IsListAnnotation(side):
return side
return None
class ListAnnotationParseResult:
"""list[...] 注解解析结果。
is_pointer=True 表示单参数 list[type] → 指针模式;
is_pointer=False 表示 Tuple(2) 模式 list[type, count]。
"""
__slots__ = ('elem_type_node', 'count_node', 'is_pointer')
def __init__(self, elem_type_node: ast.expr, count_node: ast.expr | None, is_pointer: bool) -> None:
self.elem_type_node: ast.expr = elem_type_node
self.count_node: ast.expr | None = count_node
self.is_pointer: bool = is_pointer
def ParseListAnnotation(annotation: ast.expr) -> ListAnnotationParseResult | None:
"""解析 list[...] 注解,统一处理 list[type, count] / list[type] / BinOp(BitOr) 形式。
自动处理 BinOp(BitOr) 包裹(如 list[i32, N] | t.CPtr
返回 None 表示不是 list 注解。
"""
list_node: ast.expr = annotation
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
extracted: ast.Subscript | None = ExtractListFromBinOp(annotation)
if extracted is None:
return None
list_node = extracted
if not IsListAnnotation(list_node):
return None
slice_node: ast.AST = list_node.slice
if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2:
return ListAnnotationParseResult(slice_node.elts[0], slice_node.elts[1], is_pointer=False)
# 单参数 list[type] → 指针模式
return ListAnnotationParseResult(slice_node, None, is_pointer=True)
def CheckAnnotationHasCInline(annotation_node: ast.AST | None) -> bool:
"""检测注解节点中是否包含 CInline"""
if annotation_node is None:
return False
if isinstance(annotation_node, ast.Attribute):
if hasattr(annotation_node.value, 'id') and annotation_node.value.id == 't' and annotation_node.attr == 'CInline':
if hasattr(annotation_node.value, 'id') and IsTModule(annotation_node.value.id) and annotation_node.attr == 'CInline':
return True
if isinstance(annotation_node, ast.Name):
if annotation_node.id == 'CInline':
@@ -54,3 +137,50 @@ def CheckAnnotationHasCInline(annotation_node) -> bool:
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
return CheckAnnotationHasCInline(annotation_node.left) or CheckAnnotationHasCInline(annotation_node.right)
return False
def ExtractTypeNameFromBinOp(annotation: ast.expr) -> str | None:
"""从 BinOp(BitOr) 注解左侧提取类型名(如 TypeA | TypeB → TypeA
返回 Name.id 或 Attribute.attr非 BinOp 返回 None。
"""
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
left: ast.expr = annotation.left
if isinstance(left, ast.Name):
return left.id
if isinstance(left, ast.Attribute):
return left.attr
return None
def FindStructNameInAnnotation(node: ast.AST, struct_names: dict | set) -> str | None:
"""递归在注解中查找结构体名(支持 BinOp(BitOr) 递归)。
检查 Name.id、Constant.str、Attribute.attr 是否在 struct_names 中。
"""
if isinstance(node, ast.Name) and node.id in struct_names:
return node.id
if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in struct_names:
return node.value
if isinstance(node, ast.Attribute) and node.attr in struct_names:
return node.attr
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
result: str | None = FindStructNameInAnnotation(node.left, struct_names)
if result:
return result
return FindStructNameInAnnotation(node.right, struct_names)
return None
def AnnotationContainsName(annotation: ast.AST, name: str) -> bool:
"""检查注解中是否包含指定名称(支持 BinOp(BitOr) 递归)。
同时检查 Attribute.attr 和 Name.id比 ast.dump 字符串匹配更精确。
"""
if isinstance(annotation, ast.Attribute):
return annotation.attr == name
if isinstance(annotation, ast.Name):
return annotation.id == name
if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr):
return AnnotationContainsName(annotation.left, name) or AnnotationContainsName(annotation.right, name)
return False