将 EnumName/value/IsSigned 加入 FIELD_ROUTES,消除所有冗余 hasattr/getattr
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
404
lib/core/ConstEvaluator.py
Normal file
404
lib/core/ConstEvaluator.py
Normal file
@@ -0,0 +1,404 @@
|
||||
"""统一常量表达式求值器
|
||||
|
||||
整合了原先分散在 5 处的常量求值逻辑:
|
||||
- SymbolTable._eval_const_expr
|
||||
- CTypeInfo.TryEvalConstExpr
|
||||
- ConstEvalMixin._try_eval_const_expr
|
||||
- HandlesAssign._eval_const_expr
|
||||
- HandlesIf._eval_const_expr
|
||||
|
||||
ConstEvaluator 提供三个级别的求值:
|
||||
1. eval_basic(node) — 纯 AST 常量 + 算术(无外部依赖)
|
||||
2. eval_with_symtab(node) — + SymbolTable 中的 define 查找
|
||||
3. eval_full(node, ctx) — + Gen._define_constants / _all_define_constants / 平台宏
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class ConstEvaluator:
|
||||
"""统一常量表达式求值器"""
|
||||
|
||||
# ==================================================================
|
||||
# Level 1: 纯 AST 常量 + 算术(无外部依赖)
|
||||
# ==================================================================
|
||||
|
||||
@staticmethod
|
||||
def eval_basic(node: ast.AST) -> Optional[Any]:
|
||||
"""求值纯常量表达式,不依赖任何外部符号表。
|
||||
|
||||
支持: Constant, BinOp, UnaryOp
|
||||
"""
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
return ConstEvaluator._eval_arith(node, ConstEvaluator.eval_basic)
|
||||
|
||||
# ==================================================================
|
||||
# Level 2: + SymbolTable define 查找
|
||||
# ==================================================================
|
||||
|
||||
@staticmethod
|
||||
def eval_with_symtab(node: ast.AST, symtab) -> Optional[Any]:
|
||||
"""求值常量表达式,支持从 SymbolTable 查找 define 值。
|
||||
|
||||
支持: Constant, BinOp, UnaryOp, Name(define), Attribute(define)
|
||||
"""
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
if isinstance(node, ast.Name):
|
||||
if hasattr(symtab, '__contains__') and node.id in symtab:
|
||||
info = symtab[node.id]
|
||||
if info.IsDefine and isinstance(info.DefineValue, int):
|
||||
return info.DefineValue
|
||||
return None
|
||||
if isinstance(node, ast.Attribute):
|
||||
return ConstEvaluator._eval_attribute_define(node, symtab)
|
||||
return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_with_symtab(n, symtab))
|
||||
|
||||
# ==================================================================
|
||||
# Level 3: + Gen._define_constants / _all_define_constants / 平台宏
|
||||
# ==================================================================
|
||||
|
||||
@staticmethod
|
||||
def eval_full(node: ast.AST, ctx: 'EvalContext') -> Optional[Any]:
|
||||
"""完整求值,支持 define_constants、平台宏、BoolOp、Compare。
|
||||
|
||||
ctx: EvalContext 实例,封装了 Gen、SymbolTable 等上下文。
|
||||
"""
|
||||
# BoolOp (HandlesIf 逻辑)
|
||||
if isinstance(node, ast.BoolOp):
|
||||
if isinstance(node.op, ast.And):
|
||||
for val in node.values:
|
||||
result = ConstEvaluator.eval_full(val, ctx)
|
||||
if result is None:
|
||||
return None
|
||||
if not result:
|
||||
return 0
|
||||
return 1
|
||||
elif isinstance(node.op, ast.Or):
|
||||
for val in node.values:
|
||||
result = ConstEvaluator.eval_full(val, ctx)
|
||||
if result is None:
|
||||
return None
|
||||
if result:
|
||||
return 1
|
||||
return 0
|
||||
return None
|
||||
|
||||
# Compare (HandlesIf 逻辑)
|
||||
if isinstance(node, ast.Compare):
|
||||
left = ConstEvaluator.eval_full(node.left, ctx)
|
||||
if left is None:
|
||||
return None
|
||||
for op, comparator in zip(node.ops, node.comparators):
|
||||
right = ConstEvaluator.eval_full(comparator, ctx)
|
||||
if right is None:
|
||||
return None
|
||||
result = ConstEvaluator._eval_compare_op(op, left, right)
|
||||
if result is None:
|
||||
return None
|
||||
if not result:
|
||||
return 0
|
||||
left = right
|
||||
return 1
|
||||
|
||||
# Constant — 直接返回原始值,bool→0/1 转换由 HandlesIf 自行处理
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
|
||||
# Name — 查 define_constants / SymbolTable / 平台宏
|
||||
if isinstance(node, ast.Name):
|
||||
return ctx.lookup_name(node.id)
|
||||
|
||||
# Attribute — 查 define_constants / SymbolTable / 平台宏
|
||||
if isinstance(node, ast.Attribute):
|
||||
return ctx.lookup_attribute(node)
|
||||
|
||||
# UnaryOp
|
||||
if isinstance(node, ast.UnaryOp):
|
||||
operand = ConstEvaluator.eval_full(node.operand, ctx)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.Not):
|
||||
return 1 if not operand else 0
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
if isinstance(node.op, ast.UAdd):
|
||||
return +operand
|
||||
if isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
return None
|
||||
|
||||
# BinOp
|
||||
return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_full(n, ctx))
|
||||
|
||||
# ==================================================================
|
||||
# 内部辅助
|
||||
# ==================================================================
|
||||
|
||||
@staticmethod
|
||||
def _eval_arith(node: ast.AST, recurse) -> Optional[Any]:
|
||||
"""通用算术求值:BinOp + UnaryOp"""
|
||||
if isinstance(node, ast.BinOp):
|
||||
left = recurse(node.left)
|
||||
right = recurse(node.right)
|
||||
if left is None or right is None:
|
||||
return None
|
||||
return ConstEvaluator._apply_binop(node.op, left, right)
|
||||
if isinstance(node, ast.UnaryOp):
|
||||
operand = recurse(node.operand)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
if isinstance(node.op, ast.UAdd):
|
||||
return +operand
|
||||
if isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
return None
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _apply_binop(op: ast.operator, left, right) -> Optional[Any]:
|
||||
"""应用二元运算符"""
|
||||
try:
|
||||
if isinstance(op, ast.Add):
|
||||
return left + right
|
||||
elif isinstance(op, ast.Sub):
|
||||
return left - right
|
||||
elif isinstance(op, ast.Mult):
|
||||
return left * right
|
||||
elif isinstance(op, ast.Div):
|
||||
return left // right if isinstance(left, int) and isinstance(right, int) else left / right
|
||||
elif isinstance(op, ast.FloorDiv):
|
||||
if isinstance(right, (int, float)) and right == 0:
|
||||
return None
|
||||
return left // right
|
||||
elif isinstance(op, ast.Mod):
|
||||
if isinstance(right, (int, float)) and right == 0:
|
||||
return None
|
||||
return left % right
|
||||
elif isinstance(op, ast.Pow):
|
||||
return left ** right
|
||||
elif isinstance(op, ast.LShift):
|
||||
return left << right
|
||||
elif isinstance(op, ast.RShift):
|
||||
return left >> right
|
||||
elif isinstance(op, ast.BitOr):
|
||||
return left | right
|
||||
elif isinstance(op, ast.BitXor):
|
||||
return left ^ right
|
||||
elif isinstance(op, ast.BitAnd):
|
||||
return left & right
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _eval_compare_op(op, left, right) -> Optional[bool]:
|
||||
"""应用比较运算符"""
|
||||
if isinstance(op, ast.Eq):
|
||||
return left == right
|
||||
elif isinstance(op, ast.NotEq):
|
||||
return left != right
|
||||
elif isinstance(op, ast.Lt):
|
||||
return left < right
|
||||
elif isinstance(op, ast.LtE):
|
||||
return left <= right
|
||||
elif isinstance(op, ast.Gt):
|
||||
return left > right
|
||||
elif isinstance(op, ast.GtE):
|
||||
return left >= right
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _eval_attribute_define(node: ast.Attribute, symtab) -> Optional[Any]:
|
||||
"""从 SymbolTable 查找 Attribute 形式的 define 值"""
|
||||
parts = []
|
||||
current = node
|
||||
while isinstance(current, ast.Attribute):
|
||||
parts.append(current.attr)
|
||||
current = current.value
|
||||
if isinstance(current, ast.Name):
|
||||
parts.append(current.id)
|
||||
parts.reverse()
|
||||
attr_name = parts[-1]
|
||||
possible_keys = [attr_name, '.'.join(parts)]
|
||||
for key in possible_keys:
|
||||
if hasattr(symtab, '__contains__') and key in symtab:
|
||||
info = symtab[key]
|
||||
if info.IsDefine and isinstance(info.DefineValue, int):
|
||||
return info.DefineValue
|
||||
# 模糊匹配
|
||||
if len(parts) >= 2:
|
||||
for mod_key, mod_info in (symtab.items() if hasattr(symtab, 'items') else []):
|
||||
if mod_info.IsDefine and isinstance(mod_info.DefineValue, int):
|
||||
if mod_key.endswith('.' + attr_name) or mod_key == attr_name:
|
||||
return mod_info.DefineValue
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _intify(val):
|
||||
"""float → int 转换(仅当 float 值恰好是整数时)"""
|
||||
if isinstance(val, float) and val == int(val):
|
||||
return int(val)
|
||||
return val
|
||||
|
||||
|
||||
class EvalContext:
|
||||
"""常量求值上下文,封装 Gen / SymbolTable / 平台宏查找逻辑。
|
||||
|
||||
由调用方构造并传入 ConstEvaluator.eval_full()。
|
||||
"""
|
||||
|
||||
def __init__(self, Gen=None, symtab=None, platform_macros: dict | None = None):
|
||||
self.Gen = Gen
|
||||
self.symtab = symtab
|
||||
self._platform_macros = platform_macros
|
||||
|
||||
def lookup_name(self, name: str) -> Optional[Any]:
|
||||
"""查找 Name 节点的值:define_constants → SymbolTable → 平台宏"""
|
||||
# 1. Gen._define_constants
|
||||
if self.Gen and hasattr(self.Gen, '_define_constants') and name in self.Gen._define_constants:
|
||||
val = self.Gen._define_constants[name]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
|
||||
# 2. Gen._DefineConstants (大写版本)
|
||||
if self.Gen and hasattr(self.Gen, '_DefineConstants') and name in self.Gen._DefineConstants:
|
||||
val = self.Gen._DefineConstants[name]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
|
||||
# 3. SymbolTable
|
||||
if self.symtab and name in self.symtab:
|
||||
info = self.symtab[name]
|
||||
val = info.value
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
if info.IsDefine and isinstance(info.DefineValue, (int, float)):
|
||||
return ConstEvaluator._intify(info.DefineValue)
|
||||
|
||||
# 4. 平台宏
|
||||
macros = self._get_platform_macros()
|
||||
if name in macros:
|
||||
return macros[name]
|
||||
|
||||
return None
|
||||
|
||||
def lookup_attribute(self, node: ast.Attribute) -> Optional[Any]:
|
||||
"""查找 Attribute 节点的值"""
|
||||
module_name = node.value.id if isinstance(node.value, ast.Name) else None
|
||||
attr_name = node.attr
|
||||
|
||||
if module_name and attr_name:
|
||||
combined_key = f"{module_name}.{attr_name}"
|
||||
|
||||
# 1. Gen._define_constants
|
||||
if self.Gen and hasattr(self.Gen, '_define_constants') and combined_key in self.Gen._define_constants:
|
||||
val = self.Gen._define_constants[combined_key]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
|
||||
# 2. SymbolTable (精确匹配 + 后缀匹配)
|
||||
if self.symtab:
|
||||
for key, info in self.symtab.items():
|
||||
if key.endswith(f".{combined_key}") or key == combined_key:
|
||||
if info.IsDefine and isinstance(info.DefineValue, (int, float)):
|
||||
return ConstEvaluator._intify(info.DefineValue)
|
||||
|
||||
# 3. _all_define_constants
|
||||
all_dc = self._get_all_define_constants()
|
||||
if combined_key in all_dc:
|
||||
val = all_dc[combined_key]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
if attr_name in all_dc:
|
||||
val = all_dc[attr_name]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
for dc_key, dc_val in all_dc.items():
|
||||
if dc_key == attr_name or dc_key.endswith(f".{attr_name}"):
|
||||
if isinstance(dc_val, (int, float)):
|
||||
return ConstEvaluator._intify(dc_val)
|
||||
|
||||
# 4. SymbolTable 短名查找
|
||||
if self.symtab and attr_name in self.symtab:
|
||||
info = self.symtab[attr_name]
|
||||
if info.IsDefine and isinstance(info.DefineValue, (int, float)):
|
||||
return ConstEvaluator._intify(info.DefineValue)
|
||||
|
||||
# 5. Gen._define_constants 短名
|
||||
if self.Gen and hasattr(self.Gen, '_define_constants') and attr_name in self.Gen._define_constants:
|
||||
val = self.Gen._define_constants[attr_name]
|
||||
if isinstance(val, (int, float)):
|
||||
return ConstEvaluator._intify(val)
|
||||
|
||||
# 6. 平台宏
|
||||
macros = self._get_platform_macros()
|
||||
full_key = self._get_attr_full_name(node)
|
||||
if full_key:
|
||||
if full_key in macros:
|
||||
return macros[full_key]
|
||||
short_name = full_key.split('.')[-1] if '.' in full_key else full_key
|
||||
if short_name in macros:
|
||||
return macros[short_name]
|
||||
|
||||
return None
|
||||
|
||||
def _get_all_define_constants(self) -> dict:
|
||||
"""获取 _all_define_constants"""
|
||||
if self.Gen and hasattr(self.Gen, '_all_define_constants'):
|
||||
return self.Gen._all_define_constants
|
||||
return {}
|
||||
|
||||
def _get_platform_macros(self) -> dict:
|
||||
"""获取平台宏"""
|
||||
if self._platform_macros is not None:
|
||||
return self._platform_macros
|
||||
if not self.Gen:
|
||||
return {}
|
||||
macros = {}
|
||||
pi = getattr(self.Gen, '_platform_info', {})
|
||||
ptr_size = getattr(self.Gen, 'ptr_size', 8)
|
||||
if pi.get('is_windows'):
|
||||
macros['_WIN32'] = 1
|
||||
if not pi.get('is_32bit'):
|
||||
macros['_WIN64'] = 1
|
||||
macros['WIN64'] = 1
|
||||
macros['WIN32'] = 1
|
||||
if pi.get('is_linux'):
|
||||
macros['__linux__'] = 1
|
||||
if pi.get('is_macos'):
|
||||
macros['__APPLE__'] = 1
|
||||
macros['__MACH__'] = 1
|
||||
if pi.get('is_x86_64'):
|
||||
macros['__x86_64__'] = 1
|
||||
macros['__x86_64'] = 1
|
||||
macros['_M_X64'] = 1
|
||||
elif pi.get('is_arm64'):
|
||||
macros['__aarch64__'] = 1
|
||||
macros['_M_ARM64'] = 1
|
||||
if not pi.get('is_32bit') and pi.get('is_linux'):
|
||||
macros['__LP64__'] = 1
|
||||
elif pi.get('is_32bit'):
|
||||
macros['_ILP32'] = 1
|
||||
macros['SIZEOF_VOID_P'] = ptr_size
|
||||
macros['__SIZEOF_POINTER__'] = ptr_size
|
||||
macros['NDEBUG'] = 0
|
||||
return macros
|
||||
|
||||
@staticmethod
|
||||
def _get_attr_full_name(node: ast.Attribute) -> Optional[str]:
|
||||
"""从 Attribute 节点提取完整名称 (e.g. 'module.name')"""
|
||||
parts = []
|
||||
current = node
|
||||
while isinstance(current, ast.Attribute):
|
||||
parts.append(current.attr)
|
||||
current = current.value
|
||||
if isinstance(current, ast.Name):
|
||||
parts.append(current.id)
|
||||
parts.reverse()
|
||||
return '.'.join(parts) if parts else None
|
||||
79
lib/core/DiagnosticCollector.py
Normal file
79
lib/core/DiagnosticCollector.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""诊断系统 — 收集编译过程中的警告和错误
|
||||
|
||||
替代原先静默回退的模式:
|
||||
- return 'i32' → 记录 Warning + 回退到 'i32'
|
||||
- return [] → 记录 Error + 回退到 []
|
||||
|
||||
使用方式:
|
||||
diag = DiagnosticCollector()
|
||||
diag.warn(file, lineno, "无法解析类型,回退到 i32")
|
||||
diag.error(file, lineno, f"加载模块失败: {path}")
|
||||
diag.report() # 打印所有诊断信息
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class DiagnosticLevel(Enum):
|
||||
WARNING = "WARNING"
|
||||
ERROR = "ERROR"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Diagnostic:
|
||||
level: DiagnosticLevel
|
||||
file: str
|
||||
lineno: int
|
||||
message: str
|
||||
|
||||
def __str__(self):
|
||||
short_file = os.path.basename(self.file) if self.file else "<unknown>"
|
||||
return f"[{self.level.value}] {short_file}:{self.lineno} — {self.message}"
|
||||
|
||||
|
||||
class DiagnosticCollector:
|
||||
"""诊断信息收集器"""
|
||||
|
||||
def __init__(self):
|
||||
self._diagnostics: List[Diagnostic] = []
|
||||
|
||||
def warn(self, file: str, lineno: int, message: str):
|
||||
self._diagnostics.append(Diagnostic(DiagnosticLevel.WARNING, file, lineno, message))
|
||||
|
||||
def error(self, file: str, lineno: int, message: str):
|
||||
self._diagnostics.append(Diagnostic(DiagnosticLevel.ERROR, file, lineno, message))
|
||||
|
||||
@property
|
||||
def warnings(self) -> List[Diagnostic]:
|
||||
return [d for d in self._diagnostics if d.level == DiagnosticLevel.WARNING]
|
||||
|
||||
@property
|
||||
def errors(self) -> List[Diagnostic]:
|
||||
return [d for d in self._diagnostics if d.level == DiagnosticLevel.ERROR]
|
||||
|
||||
@property
|
||||
def has_errors(self) -> bool:
|
||||
return any(d.level == DiagnosticLevel.ERROR for d in self._diagnostics)
|
||||
|
||||
@property
|
||||
def has_warnings(self) -> bool:
|
||||
return any(d.level == DiagnosticLevel.WARNING for d in self._diagnostics)
|
||||
|
||||
def report(self, min_level: DiagnosticLevel = DiagnosticLevel.WARNING):
|
||||
"""打印所有诊断信息"""
|
||||
for d in self._diagnostics:
|
||||
if d.level.value >= min_level.value:
|
||||
print(d)
|
||||
|
||||
def clear(self):
|
||||
self._diagnostics.clear()
|
||||
|
||||
def __len__(self):
|
||||
return len(self._diagnostics)
|
||||
|
||||
def __bool__(self):
|
||||
return len(self._diagnostics) > 0
|
||||
@@ -82,7 +82,7 @@ class AnnAssignHandle(BaseHandle):
|
||||
IsUnion = False
|
||||
if ClassName and ClassName in self.Trans.SymbolTable:
|
||||
TypeInfo = self.Trans.SymbolTable[ClassName]
|
||||
if hasattr(TypeInfo, 'IsUnion') and TypeInfo.IsUnion:
|
||||
if TypeInfo.IsUnion:
|
||||
IsUnion = True
|
||||
if ClassName and ClassName in Gen.structs:
|
||||
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||||
|
||||
@@ -440,8 +440,8 @@ class AssignHandle:
|
||||
sym_key = f"{ModulePath}.{FuncName}"
|
||||
sym_info = self.Trans.SymbolTable.get(sym_key)
|
||||
if sym_info and sym_info.IsFunction:
|
||||
ret_type_info = getattr(sym_info, 'FuncPtrReturn', None)
|
||||
param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])]
|
||||
ret_type_info = sym_info.FuncPtrReturn
|
||||
param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])]
|
||||
if ret_type_info:
|
||||
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||
ret_type = ret_type_info.ToLLVM(Gen)
|
||||
@@ -616,7 +616,7 @@ class AssignHandle:
|
||||
if ClassName and ClassName in Gen.structs:
|
||||
PropKey = f'{ClassName}.{AttrName}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
|
||||
SelfVar = Gen._get_var_ptr('self')
|
||||
if SelfVar:
|
||||
SelfPtr = Gen._load(SelfVar, name="self")
|
||||
@@ -734,7 +734,7 @@ class AssignHandle:
|
||||
if ClassName and ClassName in Gen.structs:
|
||||
PropKey = f'{ClassName}.{AttrName}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList:
|
||||
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||||
SetterFunc = Gen._get_function(PropKey + '$set')
|
||||
if SetterFunc and ObjVal:
|
||||
@@ -1222,7 +1222,7 @@ class AssignHandle:
|
||||
elif isinstance(count_node, ast.Name):
|
||||
if count_node.id in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[count_node.id]
|
||||
if isinstance(getattr(SymInfo, 'value', None), int):
|
||||
if isinstance(SymInfo.value, int):
|
||||
ArrayCount = SymInfo.value
|
||||
if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}):
|
||||
DefVal = Gen._define_constants[count_node.id]
|
||||
@@ -1558,94 +1558,10 @@ class AssignHandle:
|
||||
Gen.variables[VarName] = GlobalVar
|
||||
|
||||
def _eval_const_expr(self, node, Gen):
|
||||
"""计算常量表达式的值"""
|
||||
import ast
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
elif isinstance(node, ast.BinOp):
|
||||
left = self._eval_const_expr(node.left, Gen)
|
||||
right = self._eval_const_expr(node.right, Gen)
|
||||
if left is None or right is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.Add):
|
||||
return left + right
|
||||
elif isinstance(node.op, ast.Sub):
|
||||
return left - right
|
||||
elif isinstance(node.op, ast.Mult):
|
||||
return left * right
|
||||
elif isinstance(node.op, ast.Div):
|
||||
return left // right if isinstance(left, int) and isinstance(right, int) else left / right
|
||||
elif isinstance(node.op, ast.FloorDiv):
|
||||
return left // right
|
||||
elif isinstance(node.op, ast.Mod):
|
||||
return left % right
|
||||
elif isinstance(node.op, ast.Pow):
|
||||
return left ** right
|
||||
elif isinstance(node.op, ast.LShift):
|
||||
return left << right
|
||||
elif isinstance(node.op, ast.RShift):
|
||||
return left >> right
|
||||
elif isinstance(node.op, ast.BitOr):
|
||||
return left | right
|
||||
elif isinstance(node.op, ast.BitXor):
|
||||
return left ^ right
|
||||
elif isinstance(node.op, ast.BitAnd):
|
||||
return left & right
|
||||
elif isinstance(node, ast.UnaryOp):
|
||||
operand = self._eval_const_expr(node.operand, Gen)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
elif isinstance(node.op, ast.UAdd):
|
||||
return +operand
|
||||
elif isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
elif isinstance(node, ast.Name):
|
||||
if node.id in getattr(Gen, '_define_constants', {}):
|
||||
return Gen._define_constants[node.id]
|
||||
if node.id in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[node.id]
|
||||
val = getattr(SymInfo, 'value', None)
|
||||
if isinstance(val, (int, float)):
|
||||
return val
|
||||
if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)):
|
||||
return SymInfo.DefineValue
|
||||
elif isinstance(node, ast.Attribute):
|
||||
module_name = node.value.id if isinstance(node.value, ast.Name) else None
|
||||
attr_name = node.attr
|
||||
if module_name and attr_name:
|
||||
combined_key = f"{module_name}.{attr_name}"
|
||||
if combined_key in getattr(Gen, '_define_constants', {}):
|
||||
val = Gen._define_constants[combined_key]
|
||||
if isinstance(val, (int, float)):
|
||||
return int(val) if isinstance(val, float) and val == int(val) else val
|
||||
for key, SymInfo in self.Trans.SymbolTable.items():
|
||||
if key.endswith(f".{combined_key}") or key == combined_key:
|
||||
if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)):
|
||||
return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue
|
||||
all_dc = getattr(self.Trans, '_all_define_constants', None) or getattr(Gen, '_all_define_constants', {})
|
||||
if combined_key in all_dc:
|
||||
val = all_dc[combined_key]
|
||||
if isinstance(val, (int, float)):
|
||||
return int(val) if isinstance(val, float) and val == int(val) else val
|
||||
if attr_name in all_dc:
|
||||
val = all_dc[attr_name]
|
||||
if isinstance(val, (int, float)):
|
||||
return int(val) if isinstance(val, float) and val == int(val) else val
|
||||
for dc_key, dc_val in all_dc.items():
|
||||
if dc_key == attr_name or dc_key.endswith(f".{attr_name}"):
|
||||
if isinstance(dc_val, (int, float)):
|
||||
return int(dc_val) if isinstance(dc_val, float) and dc_val == int(dc_val) else dc_val
|
||||
if attr_name in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[attr_name]
|
||||
if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)):
|
||||
return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue
|
||||
if attr_name in getattr(Gen, '_define_constants', {}):
|
||||
val = Gen._define_constants[attr_name]
|
||||
if isinstance(val, (int, float)):
|
||||
return int(val) if isinstance(val, float) and val == int(val) else val
|
||||
return None
|
||||
"""计算常量表达式的值(委托到 ConstEvaluator)"""
|
||||
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
|
||||
ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable)
|
||||
return ConstEvaluator.eval_full(node, ctx)
|
||||
|
||||
def _eval_global_count(self, node, Gen):
|
||||
val = self._eval_const_expr(node, Gen)
|
||||
|
||||
@@ -395,74 +395,8 @@ class CTypeInfo:
|
||||
|
||||
@staticmethod
|
||||
def TryEvalConstExpr(node, SymbolTable):
|
||||
if isinstance(node, ast.Constant) and isinstance(node.value, int):
|
||||
return node.value
|
||||
if isinstance(node, ast.BinOp):
|
||||
left = CTypeInfo.TryEvalConstExpr(node.left, SymbolTable)
|
||||
right = CTypeInfo.TryEvalConstExpr(node.right, SymbolTable)
|
||||
if left is None or right is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.Add):
|
||||
return left + right
|
||||
elif isinstance(node.op, ast.Sub):
|
||||
return left - right
|
||||
elif isinstance(node.op, ast.Mult):
|
||||
return left * right
|
||||
elif isinstance(node.op, ast.FloorDiv):
|
||||
return left // right if right != 0 else None
|
||||
elif isinstance(node.op, ast.Mod):
|
||||
return left % right if right != 0 else None
|
||||
elif isinstance(node.op, ast.LShift):
|
||||
return left << right
|
||||
elif isinstance(node.op, ast.RShift):
|
||||
return left >> right
|
||||
elif isinstance(node.op, ast.BitOr):
|
||||
return left | right
|
||||
elif isinstance(node.op, ast.BitAnd):
|
||||
return left & right
|
||||
elif isinstance(node.op, ast.BitXor):
|
||||
return left ^ right
|
||||
elif isinstance(node.op, ast.Pow):
|
||||
return left ** right
|
||||
return None
|
||||
if isinstance(node, ast.UnaryOp):
|
||||
operand = CTypeInfo.TryEvalConstExpr(node.operand, SymbolTable)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
elif isinstance(node.op, ast.UAdd):
|
||||
return +operand
|
||||
elif isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
return None
|
||||
if isinstance(node, ast.Name):
|
||||
if node.id in SymbolTable:
|
||||
info = SymbolTable[node.id]
|
||||
if getattr(info, 'IsDefine', None) and isinstance(getattr(info, 'DefineValue', None), int):
|
||||
return info.DefineValue
|
||||
if isinstance(node, ast.Attribute):
|
||||
parts = []
|
||||
current = node
|
||||
while isinstance(current, ast.Attribute):
|
||||
parts.append(current.attr)
|
||||
current = current.value
|
||||
if isinstance(current, ast.Name):
|
||||
parts.append(current.id)
|
||||
parts.reverse()
|
||||
attr_name = parts[-1]
|
||||
possible_keys = [attr_name, '.'.join(parts)]
|
||||
for key in possible_keys:
|
||||
if key in SymbolTable:
|
||||
info = SymbolTable[key]
|
||||
if getattr(info, 'IsDefine', None) and isinstance(getattr(info, 'DefineValue', None), int):
|
||||
return info.DefineValue
|
||||
if len(parts) >= 2:
|
||||
for mod_key, mod_info in SymbolTable.items():
|
||||
if getattr(mod_info, 'IsDefine', None) and isinstance(getattr(mod_info, 'DefineValue', None), int):
|
||||
if mod_key.endswith('.' + attr_name) or mod_key == attr_name:
|
||||
return mod_info.DefineValue
|
||||
return None
|
||||
from lib.core.ConstEvaluator import ConstEvaluator
|
||||
return ConstEvaluator.eval_with_symtab(node, SymbolTable)
|
||||
|
||||
@classmethod
|
||||
def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo":
|
||||
@@ -1136,10 +1070,6 @@ class CTypeInfo:
|
||||
NewInfo._ts.original_type = NewInfo._ts.original_type.Copy()
|
||||
if NewInfo._ts.array_ptr:
|
||||
NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy()
|
||||
# 实例上的动态属性也需要拷贝(如 IsSigned 等)
|
||||
for key, val in self.__dict__.items():
|
||||
if key not in ('_ts', '_sm'):
|
||||
object.__setattr__(NewInfo, key, val)
|
||||
return NewInfo
|
||||
|
||||
def get(self, key, default=None):
|
||||
|
||||
@@ -40,7 +40,7 @@ class DeleteHandle(BaseHandle):
|
||||
if ClassName:
|
||||
PropKey = f'{ClassName}.{AttrName}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
|
||||
SelfVar = Gen._get_var_ptr('self')
|
||||
if SelfVar:
|
||||
SelfPtr = Gen._load(SelfVar, name="self")
|
||||
@@ -54,7 +54,7 @@ class DeleteHandle(BaseHandle):
|
||||
if ClassName:
|
||||
PropKey = f'{ClassName}.{AttrName}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList:
|
||||
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value)
|
||||
if obj_val:
|
||||
DeleterFunc = Gen._get_function(PropKey + '$del')
|
||||
|
||||
@@ -329,7 +329,7 @@ class ExprHandle(BaseHandle):
|
||||
if VarName not in getattr(Gen, '_define_constants', {}):
|
||||
try:
|
||||
sym_info = self.translator.SymbolTable.get(VarName)
|
||||
if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None:
|
||||
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
|
||||
val = sym_info.DefineValue
|
||||
if isinstance(val, int):
|
||||
# Use VarType hint if available
|
||||
@@ -400,9 +400,9 @@ class ExprHandle(BaseHandle):
|
||||
return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0)
|
||||
if VarName in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[VarName]
|
||||
if getattr(SymInfo, 'IsEnumMember', None) and isinstance(getattr(SymInfo, 'value', None), int):
|
||||
if SymInfo.IsEnumMember and isinstance(SymInfo.value, int):
|
||||
return ir.Constant(ir.IntType(32), SymInfo.value)
|
||||
if getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsFuncPtr', False):
|
||||
if SymInfo.IsFunction or SymInfo.IsFuncPtr:
|
||||
MangledName = Gen._mangle_func_name(VarName)
|
||||
if MangledName in Gen.module.globals:
|
||||
g = Gen.module.globals[MangledName]
|
||||
|
||||
@@ -92,7 +92,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
PossibleKeys.append(key)
|
||||
for lookup_key in PossibleKeys:
|
||||
SymInfo = self.Trans.SymbolTable.get(lookup_key)
|
||||
if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None:
|
||||
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
|
||||
return self._make_define_constant(Gen, SymInfo.DefineValue)
|
||||
# 也检查 _define_constants
|
||||
define_constants = getattr(Gen, '_define_constants', {})
|
||||
@@ -202,7 +202,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
# 检查 property getter
|
||||
PropKey = f'{ClassName}.{Node.attr}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
|
||||
SelfVar = Gen._get_var_ptr('self')
|
||||
if SelfVar:
|
||||
SelfPtr = Gen._load(SelfVar, name="self")
|
||||
@@ -234,16 +234,16 @@ class ExprAttrHandle(BaseHandle):
|
||||
def _handle_attr_enum(self, Node, VarName):
|
||||
"""处理枚举成员访问 (VarName 是枚举类型名)"""
|
||||
SymInfo = self.Trans.SymbolTable.get(VarName)
|
||||
if not SymInfo or not getattr(SymInfo, 'IsEnum', None):
|
||||
if not SymInfo or not SymInfo.IsEnum:
|
||||
return None
|
||||
if Node.attr in self.Trans.SymbolTable:
|
||||
MemberInfo = self.Trans.SymbolTable[Node.attr]
|
||||
if getattr(MemberInfo, 'IsEnumMember', None) and getattr(MemberInfo, 'EnumName', None) == VarName:
|
||||
if isinstance(getattr(MemberInfo, 'value', None), int):
|
||||
if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName:
|
||||
if isinstance(MemberInfo.value, int):
|
||||
return ir.Constant(ir.IntType(32), MemberInfo.value)
|
||||
for key, info in self.Trans.SymbolTable.items():
|
||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == VarName and key == Node.attr:
|
||||
if isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and info.EnumName == VarName and key == Node.attr:
|
||||
if isinstance(info.value, int):
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
return None
|
||||
|
||||
@@ -285,7 +285,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
# 检查 property getter
|
||||
PropKey = f'{ClassName}.{AttrName}'
|
||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
||||
if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
|
||||
if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList:
|
||||
ObjVal = self.HandleExprLlvm(Node.value)
|
||||
GetterFunc = Gen._get_function(PropKey)
|
||||
if GetterFunc and ObjVal:
|
||||
@@ -297,7 +297,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
TypeInfo = self.Trans.SymbolTable.get(ClassName)
|
||||
IsUnion = TypeInfo.IsUnion if TypeInfo else False
|
||||
IsCenum = TypeInfo.IsEnum if TypeInfo else False
|
||||
IsRenum = getattr(TypeInfo, 'IsRenum', False) if TypeInfo else False
|
||||
IsRenum = TypeInfo.IsRenum if TypeInfo else False
|
||||
|
||||
# REnum 处理
|
||||
if IsRenum:
|
||||
@@ -322,12 +322,12 @@ class ExprAttrHandle(BaseHandle):
|
||||
for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"):
|
||||
if qname in self.Trans.SymbolTable:
|
||||
info = self.Trans.SymbolTable[qname]
|
||||
if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and isinstance(info.value, int):
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
for key, info in self.Trans.SymbolTable.items():
|
||||
if key == AttrName:
|
||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == ClassName:
|
||||
if isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and info.EnumName == ClassName:
|
||||
if isinstance(info.value, int):
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
break
|
||||
|
||||
@@ -1062,7 +1062,7 @@ class ExprAttrHandle(BaseHandle):
|
||||
possible_keys.append(key)
|
||||
for lookup_key in possible_keys:
|
||||
SymInfo = self.Trans.SymbolTable.get(lookup_key)
|
||||
if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None:
|
||||
if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None:
|
||||
val = SymInfo.DefineValue
|
||||
if isinstance(val, int):
|
||||
if val > 0x7FFFFFFF or val < -0x80000000:
|
||||
@@ -1085,21 +1085,21 @@ class ExprAttrHandle(BaseHandle):
|
||||
for enum_key in enum_keys:
|
||||
if enum_key in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[enum_key]
|
||||
if getattr(SymInfo, 'IsEnum', None):
|
||||
if SymInfo.IsEnum:
|
||||
for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"):
|
||||
if qname in self.Trans.SymbolTable:
|
||||
info = self.Trans.SymbolTable[qname]
|
||||
if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and isinstance(info.value, int):
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
for key, info in self.Trans.SymbolTable.items():
|
||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_key and key == member_name:
|
||||
if isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and info.EnumName == enum_key and key == member_name:
|
||||
if isinstance(info.value, int):
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
for key, info in self.Trans.SymbolTable.items():
|
||||
if getattr(info, 'IsEnumMember', None) and key == member_name:
|
||||
if isinstance(getattr(info, 'value', None), int):
|
||||
if info.IsEnumMember and key == member_name:
|
||||
if isinstance(info.value, int):
|
||||
for enum_key in enum_keys:
|
||||
if getattr(info, 'EnumName', None) == enum_key:
|
||||
if info.EnumName == enum_key:
|
||||
return ir.Constant(ir.IntType(32), info.value)
|
||||
return None
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ class ExprBuiltinHandle(BaseHandle):
|
||||
LastPart = arg.attr
|
||||
if LastPart in self.Trans.SymbolTable:
|
||||
AttrInfo = self.Trans.SymbolTable[LastPart]
|
||||
if getattr(AttrInfo, 'IsEnumMember', None) and getattr(AttrInfo, 'EnumName', None):
|
||||
if AttrInfo.IsEnumMember and AttrInfo.EnumName:
|
||||
enum_type_name = AttrInfo.EnumName
|
||||
elif isinstance(arg.value, ast.Attribute):
|
||||
attr_path = _get_attr_path(arg)
|
||||
@@ -554,14 +554,14 @@ class ExprBuiltinHandle(BaseHandle):
|
||||
for qname in (qualified_name_dot, qualified_name_under):
|
||||
if qname in self.Trans.SymbolTable:
|
||||
info = self.Trans.SymbolTable[qname]
|
||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_class_name:
|
||||
if info.IsEnumMember and info.EnumName == enum_class_name:
|
||||
enum_member_found = info
|
||||
break
|
||||
if not enum_member_found:
|
||||
for key in self.Trans.SymbolTable:
|
||||
if key == LastPart:
|
||||
info = self.Trans.SymbolTable[key]
|
||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_class_name:
|
||||
if info.IsEnumMember and info.EnumName == enum_class_name:
|
||||
enum_member_found = info
|
||||
break
|
||||
if enum_member_found:
|
||||
|
||||
@@ -435,7 +435,7 @@ class ExprCallHandle(BaseHandle):
|
||||
if first_part in aliases:
|
||||
ModulePath = aliases[first_part] + ModulePath[len(first_part):]
|
||||
is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map
|
||||
is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[Node.func.value.id], 'IsStruct', False)))
|
||||
is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and self.Trans.SymbolTable[Node.func.value.id].IsStruct))
|
||||
if is_instance_var and not is_class_name:
|
||||
return self._HandleMethodCallLlvm(Node)
|
||||
FuncAttr = Node.func.attr
|
||||
@@ -454,11 +454,11 @@ class ExprCallHandle(BaseHandle):
|
||||
result = self._HandleClassNewLlvm(Node, FuncAttr)
|
||||
if result is not None:
|
||||
return result
|
||||
if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None):
|
||||
if SymInfo.IsEnumMember and SymInfo.EnumName:
|
||||
EnumName = SymInfo.EnumName
|
||||
if EnumName in self.Trans.SymbolTable:
|
||||
EnumInfo = self.Trans.SymbolTable[EnumName]
|
||||
if getattr(EnumInfo, 'IsRenum', False):
|
||||
if EnumInfo.IsRenum:
|
||||
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
|
||||
if result is not None:
|
||||
return result
|
||||
@@ -480,9 +480,9 @@ class ExprCallHandle(BaseHandle):
|
||||
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
||||
if FullAttrKey in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[FullAttrKey]
|
||||
if getattr(SymInfo, 'IsTypedef', False):
|
||||
if SymInfo.IsTypedef:
|
||||
return ir.Constant(ir.IntType(32), 0)
|
||||
if getattr(SymInfo, 'IsStruct', False):
|
||||
if SymInfo.IsStruct:
|
||||
if FuncAttr not in Gen.structs:
|
||||
self._ensure_struct_declared(FuncAttr)
|
||||
if FuncAttr in Gen.structs:
|
||||
@@ -533,7 +533,7 @@ class ExprCallHandle(BaseHandle):
|
||||
raise Exception(f"Undefined method: 't.{FuncAttr}'")
|
||||
if isinstance(Node.func.value, ast.Attribute):
|
||||
inner_attr = Node.func.value.attr
|
||||
if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[inner_attr], 'IsStruct', False)):
|
||||
if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and self.Trans.SymbolTable[inner_attr].IsStruct):
|
||||
static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr)
|
||||
if static_result is not None:
|
||||
return static_result
|
||||
@@ -569,11 +569,11 @@ class ExprCallHandle(BaseHandle):
|
||||
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}:
|
||||
# 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明
|
||||
_attr_sym = self.Trans.SymbolTable.get(FuncAttr)
|
||||
_is_func_or_var = _attr_sym and (getattr(_attr_sym, 'IsFunction', False) or getattr(_attr_sym, 'IsVariable', False))
|
||||
_is_func_or_var = _attr_sym and (_attr_sym.IsFunction or _attr_sym.IsVariable)
|
||||
if not _is_func_or_var and ModulePath:
|
||||
_full_key = f"{ModulePath}.{FuncAttr}"
|
||||
_full_sym = self.Trans.SymbolTable.get(_full_key)
|
||||
if _full_sym and (getattr(_full_sym, 'IsFunction', False) or getattr(_full_sym, 'IsVariable', False)):
|
||||
if _full_sym and (_full_sym.IsFunction or _full_sym.IsVariable):
|
||||
_is_func_or_var = True
|
||||
# 优先检查 FuncAttr 是否为 struct/类构造器
|
||||
if not _is_func_or_var and FuncAttr not in Gen.structs:
|
||||
@@ -587,7 +587,7 @@ class ExprCallHandle(BaseHandle):
|
||||
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
||||
if FullAttrKey in self.Trans.SymbolTable:
|
||||
FullSymInfo = self.Trans.SymbolTable[FullAttrKey]
|
||||
if getattr(FullSymInfo, 'IsStruct', False) or getattr(FullSymInfo, 'IsCpythonObject', False):
|
||||
if FullSymInfo.IsStruct or FullSymInfo.IsCpythonObject:
|
||||
if FuncAttr not in Gen.structs:
|
||||
self._ensure_struct_declared(FuncAttr)
|
||||
if FuncAttr in Gen.structs:
|
||||
@@ -649,7 +649,7 @@ class ExprCallHandle(BaseHandle):
|
||||
Gen = self.Trans.LlvmGen
|
||||
# 如果名称是函数或变量,不应创建 struct
|
||||
SymInfo = self.Trans.SymbolTable.get(class_name)
|
||||
if SymInfo and (getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsVariable', False)):
|
||||
if SymInfo and (SymInfo.IsFunction or SymInfo.IsVariable):
|
||||
return
|
||||
if class_name in Gen.structs:
|
||||
existing = Gen.structs[class_name]
|
||||
@@ -721,16 +721,16 @@ class ExprCallHandle(BaseHandle):
|
||||
SymKey = f'{ClassName}.{MethodName}'
|
||||
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName)
|
||||
if SymInfo and SymInfo.IsFunction:
|
||||
ret_type_info = getattr(SymInfo, 'FuncPtrReturn', None)
|
||||
ret_type_info = SymInfo.FuncPtrReturn
|
||||
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||
ret_type = ret_type_info.ToLLVM(Gen)
|
||||
else:
|
||||
ret_type = Gen._CType2LLVM('i32', False)
|
||||
param_type_infos = [pt for _, pt in (getattr(SymInfo, 'FuncPtrParams', None) or [])]
|
||||
param_type_infos = [pt for _, pt in (SymInfo.FuncPtrParams or [])]
|
||||
if isinstance(ret_type, ir.VoidType):
|
||||
ret_type = ir.IntType(32)
|
||||
llvm_param_types = []
|
||||
is_static = hasattr(SymInfo, 'MetaList') and FuncMeta.STATIC_METHOD in SymInfo.MetaList
|
||||
is_static = FuncMeta.STATIC_METHOD in SymInfo.MetaList
|
||||
if ClassName in Gen.structs and not is_static:
|
||||
llvm_param_types.append(ir.PointerType(Gen.structs[ClassName]))
|
||||
for pt in param_type_infos:
|
||||
@@ -762,8 +762,8 @@ class ExprCallHandle(BaseHandle):
|
||||
CallArgs = []
|
||||
SymKey = f'{ClassName}.{MethodName}'
|
||||
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName)
|
||||
is_static_call = SymInfo is not None and hasattr(SymInfo, 'MetaList') and FuncMeta.STATIC_METHOD in SymInfo.MetaList
|
||||
is_classmethod_call = SymInfo is not None and hasattr(SymInfo, 'MetaList') and FuncMeta.CLASS_METHOD in SymInfo.MetaList
|
||||
is_static_call = SymInfo is not None and FuncMeta.STATIC_METHOD in SymInfo.MetaList
|
||||
is_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList
|
||||
# @classmethod: 在参数列表前插入 cls(栈上分配的类实例指针)
|
||||
if is_classmethod_call and ClassName in Gen.structs:
|
||||
ClsPtr = Gen._alloca(Gen.structs[ClassName], name=f"cls_{ClassName}")
|
||||
@@ -1230,13 +1230,13 @@ class ExprCallHandle(BaseHandle):
|
||||
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
|
||||
sym_key = f'{ModulePath}.{func_name}'
|
||||
sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(func_name)
|
||||
is_inline = sym_info and (getattr(sym_info, 'IsInline', False) or isinstance(getattr(sym_info, 'Storage', None), t.CInline))
|
||||
if is_inline and getattr(sym_info, 'InlineBody', None):
|
||||
is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline))
|
||||
if is_inline and sym_info.InlineBody:
|
||||
self._HandleInlineExpandLlvm(Node, sym_info)
|
||||
return ir.Constant(ir.IntType(32), 1)
|
||||
sym_info_exact = self.Trans.SymbolTable.get(sym_key)
|
||||
if sym_info_exact:
|
||||
exact_params = getattr(sym_info_exact, 'FuncPtrParams', [])
|
||||
exact_params = sym_info_exact.FuncPtrParams
|
||||
exact_param_names = [pn for pn, _ in exact_params]
|
||||
if exact_param_names:
|
||||
provided = len(Node.args)
|
||||
@@ -1280,15 +1280,15 @@ class ExprCallHandle(BaseHandle):
|
||||
if not sym_info:
|
||||
sym_info = self.Trans.SymbolTable.get(func_name)
|
||||
if sym_info:
|
||||
is_func = getattr(sym_info, 'IsFunction', False)
|
||||
sym_is_variadic = getattr(sym_info, 'IsVariadic', False)
|
||||
is_func = sym_info.IsFunction
|
||||
sym_is_variadic = sym_info.IsVariadic
|
||||
if is_func:
|
||||
ret_type_info = getattr(sym_info, 'FuncPtrReturn', None)
|
||||
ret_type_info = sym_info.FuncPtrReturn
|
||||
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||
ret_type = ret_type_info.ToLLVM(Gen)
|
||||
else:
|
||||
ret_type = Gen._CType2LLVM('i32', False)
|
||||
sym_params = getattr(sym_info, 'FuncPtrParams', [])
|
||||
sym_params = sym_info.FuncPtrParams
|
||||
param_type_infos = [pt for _, pt in sym_params]
|
||||
if isinstance(ret_type, ir.VoidType):
|
||||
ret_type = ir.IntType(32)
|
||||
@@ -1411,15 +1411,15 @@ class ExprCallHandle(BaseHandle):
|
||||
if not sym_info:
|
||||
sym_info = self.Trans.SymbolTable.get(func_name)
|
||||
if sym_info:
|
||||
is_func = getattr(sym_info, 'IsFunction', False)
|
||||
sym_is_variadic = getattr(sym_info, 'IsVariadic', False)
|
||||
is_func = sym_info.IsFunction
|
||||
sym_is_variadic = sym_info.IsVariadic
|
||||
if is_func:
|
||||
ret_type_info = getattr(sym_info, 'FuncPtrReturn', None)
|
||||
ret_type_info = sym_info.FuncPtrReturn
|
||||
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||
ret_type = ret_type_info.ToLLVM(Gen)
|
||||
else:
|
||||
ret_type = Gen._CType2LLVM('i32', False)
|
||||
param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])]
|
||||
param_type_infos = [pt for _, pt in sym_info.FuncPtrParams]
|
||||
if isinstance(ret_type, ir.VoidType):
|
||||
ret_type = ir.IntType(32)
|
||||
llvm_param_types = []
|
||||
@@ -1830,7 +1830,7 @@ class ExprCallHandle(BaseHandle):
|
||||
if ClassName:
|
||||
SymKey = f'{ClassName}.{MethodName}'
|
||||
SymInfo = self.Trans.SymbolTable.get(SymKey)
|
||||
if SymInfo and hasattr(SymInfo, 'MetaList'):
|
||||
if SymInfo and SymInfo.MetaList:
|
||||
if FuncMeta.STATIC_METHOD in SymInfo.MetaList:
|
||||
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
|
||||
if FuncMeta.CLASS_METHOD in SymInfo.MetaList:
|
||||
|
||||
@@ -73,7 +73,7 @@ class IfHandle(BaseHandle):
|
||||
return True
|
||||
if name in self.Trans.SymbolTable:
|
||||
info = self.Trans.SymbolTable[name]
|
||||
if getattr(info, 'IsDefine', False):
|
||||
if info.IsDefine:
|
||||
return True
|
||||
platform_macros = self._get_platform_macros()
|
||||
return name in platform_macros
|
||||
@@ -86,8 +86,8 @@ class IfHandle(BaseHandle):
|
||||
return val
|
||||
if name in self.Trans.SymbolTable:
|
||||
info = self.Trans.SymbolTable[name]
|
||||
if getattr(info, 'IsDefine', False):
|
||||
val = getattr(info, 'DefineValue', 0)
|
||||
if info.IsDefine:
|
||||
val = info.DefineValue
|
||||
if isinstance(val, (int, float)):
|
||||
return val
|
||||
platform_macros = self._get_platform_macros()
|
||||
@@ -129,118 +129,21 @@ class IfHandle(BaseHandle):
|
||||
return macros
|
||||
|
||||
def _eval_const_expr(self, node):
|
||||
if isinstance(node, ast.Constant):
|
||||
val = node.value
|
||||
if isinstance(val, bool):
|
||||
return 1 if val else 0
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return 1 if val != 0.0 else 0
|
||||
return 0
|
||||
if isinstance(node, ast.Name):
|
||||
name = node.id
|
||||
val = self._get_macro_value(name)
|
||||
if val is not None:
|
||||
return val
|
||||
return None
|
||||
if isinstance(node, ast.Attribute):
|
||||
full_key = self._get_attr_full_name(node)
|
||||
if full_key:
|
||||
val = self._get_macro_value(full_key)
|
||||
if val is not None:
|
||||
return val
|
||||
short_name = full_key.split('.')[-1] if '.' in full_key else full_key
|
||||
val = self._get_macro_value(short_name)
|
||||
if val is not None:
|
||||
return val
|
||||
return None
|
||||
if isinstance(node, ast.UnaryOp):
|
||||
operand = self._eval_const_expr(node.operand)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.Not):
|
||||
return 1 if not operand else 0
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
if isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
return None
|
||||
if isinstance(node, ast.BinOp):
|
||||
left = self._eval_const_expr(node.left)
|
||||
right = self._eval_const_expr(node.right)
|
||||
if left is None or right is None:
|
||||
return None
|
||||
try:
|
||||
if isinstance(node.op, ast.Add):
|
||||
return left + right
|
||||
elif isinstance(node.op, ast.Sub):
|
||||
return left - right
|
||||
elif isinstance(node.op, ast.Mult):
|
||||
return left * right
|
||||
elif isinstance(node.op, ast.FloorDiv):
|
||||
return left // right if right != 0 else 0
|
||||
elif isinstance(node.op, ast.Mod):
|
||||
return left % right if right != 0 else 0
|
||||
elif isinstance(node.op, ast.LShift):
|
||||
return left << right
|
||||
elif isinstance(node.op, ast.RShift):
|
||||
return left >> right
|
||||
elif isinstance(node.op, ast.BitOr):
|
||||
return left | right
|
||||
elif isinstance(node.op, ast.BitAnd):
|
||||
return left & right
|
||||
elif isinstance(node.op, ast.BitXor):
|
||||
return left ^ right
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
if isinstance(node, ast.BoolOp):
|
||||
if isinstance(node.op, ast.And):
|
||||
for val in node.values:
|
||||
result = self._eval_const_expr(val)
|
||||
if result is None:
|
||||
return None
|
||||
if not result:
|
||||
return 0
|
||||
return 1
|
||||
elif isinstance(node.op, ast.Or):
|
||||
for val in node.values:
|
||||
result = self._eval_const_expr(val)
|
||||
if result is None:
|
||||
return None
|
||||
if result:
|
||||
return 1
|
||||
return 0
|
||||
if isinstance(node, ast.Compare):
|
||||
left = self._eval_const_expr(node.left)
|
||||
if left is None:
|
||||
return None
|
||||
for op, comparator in zip(node.ops, node.comparators):
|
||||
right = self._eval_const_expr(comparator)
|
||||
if right is None:
|
||||
return None
|
||||
if isinstance(op, ast.Eq):
|
||||
result = left == right
|
||||
elif isinstance(op, ast.NotEq):
|
||||
result = left != right
|
||||
elif isinstance(op, ast.Lt):
|
||||
result = left < right
|
||||
elif isinstance(op, ast.LtE):
|
||||
result = left <= right
|
||||
elif isinstance(op, ast.Gt):
|
||||
result = left > right
|
||||
elif isinstance(op, ast.GtE):
|
||||
result = left >= right
|
||||
else:
|
||||
return None
|
||||
if not result:
|
||||
return 0
|
||||
return 1
|
||||
if isinstance(node, ast.Call):
|
||||
if self._is_cif_call(node):
|
||||
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
|
||||
Gen = self.Trans.LlvmGen
|
||||
ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable)
|
||||
result = ConstEvaluator.eval_full(node, ctx)
|
||||
if result is None:
|
||||
# 保留 CIf 嵌套调用处理(HandlesIf 特有逻辑)
|
||||
if isinstance(node, ast.Call) and self._is_cif_call(node):
|
||||
return self._evaluate_cif_condition(node)
|
||||
return None
|
||||
return None
|
||||
# HandlesIf 需要 bool/float → int 转换(#if 条件编译语义)
|
||||
if isinstance(result, bool):
|
||||
return 1 if result else 0
|
||||
if isinstance(result, float):
|
||||
return 1 if result != 0.0 else 0
|
||||
return result
|
||||
|
||||
def _HandleIfLlvm(self, Node):
|
||||
Gen = self.Trans.LlvmGen
|
||||
|
||||
@@ -74,14 +74,14 @@ class ImportHandle(BaseHandle):
|
||||
if not asname or asname == name:
|
||||
# Check if this name is a CDefine constant in SymbolTable
|
||||
sym_info = self.Trans.SymbolTable.get(name)
|
||||
if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None:
|
||||
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
|
||||
define_constants = vars(Gen).setdefault('_define_constants', {})
|
||||
if name not in define_constants:
|
||||
define_constants[name] = sym_info.DefineValue
|
||||
# Also check with module prefix
|
||||
for prefix_key in [f"{module}.{name}", name]:
|
||||
sym_info2 = self.Trans.SymbolTable.get(prefix_key)
|
||||
if sym_info2 and getattr(sym_info2, 'IsDefine', None) and getattr(sym_info2, 'DefineValue', None) is not None:
|
||||
if sym_info2 and sym_info2.IsDefine and sym_info2.DefineValue is not None:
|
||||
define_constants = vars(Gen).setdefault('_define_constants', {})
|
||||
if name not in define_constants:
|
||||
define_constants[name] = sym_info2.DefineValue
|
||||
@@ -893,7 +893,7 @@ class ImportHandle(BaseHandle):
|
||||
elif isinstance(value_node, ast.Name):
|
||||
if value_node.id in getattr(self.Trans, 'SymbolTable', {}):
|
||||
info = self.Trans.SymbolTable[value_node.id]
|
||||
if getattr(info, 'IsDefine', None) and getattr(info, 'DefineValue', None) is not None:
|
||||
if info.IsDefine and info.DefineValue is not None:
|
||||
return info.DefineValue
|
||||
elif isinstance(value_node, ast.Call):
|
||||
if isinstance(value_node.func, ast.Attribute):
|
||||
@@ -1020,7 +1020,7 @@ class ImportHandle(BaseHandle):
|
||||
ParamTypes = []
|
||||
is_method = is_class_method or '.__' in FuncName
|
||||
class_name_for_method = FuncName.split('.')[0] if '.' in FuncName else None
|
||||
class_is_cpython = class_name_for_method and class_name_for_method in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[class_name_for_method], 'IsCpythonObject', False)
|
||||
class_is_cpython = class_name_for_method and class_name_for_method in self.Trans.SymbolTable and self.Trans.SymbolTable[class_name_for_method].IsCpythonObject
|
||||
for i, Arg in enumerate(Node.args.args):
|
||||
if i == 0 and is_method:
|
||||
# self parameter of a method should always be a pointer to the struct
|
||||
|
||||
@@ -21,7 +21,7 @@ class MatchHandle(BaseHandle):
|
||||
VarName = Node.subject.id
|
||||
if VarName in self.Trans.SymbolTable:
|
||||
TypeInfo = self.Trans.SymbolTable[VarName]
|
||||
if getattr(TypeInfo, 'IsRenum', False):
|
||||
if TypeInfo.IsRenum:
|
||||
IsRenumMatch = True
|
||||
RenumName = TypeInfo.Name
|
||||
SubjectPtr = Gen._loadVar(VarName)
|
||||
@@ -37,11 +37,11 @@ class MatchHandle(BaseHandle):
|
||||
VariantName = cls_node.attr
|
||||
if VariantName and VariantName in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[VariantName]
|
||||
if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None):
|
||||
if SymInfo.IsEnumMember and SymInfo.EnumName:
|
||||
EnumName = SymInfo.EnumName
|
||||
if EnumName in self.Trans.SymbolTable:
|
||||
EnumInfo = self.Trans.SymbolTable[EnumName]
|
||||
if getattr(EnumInfo, 'IsRenum', False):
|
||||
if EnumInfo.IsRenum:
|
||||
IsRenumMatch = True
|
||||
RenumName = EnumName
|
||||
if SubjectPtr is None:
|
||||
@@ -209,7 +209,7 @@ class MatchHandle(BaseHandle):
|
||||
TagValue = None
|
||||
if VariantName in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[VariantName]
|
||||
if getattr(SymInfo, 'IsEnumMember', False):
|
||||
if SymInfo.IsEnumMember:
|
||||
TagValue = SymInfo.value
|
||||
if TagValue is not None:
|
||||
CaseValues.append(ir.Constant(ir.IntType(32), TagValue))
|
||||
|
||||
@@ -120,8 +120,8 @@ class HandlesTypeMerge(BaseHandle):
|
||||
# 也尝试在符号表中查找模块别名
|
||||
if ModulePath in self.Trans.SymbolTable:
|
||||
entry = self.Trans.SymbolTable[ModulePath]
|
||||
if isinstance(entry, CTypeInfo) and getattr(entry, 'IsModuleAlias', False):
|
||||
resolved = getattr(entry, 'ResolvedModule', None)
|
||||
if isinstance(entry, CTypeInfo) and entry.IsModuleAlias:
|
||||
resolved = entry.ResolvedModule
|
||||
if resolved:
|
||||
ModulePath = resolved
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class WithHandle(BaseHandle):
|
||||
if ClassName and ClassName not in Gen.structs:
|
||||
if ClassName in self.Trans.SymbolTable:
|
||||
SymInfo = self.Trans.SymbolTable[ClassName]
|
||||
if getattr(SymInfo, 'IsStruct', False) or getattr(SymInfo, 'IsRenum', False):
|
||||
if SymInfo.IsStruct or SymInfo.IsRenum:
|
||||
pass
|
||||
else:
|
||||
ClassName = None
|
||||
|
||||
@@ -173,28 +173,28 @@ class BaseGenMixin:
|
||||
return ir.IntType(8)
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable:
|
||||
Entry = self.SymbolTable[clean_name]
|
||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
||||
if Entry.IsTypedef:
|
||||
resolved_str = self._resolve_typedef(clean_name)
|
||||
if resolved_str != clean_name:
|
||||
return self._type_str_to_llvm(resolved_str)
|
||||
if hasattr(Entry, 'BaseType') and Entry.BaseType:
|
||||
if Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0:
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0:
|
||||
resolved = self._resolve_ctype_to_str(Entry)
|
||||
if resolved:
|
||||
return self._type_str_to_llvm(resolved)
|
||||
if hasattr(Entry, 'IsRenum') and Entry.IsRenum:
|
||||
if Entry.IsRenum:
|
||||
if clean_name in self.structs:
|
||||
return self.structs[clean_name]
|
||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
||||
if Entry.IsEnum:
|
||||
return ir.IntType(32)
|
||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
||||
if Entry.IsExceptionClass:
|
||||
return ir.IntType(32)
|
||||
if hasattr(Entry, 'IsFunction') and Entry.IsFunction:
|
||||
if Entry.IsFunction:
|
||||
return ir.PointerType(ir.IntType(8))
|
||||
if hasattr(Entry, 'IsVariable') and Entry.IsVariable:
|
||||
if Entry.IsVariable:
|
||||
return ir.PointerType(ir.IntType(8))
|
||||
if hasattr(Entry, 'BaseType'):
|
||||
if Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
|
||||
return ir.IntType(32)
|
||||
@@ -237,17 +237,17 @@ class BaseGenMixin:
|
||||
# 2. 再查 SymbolTable(用户定义的 typedef)
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable:
|
||||
Entry = self.SymbolTable[name]
|
||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
||||
if hasattr(Entry, 'BaseType') and Entry.BaseType:
|
||||
if Entry.IsTypedef:
|
||||
if Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) and getattr(Entry, 'PtrCount', 0) == 0:
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) and Entry.PtrCount == 0:
|
||||
llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType)
|
||||
if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
|
||||
return int(llvm_str[1:])
|
||||
if hasattr(Entry, 'OriginalType') and Entry.OriginalType:
|
||||
if Entry.OriginalType:
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo
|
||||
if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType:
|
||||
if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and getattr(Entry.OriginalType, 'PtrCount', 0) == 0:
|
||||
if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and Entry.OriginalType.PtrCount == 0:
|
||||
llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType)
|
||||
if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
|
||||
return int(llvm_str[1:])
|
||||
|
||||
@@ -207,13 +207,13 @@ class StructGenMixin:
|
||||
is_packed = ClassName in self.class_packed
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
||||
Entry = self.SymbolTable[ClassName]
|
||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
||||
if Entry.IsExceptionClass:
|
||||
continue
|
||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
||||
if not getattr(Entry, 'IsRenum', False):
|
||||
if Entry.IsEnum:
|
||||
if not Entry.IsRenum:
|
||||
continue
|
||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
||||
if hasattr(Entry, 'BaseType') and Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
|
||||
if Entry.IsTypedef:
|
||||
if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
|
||||
import lib.includes.t as _t
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)):
|
||||
continue
|
||||
@@ -304,10 +304,10 @@ class StructGenMixin:
|
||||
for ClassName in all_classes:
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
||||
Entry = self.SymbolTable[ClassName]
|
||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
||||
if Entry.IsExceptionClass:
|
||||
continue
|
||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
||||
if not getattr(Entry, 'IsRenum', False):
|
||||
if Entry.IsEnum:
|
||||
if not Entry.IsRenum:
|
||||
continue
|
||||
existing_st = self.structs.get(ClassName)
|
||||
if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0:
|
||||
|
||||
@@ -137,7 +137,7 @@ class TypeConvertMixin:
|
||||
|
||||
if isinstance(BaseType, _t.CDefine):
|
||||
# Use 64-bit type if the define value exceeds 32-bit range
|
||||
if type_info and hasattr(type_info, 'DefineValue') and isinstance(type_info.DefineValue, int):
|
||||
if type_info and isinstance(type_info.DefineValue, int):
|
||||
if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF:
|
||||
return ir.IntType(64)
|
||||
return ir.IntType(32)
|
||||
@@ -180,8 +180,8 @@ class TypeConvertMixin:
|
||||
if OriginalType:
|
||||
current = OriginalType
|
||||
continue
|
||||
elif hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
||||
if hasattr(Entry, 'OriginalType') and Entry.OriginalType:
|
||||
elif Entry.IsTypedef:
|
||||
if Entry.OriginalType:
|
||||
if isinstance(Entry.OriginalType, _CTypeInfo):
|
||||
if Entry.OriginalType.IsFuncPtr:
|
||||
return 'Callable'
|
||||
@@ -189,9 +189,9 @@ class TypeConvertMixin:
|
||||
elif isinstance(Entry.OriginalType, str):
|
||||
current = Entry.OriginalType
|
||||
continue
|
||||
if hasattr(Entry, 'BaseType') and Entry.BaseType:
|
||||
if Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0:
|
||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0:
|
||||
resolved = self._resolve_ctype_to_str(Entry)
|
||||
if resolved and resolved != current:
|
||||
current = resolved
|
||||
@@ -396,24 +396,24 @@ class TypeConvertMixin:
|
||||
return basic_stripped
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable:
|
||||
_Entry = self.SymbolTable[type_str]
|
||||
if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef:
|
||||
if _Entry.IsTypedef:
|
||||
resolved_str = self._resolve_typedef(type_str)
|
||||
if resolved_str != type_str:
|
||||
return self._type_str_to_llvm(resolved_str, IsPtr)
|
||||
if hasattr(_Entry, 'BaseType') and _Entry.BaseType:
|
||||
if _Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0:
|
||||
if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0:
|
||||
resolved = self._resolve_ctype_to_str(_Entry)
|
||||
if resolved:
|
||||
return self._type_str_to_llvm(resolved, IsPtr)
|
||||
if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum:
|
||||
if _Entry.IsRenum:
|
||||
if type_str in self.structs:
|
||||
return self.structs[type_str]
|
||||
if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum:
|
||||
if _Entry.IsEnum:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass:
|
||||
if _Entry.IsExceptionClass:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
if hasattr(_Entry, 'BaseType'):
|
||||
if _Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
@@ -431,24 +431,24 @@ class TypeConvertMixin:
|
||||
return basic_last
|
||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable:
|
||||
_Entry = self.SymbolTable[LastPart]
|
||||
if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef:
|
||||
if _Entry.IsTypedef:
|
||||
resolved_str = self._resolve_typedef(LastPart)
|
||||
if resolved_str != LastPart:
|
||||
return self._type_str_to_llvm(resolved_str, IsPtr)
|
||||
if hasattr(_Entry, 'BaseType') and _Entry.BaseType:
|
||||
if _Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0:
|
||||
if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0:
|
||||
resolved = self._resolve_ctype_to_str(_Entry)
|
||||
if resolved:
|
||||
return self._type_str_to_llvm(resolved, IsPtr)
|
||||
if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum:
|
||||
if _Entry.IsRenum:
|
||||
if LastPart in self.structs:
|
||||
return self.structs[LastPart]
|
||||
if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum:
|
||||
if _Entry.IsEnum:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass:
|
||||
if _Entry.IsExceptionClass:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
if hasattr(_Entry, 'BaseType'):
|
||||
if _Entry.BaseType:
|
||||
from lib.includes import t as _t
|
||||
if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
|
||||
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||
|
||||
79
lib/core/SymbolData.py
Normal file
79
lib/core/SymbolData.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""符号表处理的数据结构:四阶段管线中传递的中间数据"""
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
@dataclass
|
||||
class ClassSymbolData:
|
||||
"""从 AST 提取的类符号数据"""
|
||||
name: str
|
||||
type_kind: str # 'struct', 'union', 'enum', 'exception'
|
||||
lineno: int
|
||||
members: Dict[str, Any]
|
||||
is_cpython_object: bool = False
|
||||
is_packed: bool = False
|
||||
enum_members: List[Tuple[str, int, int]] = field(default_factory=list) # (name, value, lineno)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TypedefSymbolData:
|
||||
"""Typedef 符号数据(含原始注解和解析结果)"""
|
||||
name: str
|
||||
lineno: int
|
||||
# 原始注解数据(由 Extractor 设置,Resolver 使用)
|
||||
annotation: Any = None
|
||||
value: Any = None
|
||||
has_cdefine: bool = False
|
||||
has_postdef: bool = False
|
||||
has_ctypedef: bool = False
|
||||
# 解析结果(由 Resolver 设置,Inserter 使用)
|
||||
original_type_kind: Optional[str] = None
|
||||
original_class: Any = None
|
||||
members: Optional[Dict] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class FuncSymbolData:
|
||||
"""函数符号数据(含原始注解和解析结果)"""
|
||||
name: str
|
||||
lineno: int
|
||||
# 原始数据(由 Extractor 设置)
|
||||
returns_node: Any = None
|
||||
params: List = field(default_factory=list) # [(name, annotation_node), ...]
|
||||
is_variadic: bool = False
|
||||
is_inline: bool = False
|
||||
# 解析结果(由 Resolver 设置)
|
||||
ret_type: Any = None
|
||||
param_types: List = field(default_factory=list) # [str, ...]
|
||||
|
||||
|
||||
@dataclass
|
||||
class DefineSymbolData:
|
||||
"""Define 符号数据(含原始值和解析结果)"""
|
||||
name: str
|
||||
lineno: int
|
||||
# 原始数据(由 Extractor 设置)
|
||||
value_node: Any = None
|
||||
# 解析结果(由 Resolver 设置)
|
||||
value: Any = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class AnonymousTypeData:
|
||||
"""匿名类型数据"""
|
||||
name: str
|
||||
is_union: bool
|
||||
members: Dict[str, Any]
|
||||
lineno: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class ModuleSymbols:
|
||||
"""从模块提取的完整符号数据,在四阶段管线中传递"""
|
||||
file_path: str
|
||||
classes: List[ClassSymbolData] = field(default_factory=list)
|
||||
typedefs: List[TypedefSymbolData] = field(default_factory=list)
|
||||
functions: List[FuncSymbolData] = field(default_factory=list)
|
||||
defines: List[DefineSymbolData] = field(default_factory=list)
|
||||
anonymous_types: Dict[str, AnonymousTypeData] = field(default_factory=dict)
|
||||
237
lib/core/SymbolExtractor.py
Normal file
237
lib/core/SymbolExtractor.py
Normal file
@@ -0,0 +1,237 @@
|
||||
"""Pass 1: ASTSymbolExtractor — 从 AST 提取原始符号信息"""
|
||||
from __future__ import annotations
|
||||
import ast
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.SymbolTable import SymbolTable
|
||||
|
||||
from lib.core.SymbolData import (
|
||||
ModuleSymbols, ClassSymbolData, TypedefSymbolData,
|
||||
FuncSymbolData, DefineSymbolData, AnonymousTypeData
|
||||
)
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo
|
||||
from lib.includes import t
|
||||
from lib.core.SymbolUtils import AnnotationContainsTType, CheckAnnotationHasCInline
|
||||
|
||||
|
||||
class ASTSymbolExtractor:
|
||||
"""从 Python 源文件的 AST 中提取所有符号信息"""
|
||||
|
||||
def __init__(self, symbol_table: SymbolTable):
|
||||
self._symtab = symbol_table
|
||||
|
||||
def extract(self, file_path: str) -> ModuleSymbols:
|
||||
"""提取文件中的所有符号信息"""
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
tree = ast.parse(code)
|
||||
|
||||
result = ModuleSymbols(file_path=file_path)
|
||||
|
||||
# 第一步:收集所有类的成员和匿名类型
|
||||
class_members = {}
|
||||
for node in tree.body:
|
||||
if isinstance(node, ast.ClassDef):
|
||||
members = {}
|
||||
self._collect_members(node, members, result.anonymous_types)
|
||||
class_members[node.name] = members
|
||||
|
||||
# 第二步:从每个顶层节点提取符号信息
|
||||
for node in tree.body:
|
||||
if isinstance(node, ast.ClassDef):
|
||||
members_info = class_members.get(node.name, {})
|
||||
result.classes.append(self._extract_class(node, members_info))
|
||||
elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
|
||||
self._extract_ann_assign(node, result)
|
||||
elif isinstance(node, ast.FunctionDef):
|
||||
result.functions.append(self._extract_function(node))
|
||||
|
||||
return result
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 成员收集(递归处理嵌套匿名类)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _collect_members(self, class_node, members, anonymous_types, prefix=''):
|
||||
"""递归收集类成员,包括嵌套匿名类型"""
|
||||
for item in class_node.body:
|
||||
if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name):
|
||||
member_name = item.target.id
|
||||
full_name = f'{prefix}{member_name}' if prefix else member_name
|
||||
member_type = CTypeInfo.FromNode(item.annotation, self._symtab)
|
||||
if member_type is None:
|
||||
member_type = CTypeInfo()
|
||||
member_type.BaseType = t.CInt()
|
||||
is_ptr = member_type.IsPtr
|
||||
if isinstance(item.annotation, ast.BinOp):
|
||||
annotation_str = ast.dump(item.annotation)
|
||||
if 'CPtr' in annotation_str:
|
||||
is_ptr = True
|
||||
members[full_name] = member_type.Copy()
|
||||
|
||||
elif isinstance(item, ast.ClassDef):
|
||||
is_anonymous = any(
|
||||
any(AnnotationContainsTType(base, 'Anonymous') for base in item.bases)
|
||||
) if item.bases else False
|
||||
|
||||
if is_anonymous:
|
||||
is_union = any(
|
||||
any(AnnotationContainsTType(base, 'CUnion') for base in item.bases)
|
||||
)
|
||||
|
||||
nested_name = f'{prefix}{item.name}' if prefix else item.name
|
||||
members[nested_name] = CTypeInfo()
|
||||
members[nested_name].BaseType = f'union {item.name}' if is_union else f'struct {item.name}'
|
||||
members[nested_name].PtrCount = 0
|
||||
members[nested_name].ArrayDims = []
|
||||
|
||||
new_prefix = f'{prefix}{item.name}.' if prefix else f'{item.name}.'
|
||||
self._collect_members(item, members, anonymous_types, new_prefix)
|
||||
|
||||
anonymous_members = {}
|
||||
for full_name, member_info in members.items():
|
||||
if full_name.startswith(f"{nested_name}."):
|
||||
member_name = full_name[len(nested_name) + 1:]
|
||||
anonymous_members[member_name] = member_info
|
||||
|
||||
if item.name not in anonymous_types:
|
||||
anonymous_types[item.name] = AnonymousTypeData(
|
||||
name=item.name,
|
||||
is_union=is_union,
|
||||
members=anonymous_members,
|
||||
lineno=item.lineno
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 类符号提取
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _extract_class(self, node, members_info) -> ClassSymbolData:
|
||||
"""从 ClassDef 节点提取类符号数据"""
|
||||
type_kind = 'struct'
|
||||
is_cpython_object = False
|
||||
is_packed = False
|
||||
|
||||
# 检查装饰器
|
||||
if hasattr(node, 'decorator_list') and node.decorator_list:
|
||||
for decorator in node.decorator_list:
|
||||
if isinstance(decorator, ast.Attribute):
|
||||
if (hasattr(decorator.value, 'id') and
|
||||
decorator.value.id == 't' and
|
||||
decorator.attr == 'Object'):
|
||||
is_cpython_object = True
|
||||
break
|
||||
elif isinstance(decorator, ast.Call):
|
||||
if isinstance(decorator.func, ast.Attribute):
|
||||
if hasattr(decorator.func.value, 'id') and decorator.func.value.id == 'c' and decorator.func.attr == 'Attribute':
|
||||
for arg in decorator.args:
|
||||
if isinstance(arg, ast.Attribute):
|
||||
if isinstance(arg.value, ast.Attribute):
|
||||
if hasattr(arg.value.value, 'id') and arg.value.value.id == 't' and arg.value.attr == 'attr' and arg.attr == 'packed':
|
||||
is_packed = True
|
||||
|
||||
# 检查基类
|
||||
for base in node.bases:
|
||||
if AnnotationContainsTType(base, 'CUnion'):
|
||||
type_kind = 'union'
|
||||
break
|
||||
elif AnnotationContainsTType(base, 'CEnum'):
|
||||
type_kind = 'enum'
|
||||
break
|
||||
elif AnnotationContainsTType(base, 'CStruct'):
|
||||
type_kind = 'struct'
|
||||
break
|
||||
elif AnnotationContainsTType(base, 'Object'):
|
||||
is_cpython_object = True
|
||||
type_kind = 'struct'
|
||||
break
|
||||
elif isinstance(base, ast.Name) and base.id == 'Exception':
|
||||
type_kind = 'exception'
|
||||
break
|
||||
elif isinstance(base, ast.Name):
|
||||
base_entry = self._symtab.get(base.id)
|
||||
if base_entry and base_entry.IsExceptionClass:
|
||||
type_kind = 'exception'
|
||||
break
|
||||
|
||||
# 提取枚举成员
|
||||
enum_members = []
|
||||
if type_kind == 'enum':
|
||||
next_enum_value = 0
|
||||
for item in node.body:
|
||||
if isinstance(item, ast.Assign):
|
||||
if len(item.targets) == 1 and isinstance(item.targets[0], ast.Name):
|
||||
member_name = item.targets[0].id
|
||||
if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int):
|
||||
next_enum_value = item.value.value + 1
|
||||
else:
|
||||
next_enum_value += 1
|
||||
enum_members.append((member_name, next_enum_value - 1, item.lineno))
|
||||
elif isinstance(item, ast.AnnAssign):
|
||||
if isinstance(item.target, ast.Name):
|
||||
member_name = item.target.id
|
||||
if item.value:
|
||||
if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int):
|
||||
next_enum_value = item.value.value + 1
|
||||
else:
|
||||
next_enum_value += 1
|
||||
else:
|
||||
next_enum_value += 1
|
||||
enum_members.append((member_name, next_enum_value - 1, item.lineno))
|
||||
|
||||
return ClassSymbolData(
|
||||
name=node.name,
|
||||
type_kind=type_kind,
|
||||
lineno=node.lineno,
|
||||
members=members_info,
|
||||
is_cpython_object=is_cpython_object,
|
||||
is_packed=is_packed,
|
||||
enum_members=enum_members,
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# AnnAssign 提取(typedef / define)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _extract_ann_assign(self, node, result: ModuleSymbols):
|
||||
"""从 AnnAssign 节点提取 typedef 或 define 数据"""
|
||||
var_name = node.target.id
|
||||
has_cdefine = AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False
|
||||
has_postdef = AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False
|
||||
has_ctypedef = AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False
|
||||
|
||||
if has_cdefine:
|
||||
result.defines.append(DefineSymbolData(
|
||||
name=var_name,
|
||||
lineno=node.lineno,
|
||||
value_node=node.value,
|
||||
))
|
||||
else:
|
||||
result.typedefs.append(TypedefSymbolData(
|
||||
name=var_name,
|
||||
lineno=node.lineno,
|
||||
annotation=node.annotation,
|
||||
value=node.value,
|
||||
has_cdefine=has_cdefine,
|
||||
has_postdef=has_postdef,
|
||||
has_ctypedef=has_ctypedef,
|
||||
))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 函数提取
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _extract_function(self, node) -> FuncSymbolData:
|
||||
"""从 FunctionDef 节点提取函数符号数据"""
|
||||
params = [(arg.arg, arg.annotation) for arg in node.args.args]
|
||||
is_variadic = node.args.vararg is not None
|
||||
is_inline = CheckAnnotationHasCInline(node.returns)
|
||||
|
||||
return FuncSymbolData(
|
||||
name=node.name,
|
||||
lineno=node.lineno,
|
||||
returns_node=node.returns,
|
||||
params=params,
|
||||
is_variadic=is_variadic,
|
||||
is_inline=is_inline,
|
||||
)
|
||||
68
lib/core/SymbolInserter.py
Normal file
68
lib/core/SymbolInserter.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""Pass 3: SymbolInserter — 将解析后的符号插入 SymbolTable(主命名空间)"""
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, List
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.SymbolTable import SymbolTable
|
||||
|
||||
from lib.core.SymbolData import ModuleSymbols
|
||||
|
||||
|
||||
class SymbolInserter:
|
||||
"""将解析后的符号插入 SymbolTable 的主命名空间(无前缀)"""
|
||||
|
||||
def __init__(self, symbol_table: SymbolTable):
|
||||
self._symtab = symbol_table
|
||||
|
||||
def insert(self, module_symbols: ModuleSymbols) -> List[str]:
|
||||
"""插入所有符号到主命名空间,返回已加载的符号名列表"""
|
||||
loaded = []
|
||||
file_path = module_symbols.file_path
|
||||
|
||||
# 插入类符号
|
||||
for cls in module_symbols.classes:
|
||||
self._symtab._InsertClassSymbol(
|
||||
cls.name, cls.type_kind, cls.lineno, file_path,
|
||||
cls.members, cls.is_cpython_object, cls.is_packed
|
||||
)
|
||||
loaded.append(cls.name)
|
||||
|
||||
# 插入枚举成员(短名 + 类名.成员名)
|
||||
if cls.type_kind == 'enum':
|
||||
for member_name, _member_value, member_lineno in cls.enum_members:
|
||||
self._symtab._InsertEnumMemberSymbol(member_name, cls.name, member_lineno, file_path)
|
||||
loaded.append(member_name)
|
||||
class_member_name = f"{cls.name}.{member_name}"
|
||||
self._symtab._InsertEnumMemberSymbol(class_member_name, cls.name, member_lineno, file_path)
|
||||
loaded.append(class_member_name)
|
||||
|
||||
# 插入 typedef 符号
|
||||
for td in module_symbols.typedefs:
|
||||
self._symtab._InsertTypedefSymbol(
|
||||
td.name, td.original_type_kind, td.original_class,
|
||||
td.lineno, file_path, td.members
|
||||
)
|
||||
loaded.append(td.name)
|
||||
|
||||
# 插入函数符号
|
||||
for func in module_symbols.functions:
|
||||
self._symtab._InsertFuncSymbol(
|
||||
func.name, func.ret_type, func.param_types,
|
||||
func.lineno, file_path, func.is_variadic, func.is_inline
|
||||
)
|
||||
loaded.append(func.name)
|
||||
|
||||
# 插入 define 符号
|
||||
for define in module_symbols.defines:
|
||||
self._symtab._InsertDefineSymbol(
|
||||
define.name, define.value, define.lineno, file_path
|
||||
)
|
||||
loaded.append(define.name)
|
||||
|
||||
# 插入匿名类型符号(短名)
|
||||
for anon_name, anon_data in module_symbols.anonymous_types.items():
|
||||
self._symtab._InsertAnonymousSymbol(
|
||||
anon_name, anon_data.is_union, anon_data.members,
|
||||
anon_data.lineno, file_path
|
||||
)
|
||||
|
||||
return loaded
|
||||
76
lib/core/SymbolReexporter.py
Normal file
76
lib/core/SymbolReexporter.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""Pass 4: PackageReexporter — 将符号重新导出到命名空间前缀下"""
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, List
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.SymbolTable import SymbolTable
|
||||
|
||||
from lib.core.SymbolData import ModuleSymbols
|
||||
|
||||
|
||||
class PackageReexporter:
|
||||
"""将已解析的符号重新导出到命名空间前缀下(如 mpool.MPool)"""
|
||||
|
||||
def __init__(self, symbol_table: SymbolTable):
|
||||
self._symtab = symbol_table
|
||||
|
||||
def reexport(self, module_symbols: ModuleSymbols, prefixes: List[str], lineno: int = 0) -> List[str]:
|
||||
"""将符号重新导出到所有命名空间前缀下,返回新增的符号名列表"""
|
||||
loaded = []
|
||||
file_path = module_symbols.file_path
|
||||
primary_prefix = prefixes[0] if prefixes else None
|
||||
|
||||
for prefix in prefixes:
|
||||
# 插入类符号(前缀.类名)
|
||||
for cls in module_symbols.classes:
|
||||
full_name = f"{prefix}.{cls.name}"
|
||||
self._symtab._InsertClassSymbol(
|
||||
full_name, cls.type_kind, cls.lineno, file_path,
|
||||
cls.members, cls.is_cpython_object, cls.is_packed
|
||||
)
|
||||
loaded.append(full_name)
|
||||
|
||||
# 插入枚举成员(前缀.成员名)
|
||||
if cls.type_kind == 'enum':
|
||||
for member_name, _member_value, member_lineno in cls.enum_members:
|
||||
full_member_name = f"{prefix}.{member_name}"
|
||||
self._symtab._InsertEnumMemberSymbol(full_member_name, cls.name, member_lineno, file_path)
|
||||
loaded.append(full_member_name)
|
||||
|
||||
# 插入 typedef 符号(前缀.名称)
|
||||
for td in module_symbols.typedefs:
|
||||
full_name = f"{prefix}.{td.name}"
|
||||
self._symtab._InsertTypedefSymbol(
|
||||
full_name, td.original_type_kind, td.original_class,
|
||||
td.lineno, file_path, td.members
|
||||
)
|
||||
loaded.append(full_name)
|
||||
|
||||
# 插入函数符号(前缀.名称)
|
||||
for func in module_symbols.functions:
|
||||
full_name = f"{prefix}.{func.name}"
|
||||
self._symtab._InsertFuncSymbol(
|
||||
full_name, func.ret_type, func.param_types,
|
||||
func.lineno, file_path, func.is_variadic, func.is_inline
|
||||
)
|
||||
loaded.append(full_name)
|
||||
|
||||
# 插入 define 符号(前缀.名称)
|
||||
for define in module_symbols.defines:
|
||||
full_name = f"{prefix}.{define.name}"
|
||||
self._symtab._InsertDefineSymbol(
|
||||
full_name, define.value, define.lineno, file_path
|
||||
)
|
||||
loaded.append(full_name)
|
||||
|
||||
# 插入模块别名
|
||||
self._symtab._InsertModuleSymbol(prefix, lineno, file_path)
|
||||
|
||||
# 插入匿名类型符号(前缀.名称)
|
||||
for anon_name, anon_data in module_symbols.anonymous_types.items():
|
||||
full_type_name = f"{prefix}.{anon_name}"
|
||||
self._symtab._InsertAnonymousSymbol(
|
||||
full_type_name, anon_data.is_union, anon_data.members,
|
||||
anon_data.lineno, file_path
|
||||
)
|
||||
|
||||
return loaded
|
||||
File diff suppressed because it is too large
Load Diff
224
lib/core/SymbolTypeResolver.py
Normal file
224
lib/core/SymbolTypeResolver.py
Normal file
@@ -0,0 +1,224 @@
|
||||
"""Pass 2: TypeResolver — 解析 typedef 类型、函数签名、define 值"""
|
||||
from __future__ import annotations
|
||||
import ast
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.SymbolTable import SymbolTable
|
||||
|
||||
from lib.core.SymbolData import (
|
||||
ModuleSymbols, TypedefSymbolData, FuncSymbolData, DefineSymbolData
|
||||
)
|
||||
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper
|
||||
from lib.includes import t
|
||||
|
||||
|
||||
class TypeResolver:
|
||||
"""解析从 AST 提取的原始符号中的类型信息"""
|
||||
|
||||
def __init__(self, symbol_table: SymbolTable):
|
||||
self._symtab = symbol_table
|
||||
|
||||
def resolve(self, module_symbols: ModuleSymbols) -> ModuleSymbols:
|
||||
"""解析所有类型信息,就地更新 ModuleSymbols"""
|
||||
# 构建 class_members 查找表(typedef Postdefinition 需要)
|
||||
class_members = {cls.name: cls.members for cls in module_symbols.classes}
|
||||
|
||||
# 解析 typedef
|
||||
for td in module_symbols.typedefs:
|
||||
self._resolve_typedef(td, class_members)
|
||||
|
||||
# 解析函数签名
|
||||
for func in module_symbols.functions:
|
||||
self._resolve_function(func)
|
||||
|
||||
# 解析 define 值
|
||||
for define in module_symbols.defines:
|
||||
self._resolve_define(define)
|
||||
|
||||
return module_symbols
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Typedef 解析
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _resolve_typedef(self, td: TypedefSymbolData, class_members: dict):
|
||||
"""解析单个 typedef 的类型信息"""
|
||||
is_postdef_with_typedef = td.has_postdef and td.has_ctypedef
|
||||
|
||||
if is_postdef_with_typedef:
|
||||
self._resolve_postdef_typedef(td, class_members)
|
||||
elif td.has_ctypedef:
|
||||
self._resolve_ctypedef_typedef(td)
|
||||
else:
|
||||
# 无特殊注解的 typedef
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
|
||||
def _resolve_postdef_typedef(self, td: TypedefSymbolData, class_members: dict):
|
||||
"""解析 Postdefinition + CTypedef 组合注解"""
|
||||
original_class = self._find_postdef_arg(td.annotation)
|
||||
if original_class and original_class in class_members:
|
||||
members_info = class_members[original_class]
|
||||
original_type_kind = 'struct'
|
||||
if original_class in self._symtab:
|
||||
orig_type_info = self._symtab[original_class]
|
||||
if orig_type_info.type_cls in (t.CStruct, t.CEnum, t.CUnion):
|
||||
if orig_type_info.type_cls is t.CStruct:
|
||||
original_type_kind = 'struct'
|
||||
elif orig_type_info.type_cls is t.CEnum:
|
||||
original_type_kind = 'enum'
|
||||
elif orig_type_info.type_cls is t.CUnion:
|
||||
original_type_kind = 'union'
|
||||
td.original_type_kind = original_type_kind
|
||||
td.original_class = original_class
|
||||
td.members = members_info
|
||||
else:
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
|
||||
def _resolve_ctypedef_typedef(self, td: TypedefSymbolData):
|
||||
"""解析 CTypedef 注解"""
|
||||
base_type_name = self._find_base_type(td.annotation)
|
||||
_TYPE_QUALIFIERS = {'CTypedef', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern', 'CDefine', 'CPostdefinition'}
|
||||
|
||||
if base_type_name == 'Callable':
|
||||
original_type = CTypeInfo()
|
||||
original_type.IsFuncPtr = True
|
||||
original_type.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
|
||||
original_type.FuncPtrParams = []
|
||||
td.original_type_kind = 'typedef'
|
||||
td.original_class = original_type
|
||||
elif base_type_name and base_type_name not in _TYPE_QUALIFIERS:
|
||||
cname = CTypeHelper.GetCName(base_type_name)
|
||||
if cname and cname != base_type_name:
|
||||
td.original_class = cname
|
||||
else:
|
||||
td.original_class = base_type_name[1:] if base_type_name.startswith('C') else base_type_name
|
||||
td.original_type_kind = 'typedef'
|
||||
else:
|
||||
# 尝试从值表达式解析
|
||||
self._resolve_typedef_from_value(td)
|
||||
|
||||
def _resolve_typedef_from_value(self, td: TypedefSymbolData):
|
||||
"""从值表达式解析 typedef 类型"""
|
||||
if not td.value:
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
return
|
||||
|
||||
value_base_type = self._find_base_type(td.value)
|
||||
_PTR_MODIFIERS = {'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'}
|
||||
|
||||
if value_base_type and value_base_type not in _PTR_MODIFIERS:
|
||||
cname = CTypeHelper.GetCName(value_base_type)
|
||||
if cname and cname != value_base_type:
|
||||
td.original_class = cname
|
||||
else:
|
||||
td.original_class = value_base_type[1:] if value_base_type.startswith('C') else value_base_type
|
||||
td.original_type_kind = 'typedef'
|
||||
return
|
||||
|
||||
if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr):
|
||||
left_type = self._symtab._ResolveTypedefValueType(td.value.left)
|
||||
right_type = self._symtab._ResolveTypedefValueType(td.value.right)
|
||||
is_ptr_type = right_type == 'ptr' or left_type == 'ptr'
|
||||
if is_ptr_type:
|
||||
base_name = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '')
|
||||
if base_name:
|
||||
original_type = base_name + ' *'
|
||||
else:
|
||||
original_type = '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'
|
||||
return
|
||||
|
||||
if isinstance(td.value, ast.Name):
|
||||
ref_name = td.value.id
|
||||
if ref_name in self._symtab:
|
||||
ref_info = self._symtab[ref_name]
|
||||
if ref_info and ref_info.IsTypedef and ref_info.OriginalType:
|
||||
td.original_class = ref_info.OriginalType
|
||||
td.original_type_kind = 'typedef'
|
||||
return
|
||||
|
||||
td.original_type_kind = None
|
||||
td.original_class = None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 函数签名解析
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _resolve_function(self, func: FuncSymbolData):
|
||||
"""解析函数的返回类型和参数类型"""
|
||||
func.ret_type = self._symtab._GetFuncRetTypeStr(func.returns_node)
|
||||
func.param_types = []
|
||||
for _arg_name, annotation in func.params:
|
||||
if annotation:
|
||||
func.param_types.append(self._symtab._GetFuncParamTypeStr(annotation))
|
||||
else:
|
||||
func.param_types.append('i8*')
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Define 值解析
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _resolve_define(self, define: DefineSymbolData):
|
||||
"""解析 define 常量值"""
|
||||
if define.value_node:
|
||||
define.value = self._symtab._eval_const_expr(define.value_node)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 静态工具方法(原 _LoadSymbolsFromFile 中的闭包)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _find_base_type(node):
|
||||
"""从注解 AST 节点中查找基础类型名称"""
|
||||
if isinstance(node, ast.Attribute):
|
||||
if hasattr(node.value, 'id') and node.value.id == 't':
|
||||
if node.attr == 'CPtr':
|
||||
return 'ptr'
|
||||
return node.attr
|
||||
elif isinstance(node, ast.Subscript):
|
||||
if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and node.value.value.id == 't' and node.value.attr == 'Callable':
|
||||
return 'Callable'
|
||||
elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
|
||||
left_result = TypeResolver._find_base_type(node.left)
|
||||
if left_result == 'ptr':
|
||||
right_result = 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 = 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'
|
||||
if left_result:
|
||||
return left_result
|
||||
if right_result:
|
||||
return right_result
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _find_postdef_arg(node):
|
||||
"""从注解 AST 节点中查找 Postdefinition 参数"""
|
||||
if isinstance(node, ast.Call):
|
||||
if isinstance(node.func, ast.Attribute):
|
||||
if hasattr(node.func.value, 'id') and node.func.value.id == 't' and node.func.attr == 'Postdefinition':
|
||||
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 = TypeResolver._find_postdef_arg(node.left)
|
||||
if left_result:
|
||||
return left_result
|
||||
right_result = TypeResolver._find_postdef_arg(node.right)
|
||||
if right_result:
|
||||
return right_result
|
||||
return None
|
||||
56
lib/core/SymbolUtils.py
Normal file
56
lib/core/SymbolUtils.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""共享工具函数:符号表处理中使用的 AST 分析工具"""
|
||||
from __future__ import annotations
|
||||
import ast
|
||||
from lib.includes import t
|
||||
|
||||
|
||||
def IsTModuleType(TypeName: str) -> bool:
|
||||
"""检测类型名称是否是 t 模块中的类型(CType 或其他特殊类型)"""
|
||||
if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'):
|
||||
return True
|
||||
TypeClass = getattr(t, TypeName, None)
|
||||
if TypeClass and isinstance(TypeClass, type):
|
||||
if issubclass(TypeClass, t.CType):
|
||||
return True
|
||||
FallbackClass = 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:
|
||||
"""检测 AST 节点中是否包含指定名称的 t 模块类型"""
|
||||
if isinstance(node, ast.Attribute):
|
||||
if (hasattr(node.value, 'id') and node.value.id == 't' and
|
||||
node.attr == TypeName):
|
||||
return True
|
||||
elif isinstance(node, ast.BinOp):
|
||||
return AnnotationContainsTType(node.left, TypeName) or AnnotationContainsTType(node.right, TypeName)
|
||||
elif isinstance(node, ast.Call):
|
||||
if AnnotationContainsTType(node.func, TypeName):
|
||||
return True
|
||||
for arg in node.args:
|
||||
if AnnotationContainsTType(arg, TypeName):
|
||||
return True
|
||||
elif isinstance(node, ast.Subscript):
|
||||
if AnnotationContainsTType(node.value, TypeName):
|
||||
return True
|
||||
if AnnotationContainsTType(node.slice, TypeName):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def CheckAnnotationHasCInline(annotation_node) -> 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':
|
||||
return True
|
||||
if isinstance(annotation_node, ast.Name):
|
||||
if annotation_node.id == 'CInline':
|
||||
return True
|
||||
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
|
||||
@@ -328,9 +328,9 @@ class AnnotationLoaderMixin:
|
||||
orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}')
|
||||
elif orig_entry.get('type') == 'enum':
|
||||
orig_type_str = f'enum {original_name}'
|
||||
elif hasattr(orig_entry, 'IsTypedef') and orig_entry.IsTypedef:
|
||||
orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}')
|
||||
elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum:
|
||||
elif orig_entry.IsTypedef:
|
||||
orig_type_str = orig_entry.OriginalType or f'struct {original_name}'
|
||||
elif orig_entry.IsEnum:
|
||||
orig_type_str = f'enum {original_name}'
|
||||
TypedefNode.OriginalType = orig_type_str
|
||||
TypedefNode.set('source', 'annotation_module')
|
||||
|
||||
@@ -112,42 +112,8 @@ class ConstEvalMixin:
|
||||
return self._try_eval_const_expr(node, Gen)
|
||||
|
||||
def _try_eval_const_expr(self, node, Gen):
|
||||
import ast
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
elif isinstance(node, ast.BinOp):
|
||||
left = self._try_eval_const_expr(node.left, Gen)
|
||||
right = self._try_eval_const_expr(node.right, Gen)
|
||||
if left is None or right is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.Add):
|
||||
return left + right
|
||||
elif isinstance(node.op, ast.Sub):
|
||||
return left - right
|
||||
elif isinstance(node.op, ast.Mult):
|
||||
return left * right
|
||||
elif isinstance(node.op, ast.LShift):
|
||||
return left << right
|
||||
elif isinstance(node.op, ast.RShift):
|
||||
return left >> right
|
||||
elif isinstance(node.op, ast.BitOr):
|
||||
return left | right
|
||||
elif isinstance(node.op, ast.BitAnd):
|
||||
return left & right
|
||||
elif isinstance(node.op, ast.BitXor):
|
||||
return left ^ right
|
||||
elif isinstance(node, ast.UnaryOp):
|
||||
operand = self._try_eval_const_expr(node.operand, Gen)
|
||||
if operand is None:
|
||||
return None
|
||||
if isinstance(node.op, ast.USub):
|
||||
return -operand
|
||||
elif isinstance(node.op, ast.Invert):
|
||||
return ~operand
|
||||
elif isinstance(node, ast.Name):
|
||||
if node.id in getattr(Gen, '_DefineConstants', {}):
|
||||
return Gen._DefineConstants[node.id]
|
||||
return None
|
||||
from lib.core.ConstEvaluator import ConstEvaluator
|
||||
return ConstEvaluator.eval_with_symtab(node, self.SymbolTable)
|
||||
|
||||
def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen):
|
||||
from lib.core.Handles.HandlesAssign import AssignHandle
|
||||
|
||||
@@ -67,6 +67,7 @@ FIELD_ROUTES = {
|
||||
'ArrayPtr': ('ts', 'array_ptr'),
|
||||
'IsState': ('ts', 'is_state'),
|
||||
'OriginalType': ('ts', 'original_type'),
|
||||
'IsSigned': ('ts', 'is_signed'),
|
||||
|
||||
# --- SymbolMeta 字段 ---
|
||||
'Name': ('sm', 'name'),
|
||||
@@ -87,6 +88,8 @@ FIELD_ROUTES = {
|
||||
'IsModuleAlias': ('sm', 'is_module_alias'),
|
||||
'ResolvedModule': ('sm', 'resolved_module'),
|
||||
'DefineValue': ('sm', 'define_value'),
|
||||
'EnumName': ('sm', 'enum_name'),
|
||||
'value': ('sm', 'enum_value'),
|
||||
|
||||
# --- _kind_flags(独立 bool,存储在 SymbolMeta._kind_flags)---
|
||||
'IsStruct': ('kf', 'IsStruct'),
|
||||
@@ -127,6 +130,7 @@ class TypeSpec:
|
||||
'is_array_ptr', 'array_ptr',
|
||||
'is_state',
|
||||
'original_type',
|
||||
'is_signed',
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
@@ -150,6 +154,7 @@ class TypeSpec:
|
||||
self.array_ptr: Any = None # CTypeInfo
|
||||
self.is_state: bool = False
|
||||
self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型)
|
||||
self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号
|
||||
|
||||
@property
|
||||
def base_type(self) -> Any:
|
||||
@@ -203,6 +208,7 @@ class TypeSpec:
|
||||
new.array_ptr = self.array_ptr
|
||||
new.is_state = self.is_state
|
||||
new.original_type = self.original_type
|
||||
new.is_signed = self.is_signed
|
||||
return new
|
||||
|
||||
|
||||
@@ -222,6 +228,7 @@ class SymbolMeta:
|
||||
'members',
|
||||
'is_cpython_object', 'is_packed',
|
||||
'define_value',
|
||||
'enum_name', 'enum_value',
|
||||
'is_inline', 'inline_body', 'inline_params',
|
||||
'is_anonymous',
|
||||
'renum_variants',
|
||||
@@ -241,6 +248,8 @@ class SymbolMeta:
|
||||
self.is_cpython_object: bool = False
|
||||
self.is_packed: bool = False
|
||||
self.define_value: Any = None
|
||||
self.enum_name: str = "" # 枚举成员所属的枚举类名
|
||||
self.enum_value: Any = None # 枚举成员的值
|
||||
self.is_inline: bool = False
|
||||
self.inline_body: list | None = None
|
||||
self.inline_params: list | None = None
|
||||
@@ -287,6 +296,8 @@ class SymbolMeta:
|
||||
new.is_cpython_object = self.is_cpython_object
|
||||
new.is_packed = self.is_packed
|
||||
new.define_value = self.define_value
|
||||
new.enum_name = self.enum_name
|
||||
new.enum_value = self.enum_value
|
||||
new.is_inline = self.is_inline
|
||||
new.inline_body = self.inline_body
|
||||
new.inline_params = list(self.inline_params) if self.inline_params else None
|
||||
|
||||
Reference in New Issue
Block a user