将 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
|
IsUnion = False
|
||||||
if ClassName and ClassName in self.Trans.SymbolTable:
|
if ClassName and ClassName in self.Trans.SymbolTable:
|
||||||
TypeInfo = self.Trans.SymbolTable[ClassName]
|
TypeInfo = self.Trans.SymbolTable[ClassName]
|
||||||
if hasattr(TypeInfo, 'IsUnion') and TypeInfo.IsUnion:
|
if TypeInfo.IsUnion:
|
||||||
IsUnion = True
|
IsUnion = True
|
||||||
if ClassName and ClassName in Gen.structs:
|
if ClassName and ClassName in Gen.structs:
|
||||||
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||||||
|
|||||||
@@ -440,8 +440,8 @@ class AssignHandle:
|
|||||||
sym_key = f"{ModulePath}.{FuncName}"
|
sym_key = f"{ModulePath}.{FuncName}"
|
||||||
sym_info = self.Trans.SymbolTable.get(sym_key)
|
sym_info = self.Trans.SymbolTable.get(sym_key)
|
||||||
if sym_info and sym_info.IsFunction:
|
if sym_info and sym_info.IsFunction:
|
||||||
ret_type_info = getattr(sym_info, 'FuncPtrReturn', None)
|
ret_type_info = sym_info.FuncPtrReturn
|
||||||
param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])]
|
param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])]
|
||||||
if ret_type_info:
|
if ret_type_info:
|
||||||
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||||
ret_type = ret_type_info.ToLLVM(Gen)
|
ret_type = ret_type_info.ToLLVM(Gen)
|
||||||
@@ -616,7 +616,7 @@ class AssignHandle:
|
|||||||
if ClassName and ClassName in Gen.structs:
|
if ClassName and ClassName in Gen.structs:
|
||||||
PropKey = f'{ClassName}.{AttrName}'
|
PropKey = f'{ClassName}.{AttrName}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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')
|
SelfVar = Gen._get_var_ptr('self')
|
||||||
if SelfVar:
|
if SelfVar:
|
||||||
SelfPtr = Gen._load(SelfVar, name="self")
|
SelfPtr = Gen._load(SelfVar, name="self")
|
||||||
@@ -734,7 +734,7 @@ class AssignHandle:
|
|||||||
if ClassName and ClassName in Gen.structs:
|
if ClassName and ClassName in Gen.structs:
|
||||||
PropKey = f'{ClassName}.{AttrName}'
|
PropKey = f'{ClassName}.{AttrName}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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)
|
ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value)
|
||||||
SetterFunc = Gen._get_function(PropKey + '$set')
|
SetterFunc = Gen._get_function(PropKey + '$set')
|
||||||
if SetterFunc and ObjVal:
|
if SetterFunc and ObjVal:
|
||||||
@@ -1222,7 +1222,7 @@ class AssignHandle:
|
|||||||
elif isinstance(count_node, ast.Name):
|
elif isinstance(count_node, ast.Name):
|
||||||
if count_node.id in self.Trans.SymbolTable:
|
if count_node.id in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[count_node.id]
|
SymInfo = self.Trans.SymbolTable[count_node.id]
|
||||||
if isinstance(getattr(SymInfo, 'value', None), int):
|
if isinstance(SymInfo.value, int):
|
||||||
ArrayCount = SymInfo.value
|
ArrayCount = SymInfo.value
|
||||||
if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}):
|
if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}):
|
||||||
DefVal = Gen._define_constants[count_node.id]
|
DefVal = Gen._define_constants[count_node.id]
|
||||||
@@ -1558,94 +1558,10 @@ class AssignHandle:
|
|||||||
Gen.variables[VarName] = GlobalVar
|
Gen.variables[VarName] = GlobalVar
|
||||||
|
|
||||||
def _eval_const_expr(self, node, Gen):
|
def _eval_const_expr(self, node, Gen):
|
||||||
"""计算常量表达式的值"""
|
"""计算常量表达式的值(委托到 ConstEvaluator)"""
|
||||||
import ast
|
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
|
||||||
if isinstance(node, ast.Constant):
|
ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable)
|
||||||
return node.value
|
return ConstEvaluator.eval_full(node, ctx)
|
||||||
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
|
|
||||||
|
|
||||||
def _eval_global_count(self, node, Gen):
|
def _eval_global_count(self, node, Gen):
|
||||||
val = self._eval_const_expr(node, Gen)
|
val = self._eval_const_expr(node, Gen)
|
||||||
|
|||||||
@@ -395,74 +395,8 @@ class CTypeInfo:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def TryEvalConstExpr(node, SymbolTable):
|
def TryEvalConstExpr(node, SymbolTable):
|
||||||
if isinstance(node, ast.Constant) and isinstance(node.value, int):
|
from lib.core.ConstEvaluator import ConstEvaluator
|
||||||
return node.value
|
return ConstEvaluator.eval_with_symtab(node, SymbolTable)
|
||||||
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
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo":
|
def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo":
|
||||||
@@ -1136,10 +1070,6 @@ class CTypeInfo:
|
|||||||
NewInfo._ts.original_type = NewInfo._ts.original_type.Copy()
|
NewInfo._ts.original_type = NewInfo._ts.original_type.Copy()
|
||||||
if NewInfo._ts.array_ptr:
|
if NewInfo._ts.array_ptr:
|
||||||
NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy()
|
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
|
return NewInfo
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class DeleteHandle(BaseHandle):
|
|||||||
if ClassName:
|
if ClassName:
|
||||||
PropKey = f'{ClassName}.{AttrName}'
|
PropKey = f'{ClassName}.{AttrName}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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')
|
SelfVar = Gen._get_var_ptr('self')
|
||||||
if SelfVar:
|
if SelfVar:
|
||||||
SelfPtr = Gen._load(SelfVar, name="self")
|
SelfPtr = Gen._load(SelfVar, name="self")
|
||||||
@@ -54,7 +54,7 @@ class DeleteHandle(BaseHandle):
|
|||||||
if ClassName:
|
if ClassName:
|
||||||
PropKey = f'{ClassName}.{AttrName}'
|
PropKey = f'{ClassName}.{AttrName}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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)
|
obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value)
|
||||||
if obj_val:
|
if obj_val:
|
||||||
DeleterFunc = Gen._get_function(PropKey + '$del')
|
DeleterFunc = Gen._get_function(PropKey + '$del')
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ class ExprHandle(BaseHandle):
|
|||||||
if VarName not in getattr(Gen, '_define_constants', {}):
|
if VarName not in getattr(Gen, '_define_constants', {}):
|
||||||
try:
|
try:
|
||||||
sym_info = self.translator.SymbolTable.get(VarName)
|
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
|
val = sym_info.DefineValue
|
||||||
if isinstance(val, int):
|
if isinstance(val, int):
|
||||||
# Use VarType hint if available
|
# Use VarType hint if available
|
||||||
@@ -400,9 +400,9 @@ class ExprHandle(BaseHandle):
|
|||||||
return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0)
|
return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0)
|
||||||
if VarName in self.Trans.SymbolTable:
|
if VarName in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[VarName]
|
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)
|
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)
|
MangledName = Gen._mangle_func_name(VarName)
|
||||||
if MangledName in Gen.module.globals:
|
if MangledName in Gen.module.globals:
|
||||||
g = Gen.module.globals[MangledName]
|
g = Gen.module.globals[MangledName]
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
PossibleKeys.append(key)
|
PossibleKeys.append(key)
|
||||||
for lookup_key in PossibleKeys:
|
for lookup_key in PossibleKeys:
|
||||||
SymInfo = self.Trans.SymbolTable.get(lookup_key)
|
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)
|
return self._make_define_constant(Gen, SymInfo.DefineValue)
|
||||||
# 也检查 _define_constants
|
# 也检查 _define_constants
|
||||||
define_constants = getattr(Gen, '_define_constants', {})
|
define_constants = getattr(Gen, '_define_constants', {})
|
||||||
@@ -202,7 +202,7 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
# 检查 property getter
|
# 检查 property getter
|
||||||
PropKey = f'{ClassName}.{Node.attr}'
|
PropKey = f'{ClassName}.{Node.attr}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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')
|
SelfVar = Gen._get_var_ptr('self')
|
||||||
if SelfVar:
|
if SelfVar:
|
||||||
SelfPtr = Gen._load(SelfVar, name="self")
|
SelfPtr = Gen._load(SelfVar, name="self")
|
||||||
@@ -234,16 +234,16 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
def _handle_attr_enum(self, Node, VarName):
|
def _handle_attr_enum(self, Node, VarName):
|
||||||
"""处理枚举成员访问 (VarName 是枚举类型名)"""
|
"""处理枚举成员访问 (VarName 是枚举类型名)"""
|
||||||
SymInfo = self.Trans.SymbolTable.get(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
|
return None
|
||||||
if Node.attr in self.Trans.SymbolTable:
|
if Node.attr in self.Trans.SymbolTable:
|
||||||
MemberInfo = self.Trans.SymbolTable[Node.attr]
|
MemberInfo = self.Trans.SymbolTable[Node.attr]
|
||||||
if getattr(MemberInfo, 'IsEnumMember', None) and getattr(MemberInfo, 'EnumName', None) == VarName:
|
if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName:
|
||||||
if isinstance(getattr(MemberInfo, 'value', None), int):
|
if isinstance(MemberInfo.value, int):
|
||||||
return ir.Constant(ir.IntType(32), MemberInfo.value)
|
return ir.Constant(ir.IntType(32), MemberInfo.value)
|
||||||
for key, info in self.Trans.SymbolTable.items():
|
for key, info in self.Trans.SymbolTable.items():
|
||||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == VarName and key == Node.attr:
|
if info.IsEnumMember and info.EnumName == VarName and key == Node.attr:
|
||||||
if isinstance(getattr(info, 'value', None), int):
|
if isinstance(info.value, int):
|
||||||
return ir.Constant(ir.IntType(32), info.value)
|
return ir.Constant(ir.IntType(32), info.value)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
# 检查 property getter
|
# 检查 property getter
|
||||||
PropKey = f'{ClassName}.{AttrName}'
|
PropKey = f'{ClassName}.{AttrName}'
|
||||||
PropInfo = self.Trans.SymbolTable.get(PropKey)
|
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)
|
ObjVal = self.HandleExprLlvm(Node.value)
|
||||||
GetterFunc = Gen._get_function(PropKey)
|
GetterFunc = Gen._get_function(PropKey)
|
||||||
if GetterFunc and ObjVal:
|
if GetterFunc and ObjVal:
|
||||||
@@ -297,7 +297,7 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
TypeInfo = self.Trans.SymbolTable.get(ClassName)
|
TypeInfo = self.Trans.SymbolTable.get(ClassName)
|
||||||
IsUnion = TypeInfo.IsUnion if TypeInfo else False
|
IsUnion = TypeInfo.IsUnion if TypeInfo else False
|
||||||
IsCenum = TypeInfo.IsEnum 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 处理
|
# REnum 处理
|
||||||
if IsRenum:
|
if IsRenum:
|
||||||
@@ -322,12 +322,12 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"):
|
for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"):
|
||||||
if qname in self.Trans.SymbolTable:
|
if qname in self.Trans.SymbolTable:
|
||||||
info = self.Trans.SymbolTable[qname]
|
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)
|
return ir.Constant(ir.IntType(32), info.value)
|
||||||
for key, info in self.Trans.SymbolTable.items():
|
for key, info in self.Trans.SymbolTable.items():
|
||||||
if key == AttrName:
|
if key == AttrName:
|
||||||
if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == ClassName:
|
if info.IsEnumMember and info.EnumName == ClassName:
|
||||||
if isinstance(getattr(info, 'value', None), int):
|
if isinstance(info.value, int):
|
||||||
return ir.Constant(ir.IntType(32), info.value)
|
return ir.Constant(ir.IntType(32), info.value)
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -1062,7 +1062,7 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
possible_keys.append(key)
|
possible_keys.append(key)
|
||||||
for lookup_key in possible_keys:
|
for lookup_key in possible_keys:
|
||||||
SymInfo = self.Trans.SymbolTable.get(lookup_key)
|
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
|
val = SymInfo.DefineValue
|
||||||
if isinstance(val, int):
|
if isinstance(val, int):
|
||||||
if val > 0x7FFFFFFF or val < -0x80000000:
|
if val > 0x7FFFFFFF or val < -0x80000000:
|
||||||
@@ -1085,21 +1085,21 @@ class ExprAttrHandle(BaseHandle):
|
|||||||
for enum_key in enum_keys:
|
for enum_key in enum_keys:
|
||||||
if enum_key in self.Trans.SymbolTable:
|
if enum_key in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[enum_key]
|
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}"):
|
for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"):
|
||||||
if qname in self.Trans.SymbolTable:
|
if qname in self.Trans.SymbolTable:
|
||||||
info = self.Trans.SymbolTable[qname]
|
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)
|
return ir.Constant(ir.IntType(32), info.value)
|
||||||
for key, info in self.Trans.SymbolTable.items():
|
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 info.IsEnumMember and info.EnumName == enum_key and key == member_name:
|
||||||
if isinstance(getattr(info, 'value', None), int):
|
if isinstance(info.value, int):
|
||||||
return ir.Constant(ir.IntType(32), info.value)
|
return ir.Constant(ir.IntType(32), info.value)
|
||||||
for key, info in self.Trans.SymbolTable.items():
|
for key, info in self.Trans.SymbolTable.items():
|
||||||
if getattr(info, 'IsEnumMember', None) and key == member_name:
|
if info.IsEnumMember and key == member_name:
|
||||||
if isinstance(getattr(info, 'value', None), int):
|
if isinstance(info.value, int):
|
||||||
for enum_key in enum_keys:
|
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 ir.Constant(ir.IntType(32), info.value)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ class ExprBuiltinHandle(BaseHandle):
|
|||||||
LastPart = arg.attr
|
LastPart = arg.attr
|
||||||
if LastPart in self.Trans.SymbolTable:
|
if LastPart in self.Trans.SymbolTable:
|
||||||
AttrInfo = self.Trans.SymbolTable[LastPart]
|
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
|
enum_type_name = AttrInfo.EnumName
|
||||||
elif isinstance(arg.value, ast.Attribute):
|
elif isinstance(arg.value, ast.Attribute):
|
||||||
attr_path = _get_attr_path(arg)
|
attr_path = _get_attr_path(arg)
|
||||||
@@ -554,14 +554,14 @@ class ExprBuiltinHandle(BaseHandle):
|
|||||||
for qname in (qualified_name_dot, qualified_name_under):
|
for qname in (qualified_name_dot, qualified_name_under):
|
||||||
if qname in self.Trans.SymbolTable:
|
if qname in self.Trans.SymbolTable:
|
||||||
info = self.Trans.SymbolTable[qname]
|
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
|
enum_member_found = info
|
||||||
break
|
break
|
||||||
if not enum_member_found:
|
if not enum_member_found:
|
||||||
for key in self.Trans.SymbolTable:
|
for key in self.Trans.SymbolTable:
|
||||||
if key == LastPart:
|
if key == LastPart:
|
||||||
info = self.Trans.SymbolTable[key]
|
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
|
enum_member_found = info
|
||||||
break
|
break
|
||||||
if enum_member_found:
|
if enum_member_found:
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ class ExprCallHandle(BaseHandle):
|
|||||||
if first_part in aliases:
|
if first_part in aliases:
|
||||||
ModulePath = aliases[first_part] + ModulePath[len(first_part):]
|
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_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:
|
if is_instance_var and not is_class_name:
|
||||||
return self._HandleMethodCallLlvm(Node)
|
return self._HandleMethodCallLlvm(Node)
|
||||||
FuncAttr = Node.func.attr
|
FuncAttr = Node.func.attr
|
||||||
@@ -454,11 +454,11 @@ class ExprCallHandle(BaseHandle):
|
|||||||
result = self._HandleClassNewLlvm(Node, FuncAttr)
|
result = self._HandleClassNewLlvm(Node, FuncAttr)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None):
|
if SymInfo.IsEnumMember and SymInfo.EnumName:
|
||||||
EnumName = SymInfo.EnumName
|
EnumName = SymInfo.EnumName
|
||||||
if EnumName in self.Trans.SymbolTable:
|
if EnumName in self.Trans.SymbolTable:
|
||||||
EnumInfo = self.Trans.SymbolTable[EnumName]
|
EnumInfo = self.Trans.SymbolTable[EnumName]
|
||||||
if getattr(EnumInfo, 'IsRenum', False):
|
if EnumInfo.IsRenum:
|
||||||
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
|
result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
@@ -480,9 +480,9 @@ class ExprCallHandle(BaseHandle):
|
|||||||
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
||||||
if FullAttrKey in self.Trans.SymbolTable:
|
if FullAttrKey in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[FullAttrKey]
|
SymInfo = self.Trans.SymbolTable[FullAttrKey]
|
||||||
if getattr(SymInfo, 'IsTypedef', False):
|
if SymInfo.IsTypedef:
|
||||||
return ir.Constant(ir.IntType(32), 0)
|
return ir.Constant(ir.IntType(32), 0)
|
||||||
if getattr(SymInfo, 'IsStruct', False):
|
if SymInfo.IsStruct:
|
||||||
if FuncAttr not in Gen.structs:
|
if FuncAttr not in Gen.structs:
|
||||||
self._ensure_struct_declared(FuncAttr)
|
self._ensure_struct_declared(FuncAttr)
|
||||||
if FuncAttr in Gen.structs:
|
if FuncAttr in Gen.structs:
|
||||||
@@ -533,7 +533,7 @@ class ExprCallHandle(BaseHandle):
|
|||||||
raise Exception(f"Undefined method: 't.{FuncAttr}'")
|
raise Exception(f"Undefined method: 't.{FuncAttr}'")
|
||||||
if isinstance(Node.func.value, ast.Attribute):
|
if isinstance(Node.func.value, ast.Attribute):
|
||||||
inner_attr = Node.func.value.attr
|
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)
|
static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr)
|
||||||
if static_result is not None:
|
if static_result is not None:
|
||||||
return static_result
|
return static_result
|
||||||
@@ -569,11 +569,11 @@ class ExprCallHandle(BaseHandle):
|
|||||||
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}:
|
if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}:
|
||||||
# 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明
|
# 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明
|
||||||
_attr_sym = self.Trans.SymbolTable.get(FuncAttr)
|
_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:
|
if not _is_func_or_var and ModulePath:
|
||||||
_full_key = f"{ModulePath}.{FuncAttr}"
|
_full_key = f"{ModulePath}.{FuncAttr}"
|
||||||
_full_sym = self.Trans.SymbolTable.get(_full_key)
|
_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
|
_is_func_or_var = True
|
||||||
# 优先检查 FuncAttr 是否为 struct/类构造器
|
# 优先检查 FuncAttr 是否为 struct/类构造器
|
||||||
if not _is_func_or_var and FuncAttr not in Gen.structs:
|
if not _is_func_or_var and FuncAttr not in Gen.structs:
|
||||||
@@ -587,7 +587,7 @@ class ExprCallHandle(BaseHandle):
|
|||||||
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
FullAttrKey = f"{ModulePath}.{FuncAttr}"
|
||||||
if FullAttrKey in self.Trans.SymbolTable:
|
if FullAttrKey in self.Trans.SymbolTable:
|
||||||
FullSymInfo = self.Trans.SymbolTable[FullAttrKey]
|
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:
|
if FuncAttr not in Gen.structs:
|
||||||
self._ensure_struct_declared(FuncAttr)
|
self._ensure_struct_declared(FuncAttr)
|
||||||
if FuncAttr in Gen.structs:
|
if FuncAttr in Gen.structs:
|
||||||
@@ -649,7 +649,7 @@ class ExprCallHandle(BaseHandle):
|
|||||||
Gen = self.Trans.LlvmGen
|
Gen = self.Trans.LlvmGen
|
||||||
# 如果名称是函数或变量,不应创建 struct
|
# 如果名称是函数或变量,不应创建 struct
|
||||||
SymInfo = self.Trans.SymbolTable.get(class_name)
|
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
|
return
|
||||||
if class_name in Gen.structs:
|
if class_name in Gen.structs:
|
||||||
existing = Gen.structs[class_name]
|
existing = Gen.structs[class_name]
|
||||||
@@ -721,16 +721,16 @@ class ExprCallHandle(BaseHandle):
|
|||||||
SymKey = f'{ClassName}.{MethodName}'
|
SymKey = f'{ClassName}.{MethodName}'
|
||||||
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName)
|
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName)
|
||||||
if SymInfo and SymInfo.IsFunction:
|
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:
|
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||||
ret_type = ret_type_info.ToLLVM(Gen)
|
ret_type = ret_type_info.ToLLVM(Gen)
|
||||||
else:
|
else:
|
||||||
ret_type = Gen._CType2LLVM('i32', False)
|
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):
|
if isinstance(ret_type, ir.VoidType):
|
||||||
ret_type = ir.IntType(32)
|
ret_type = ir.IntType(32)
|
||||||
llvm_param_types = []
|
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:
|
if ClassName in Gen.structs and not is_static:
|
||||||
llvm_param_types.append(ir.PointerType(Gen.structs[ClassName]))
|
llvm_param_types.append(ir.PointerType(Gen.structs[ClassName]))
|
||||||
for pt in param_type_infos:
|
for pt in param_type_infos:
|
||||||
@@ -762,8 +762,8 @@ class ExprCallHandle(BaseHandle):
|
|||||||
CallArgs = []
|
CallArgs = []
|
||||||
SymKey = f'{ClassName}.{MethodName}'
|
SymKey = f'{ClassName}.{MethodName}'
|
||||||
SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(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_static_call = SymInfo is not None 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_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList
|
||||||
# @classmethod: 在参数列表前插入 cls(栈上分配的类实例指针)
|
# @classmethod: 在参数列表前插入 cls(栈上分配的类实例指针)
|
||||||
if is_classmethod_call and ClassName in Gen.structs:
|
if is_classmethod_call and ClassName in Gen.structs:
|
||||||
ClsPtr = Gen._alloca(Gen.structs[ClassName], name=f"cls_{ClassName}")
|
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)
|
mangled_name = Gen._mangle_func_name(func_name, ModulePath)
|
||||||
sym_key = f'{ModulePath}.{func_name}'
|
sym_key = f'{ModulePath}.{func_name}'
|
||||||
sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(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))
|
is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline))
|
||||||
if is_inline and getattr(sym_info, 'InlineBody', None):
|
if is_inline and sym_info.InlineBody:
|
||||||
self._HandleInlineExpandLlvm(Node, sym_info)
|
self._HandleInlineExpandLlvm(Node, sym_info)
|
||||||
return ir.Constant(ir.IntType(32), 1)
|
return ir.Constant(ir.IntType(32), 1)
|
||||||
sym_info_exact = self.Trans.SymbolTable.get(sym_key)
|
sym_info_exact = self.Trans.SymbolTable.get(sym_key)
|
||||||
if sym_info_exact:
|
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]
|
exact_param_names = [pn for pn, _ in exact_params]
|
||||||
if exact_param_names:
|
if exact_param_names:
|
||||||
provided = len(Node.args)
|
provided = len(Node.args)
|
||||||
@@ -1280,15 +1280,15 @@ class ExprCallHandle(BaseHandle):
|
|||||||
if not sym_info:
|
if not sym_info:
|
||||||
sym_info = self.Trans.SymbolTable.get(func_name)
|
sym_info = self.Trans.SymbolTable.get(func_name)
|
||||||
if sym_info:
|
if sym_info:
|
||||||
is_func = getattr(sym_info, 'IsFunction', False)
|
is_func = sym_info.IsFunction
|
||||||
sym_is_variadic = getattr(sym_info, 'IsVariadic', False)
|
sym_is_variadic = sym_info.IsVariadic
|
||||||
if is_func:
|
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:
|
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||||
ret_type = ret_type_info.ToLLVM(Gen)
|
ret_type = ret_type_info.ToLLVM(Gen)
|
||||||
else:
|
else:
|
||||||
ret_type = Gen._CType2LLVM('i32', False)
|
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]
|
param_type_infos = [pt for _, pt in sym_params]
|
||||||
if isinstance(ret_type, ir.VoidType):
|
if isinstance(ret_type, ir.VoidType):
|
||||||
ret_type = ir.IntType(32)
|
ret_type = ir.IntType(32)
|
||||||
@@ -1411,15 +1411,15 @@ class ExprCallHandle(BaseHandle):
|
|||||||
if not sym_info:
|
if not sym_info:
|
||||||
sym_info = self.Trans.SymbolTable.get(func_name)
|
sym_info = self.Trans.SymbolTable.get(func_name)
|
||||||
if sym_info:
|
if sym_info:
|
||||||
is_func = getattr(sym_info, 'IsFunction', False)
|
is_func = sym_info.IsFunction
|
||||||
sym_is_variadic = getattr(sym_info, 'IsVariadic', False)
|
sym_is_variadic = sym_info.IsVariadic
|
||||||
if is_func:
|
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:
|
if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType:
|
||||||
ret_type = ret_type_info.ToLLVM(Gen)
|
ret_type = ret_type_info.ToLLVM(Gen)
|
||||||
else:
|
else:
|
||||||
ret_type = Gen._CType2LLVM('i32', False)
|
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):
|
if isinstance(ret_type, ir.VoidType):
|
||||||
ret_type = ir.IntType(32)
|
ret_type = ir.IntType(32)
|
||||||
llvm_param_types = []
|
llvm_param_types = []
|
||||||
@@ -1830,7 +1830,7 @@ class ExprCallHandle(BaseHandle):
|
|||||||
if ClassName:
|
if ClassName:
|
||||||
SymKey = f'{ClassName}.{MethodName}'
|
SymKey = f'{ClassName}.{MethodName}'
|
||||||
SymInfo = self.Trans.SymbolTable.get(SymKey)
|
SymInfo = self.Trans.SymbolTable.get(SymKey)
|
||||||
if SymInfo and hasattr(SymInfo, 'MetaList'):
|
if SymInfo and SymInfo.MetaList:
|
||||||
if FuncMeta.STATIC_METHOD in SymInfo.MetaList:
|
if FuncMeta.STATIC_METHOD in SymInfo.MetaList:
|
||||||
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
|
return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName)
|
||||||
if FuncMeta.CLASS_METHOD in SymInfo.MetaList:
|
if FuncMeta.CLASS_METHOD in SymInfo.MetaList:
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class IfHandle(BaseHandle):
|
|||||||
return True
|
return True
|
||||||
if name in self.Trans.SymbolTable:
|
if name in self.Trans.SymbolTable:
|
||||||
info = self.Trans.SymbolTable[name]
|
info = self.Trans.SymbolTable[name]
|
||||||
if getattr(info, 'IsDefine', False):
|
if info.IsDefine:
|
||||||
return True
|
return True
|
||||||
platform_macros = self._get_platform_macros()
|
platform_macros = self._get_platform_macros()
|
||||||
return name in platform_macros
|
return name in platform_macros
|
||||||
@@ -86,8 +86,8 @@ class IfHandle(BaseHandle):
|
|||||||
return val
|
return val
|
||||||
if name in self.Trans.SymbolTable:
|
if name in self.Trans.SymbolTable:
|
||||||
info = self.Trans.SymbolTable[name]
|
info = self.Trans.SymbolTable[name]
|
||||||
if getattr(info, 'IsDefine', False):
|
if info.IsDefine:
|
||||||
val = getattr(info, 'DefineValue', 0)
|
val = info.DefineValue
|
||||||
if isinstance(val, (int, float)):
|
if isinstance(val, (int, float)):
|
||||||
return val
|
return val
|
||||||
platform_macros = self._get_platform_macros()
|
platform_macros = self._get_platform_macros()
|
||||||
@@ -129,118 +129,21 @@ class IfHandle(BaseHandle):
|
|||||||
return macros
|
return macros
|
||||||
|
|
||||||
def _eval_const_expr(self, node):
|
def _eval_const_expr(self, node):
|
||||||
if isinstance(node, ast.Constant):
|
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
|
||||||
val = node.value
|
Gen = self.Trans.LlvmGen
|
||||||
if isinstance(val, bool):
|
ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable)
|
||||||
return 1 if val else 0
|
result = ConstEvaluator.eval_full(node, ctx)
|
||||||
if isinstance(val, int):
|
if result is None:
|
||||||
return val
|
# 保留 CIf 嵌套调用处理(HandlesIf 特有逻辑)
|
||||||
if isinstance(val, float):
|
if isinstance(node, ast.Call) and self._is_cif_call(node):
|
||||||
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):
|
|
||||||
return self._evaluate_cif_condition(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):
|
def _HandleIfLlvm(self, Node):
|
||||||
Gen = self.Trans.LlvmGen
|
Gen = self.Trans.LlvmGen
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ class ImportHandle(BaseHandle):
|
|||||||
if not asname or asname == name:
|
if not asname or asname == name:
|
||||||
# Check if this name is a CDefine constant in SymbolTable
|
# Check if this name is a CDefine constant in SymbolTable
|
||||||
sym_info = self.Trans.SymbolTable.get(name)
|
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', {})
|
define_constants = vars(Gen).setdefault('_define_constants', {})
|
||||||
if name not in define_constants:
|
if name not in define_constants:
|
||||||
define_constants[name] = sym_info.DefineValue
|
define_constants[name] = sym_info.DefineValue
|
||||||
# Also check with module prefix
|
# Also check with module prefix
|
||||||
for prefix_key in [f"{module}.{name}", name]:
|
for prefix_key in [f"{module}.{name}", name]:
|
||||||
sym_info2 = self.Trans.SymbolTable.get(prefix_key)
|
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', {})
|
define_constants = vars(Gen).setdefault('_define_constants', {})
|
||||||
if name not in define_constants:
|
if name not in define_constants:
|
||||||
define_constants[name] = sym_info2.DefineValue
|
define_constants[name] = sym_info2.DefineValue
|
||||||
@@ -893,7 +893,7 @@ class ImportHandle(BaseHandle):
|
|||||||
elif isinstance(value_node, ast.Name):
|
elif isinstance(value_node, ast.Name):
|
||||||
if value_node.id in getattr(self.Trans, 'SymbolTable', {}):
|
if value_node.id in getattr(self.Trans, 'SymbolTable', {}):
|
||||||
info = self.Trans.SymbolTable[value_node.id]
|
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
|
return info.DefineValue
|
||||||
elif isinstance(value_node, ast.Call):
|
elif isinstance(value_node, ast.Call):
|
||||||
if isinstance(value_node.func, ast.Attribute):
|
if isinstance(value_node.func, ast.Attribute):
|
||||||
@@ -1020,7 +1020,7 @@ class ImportHandle(BaseHandle):
|
|||||||
ParamTypes = []
|
ParamTypes = []
|
||||||
is_method = is_class_method or '.__' in FuncName
|
is_method = is_class_method or '.__' in FuncName
|
||||||
class_name_for_method = FuncName.split('.')[0] if '.' in FuncName else None
|
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):
|
for i, Arg in enumerate(Node.args.args):
|
||||||
if i == 0 and is_method:
|
if i == 0 and is_method:
|
||||||
# self parameter of a method should always be a pointer to the struct
|
# self parameter of a method should always be a pointer to the struct
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class MatchHandle(BaseHandle):
|
|||||||
VarName = Node.subject.id
|
VarName = Node.subject.id
|
||||||
if VarName in self.Trans.SymbolTable:
|
if VarName in self.Trans.SymbolTable:
|
||||||
TypeInfo = self.Trans.SymbolTable[VarName]
|
TypeInfo = self.Trans.SymbolTable[VarName]
|
||||||
if getattr(TypeInfo, 'IsRenum', False):
|
if TypeInfo.IsRenum:
|
||||||
IsRenumMatch = True
|
IsRenumMatch = True
|
||||||
RenumName = TypeInfo.Name
|
RenumName = TypeInfo.Name
|
||||||
SubjectPtr = Gen._loadVar(VarName)
|
SubjectPtr = Gen._loadVar(VarName)
|
||||||
@@ -37,11 +37,11 @@ class MatchHandle(BaseHandle):
|
|||||||
VariantName = cls_node.attr
|
VariantName = cls_node.attr
|
||||||
if VariantName and VariantName in self.Trans.SymbolTable:
|
if VariantName and VariantName in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[VariantName]
|
SymInfo = self.Trans.SymbolTable[VariantName]
|
||||||
if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None):
|
if SymInfo.IsEnumMember and SymInfo.EnumName:
|
||||||
EnumName = SymInfo.EnumName
|
EnumName = SymInfo.EnumName
|
||||||
if EnumName in self.Trans.SymbolTable:
|
if EnumName in self.Trans.SymbolTable:
|
||||||
EnumInfo = self.Trans.SymbolTable[EnumName]
|
EnumInfo = self.Trans.SymbolTable[EnumName]
|
||||||
if getattr(EnumInfo, 'IsRenum', False):
|
if EnumInfo.IsRenum:
|
||||||
IsRenumMatch = True
|
IsRenumMatch = True
|
||||||
RenumName = EnumName
|
RenumName = EnumName
|
||||||
if SubjectPtr is None:
|
if SubjectPtr is None:
|
||||||
@@ -209,7 +209,7 @@ class MatchHandle(BaseHandle):
|
|||||||
TagValue = None
|
TagValue = None
|
||||||
if VariantName in self.Trans.SymbolTable:
|
if VariantName in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[VariantName]
|
SymInfo = self.Trans.SymbolTable[VariantName]
|
||||||
if getattr(SymInfo, 'IsEnumMember', False):
|
if SymInfo.IsEnumMember:
|
||||||
TagValue = SymInfo.value
|
TagValue = SymInfo.value
|
||||||
if TagValue is not None:
|
if TagValue is not None:
|
||||||
CaseValues.append(ir.Constant(ir.IntType(32), TagValue))
|
CaseValues.append(ir.Constant(ir.IntType(32), TagValue))
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ class HandlesTypeMerge(BaseHandle):
|
|||||||
# 也尝试在符号表中查找模块别名
|
# 也尝试在符号表中查找模块别名
|
||||||
if ModulePath in self.Trans.SymbolTable:
|
if ModulePath in self.Trans.SymbolTable:
|
||||||
entry = self.Trans.SymbolTable[ModulePath]
|
entry = self.Trans.SymbolTable[ModulePath]
|
||||||
if isinstance(entry, CTypeInfo) and getattr(entry, 'IsModuleAlias', False):
|
if isinstance(entry, CTypeInfo) and entry.IsModuleAlias:
|
||||||
resolved = getattr(entry, 'ResolvedModule', None)
|
resolved = entry.ResolvedModule
|
||||||
if resolved:
|
if resolved:
|
||||||
ModulePath = resolved
|
ModulePath = resolved
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class WithHandle(BaseHandle):
|
|||||||
if ClassName and ClassName not in Gen.structs:
|
if ClassName and ClassName not in Gen.structs:
|
||||||
if ClassName in self.Trans.SymbolTable:
|
if ClassName in self.Trans.SymbolTable:
|
||||||
SymInfo = self.Trans.SymbolTable[ClassName]
|
SymInfo = self.Trans.SymbolTable[ClassName]
|
||||||
if getattr(SymInfo, 'IsStruct', False) or getattr(SymInfo, 'IsRenum', False):
|
if SymInfo.IsStruct or SymInfo.IsRenum:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
ClassName = None
|
ClassName = None
|
||||||
|
|||||||
@@ -173,28 +173,28 @@ class BaseGenMixin:
|
|||||||
return ir.IntType(8)
|
return ir.IntType(8)
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable:
|
||||||
Entry = self.SymbolTable[clean_name]
|
Entry = self.SymbolTable[clean_name]
|
||||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
if Entry.IsTypedef:
|
||||||
resolved_str = self._resolve_typedef(clean_name)
|
resolved_str = self._resolve_typedef(clean_name)
|
||||||
if resolved_str != clean_name:
|
if resolved_str != clean_name:
|
||||||
return self._type_str_to_llvm(resolved_str)
|
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
|
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)
|
resolved = self._resolve_ctype_to_str(Entry)
|
||||||
if resolved:
|
if resolved:
|
||||||
return self._type_str_to_llvm(resolved)
|
return self._type_str_to_llvm(resolved)
|
||||||
if hasattr(Entry, 'IsRenum') and Entry.IsRenum:
|
if Entry.IsRenum:
|
||||||
if clean_name in self.structs:
|
if clean_name in self.structs:
|
||||||
return self.structs[clean_name]
|
return self.structs[clean_name]
|
||||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
if Entry.IsEnum:
|
||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
if Entry.IsExceptionClass:
|
||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
if hasattr(Entry, 'IsFunction') and Entry.IsFunction:
|
if Entry.IsFunction:
|
||||||
return ir.PointerType(ir.IntType(8))
|
return ir.PointerType(ir.IntType(8))
|
||||||
if hasattr(Entry, 'IsVariable') and Entry.IsVariable:
|
if Entry.IsVariable:
|
||||||
return ir.PointerType(ir.IntType(8))
|
return ir.PointerType(ir.IntType(8))
|
||||||
if hasattr(Entry, 'BaseType'):
|
if Entry.BaseType:
|
||||||
from lib.includes import t as _t
|
from lib.includes import t as _t
|
||||||
if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
|
if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum):
|
||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
@@ -237,17 +237,17 @@ class BaseGenMixin:
|
|||||||
# 2. 再查 SymbolTable(用户定义的 typedef)
|
# 2. 再查 SymbolTable(用户定义的 typedef)
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable:
|
||||||
Entry = self.SymbolTable[name]
|
Entry = self.SymbolTable[name]
|
||||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
if Entry.IsTypedef:
|
||||||
if hasattr(Entry, 'BaseType') and Entry.BaseType:
|
if Entry.BaseType:
|
||||||
from lib.includes import t as _t
|
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)
|
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():
|
if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
|
||||||
return int(llvm_str[1:])
|
return int(llvm_str[1:])
|
||||||
if hasattr(Entry, 'OriginalType') and Entry.OriginalType:
|
if Entry.OriginalType:
|
||||||
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo
|
from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo
|
||||||
if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType:
|
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)
|
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():
|
if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit():
|
||||||
return int(llvm_str[1:])
|
return int(llvm_str[1:])
|
||||||
|
|||||||
@@ -207,13 +207,13 @@ class StructGenMixin:
|
|||||||
is_packed = ClassName in self.class_packed
|
is_packed = ClassName in self.class_packed
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
||||||
Entry = self.SymbolTable[ClassName]
|
Entry = self.SymbolTable[ClassName]
|
||||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
if Entry.IsExceptionClass:
|
||||||
continue
|
continue
|
||||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
if Entry.IsEnum:
|
||||||
if not getattr(Entry, 'IsRenum', False):
|
if not Entry.IsRenum:
|
||||||
continue
|
continue
|
||||||
if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
if Entry.IsTypedef:
|
||||||
if hasattr(Entry, 'BaseType') and Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
|
if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)):
|
||||||
import lib.includes.t as _t
|
import lib.includes.t as _t
|
||||||
if not isinstance(Entry.BaseType, (_t._CTypedef,)):
|
if not isinstance(Entry.BaseType, (_t._CTypedef,)):
|
||||||
continue
|
continue
|
||||||
@@ -304,10 +304,10 @@ class StructGenMixin:
|
|||||||
for ClassName in all_classes:
|
for ClassName in all_classes:
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable:
|
||||||
Entry = self.SymbolTable[ClassName]
|
Entry = self.SymbolTable[ClassName]
|
||||||
if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass:
|
if Entry.IsExceptionClass:
|
||||||
continue
|
continue
|
||||||
if hasattr(Entry, 'IsEnum') and Entry.IsEnum:
|
if Entry.IsEnum:
|
||||||
if not getattr(Entry, 'IsRenum', False):
|
if not Entry.IsRenum:
|
||||||
continue
|
continue
|
||||||
existing_st = self.structs.get(ClassName)
|
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:
|
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):
|
if isinstance(BaseType, _t.CDefine):
|
||||||
# Use 64-bit type if the define value exceeds 32-bit range
|
# 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:
|
if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF:
|
||||||
return ir.IntType(64)
|
return ir.IntType(64)
|
||||||
return ir.IntType(32)
|
return ir.IntType(32)
|
||||||
@@ -180,8 +180,8 @@ class TypeConvertMixin:
|
|||||||
if OriginalType:
|
if OriginalType:
|
||||||
current = OriginalType
|
current = OriginalType
|
||||||
continue
|
continue
|
||||||
elif hasattr(Entry, 'IsTypedef') and Entry.IsTypedef:
|
elif Entry.IsTypedef:
|
||||||
if hasattr(Entry, 'OriginalType') and Entry.OriginalType:
|
if Entry.OriginalType:
|
||||||
if isinstance(Entry.OriginalType, _CTypeInfo):
|
if isinstance(Entry.OriginalType, _CTypeInfo):
|
||||||
if Entry.OriginalType.IsFuncPtr:
|
if Entry.OriginalType.IsFuncPtr:
|
||||||
return 'Callable'
|
return 'Callable'
|
||||||
@@ -189,9 +189,9 @@ class TypeConvertMixin:
|
|||||||
elif isinstance(Entry.OriginalType, str):
|
elif isinstance(Entry.OriginalType, str):
|
||||||
current = Entry.OriginalType
|
current = Entry.OriginalType
|
||||||
continue
|
continue
|
||||||
if hasattr(Entry, 'BaseType') and Entry.BaseType:
|
if Entry.BaseType:
|
||||||
from lib.includes import t as _t
|
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)
|
resolved = self._resolve_ctype_to_str(Entry)
|
||||||
if resolved and resolved != current:
|
if resolved and resolved != current:
|
||||||
current = resolved
|
current = resolved
|
||||||
@@ -396,24 +396,24 @@ class TypeConvertMixin:
|
|||||||
return basic_stripped
|
return basic_stripped
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable:
|
||||||
_Entry = self.SymbolTable[type_str]
|
_Entry = self.SymbolTable[type_str]
|
||||||
if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef:
|
if _Entry.IsTypedef:
|
||||||
resolved_str = self._resolve_typedef(type_str)
|
resolved_str = self._resolve_typedef(type_str)
|
||||||
if resolved_str != type_str:
|
if resolved_str != type_str:
|
||||||
return self._type_str_to_llvm(resolved_str, IsPtr)
|
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
|
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)
|
resolved = self._resolve_ctype_to_str(_Entry)
|
||||||
if resolved:
|
if resolved:
|
||||||
return self._type_str_to_llvm(resolved, IsPtr)
|
return self._type_str_to_llvm(resolved, IsPtr)
|
||||||
if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum:
|
if _Entry.IsRenum:
|
||||||
if type_str in self.structs:
|
if type_str in self.structs:
|
||||||
return self.structs[type_str]
|
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))
|
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))
|
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
|
from lib.includes import t as _t
|
||||||
if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
|
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))
|
return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32))
|
||||||
@@ -431,24 +431,24 @@ class TypeConvertMixin:
|
|||||||
return basic_last
|
return basic_last
|
||||||
if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable:
|
if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable:
|
||||||
_Entry = self.SymbolTable[LastPart]
|
_Entry = self.SymbolTable[LastPart]
|
||||||
if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef:
|
if _Entry.IsTypedef:
|
||||||
resolved_str = self._resolve_typedef(LastPart)
|
resolved_str = self._resolve_typedef(LastPart)
|
||||||
if resolved_str != LastPart:
|
if resolved_str != LastPart:
|
||||||
return self._type_str_to_llvm(resolved_str, IsPtr)
|
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
|
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)
|
resolved = self._resolve_ctype_to_str(_Entry)
|
||||||
if resolved:
|
if resolved:
|
||||||
return self._type_str_to_llvm(resolved, IsPtr)
|
return self._type_str_to_llvm(resolved, IsPtr)
|
||||||
if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum:
|
if _Entry.IsRenum:
|
||||||
if LastPart in self.structs:
|
if LastPart in self.structs:
|
||||||
return self.structs[LastPart]
|
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))
|
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))
|
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
|
from lib.includes import t as _t
|
||||||
if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum:
|
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))
|
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}')
|
orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}')
|
||||||
elif orig_entry.get('type') == 'enum':
|
elif orig_entry.get('type') == 'enum':
|
||||||
orig_type_str = f'enum {original_name}'
|
orig_type_str = f'enum {original_name}'
|
||||||
elif hasattr(orig_entry, 'IsTypedef') and orig_entry.IsTypedef:
|
elif orig_entry.IsTypedef:
|
||||||
orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}')
|
orig_type_str = orig_entry.OriginalType or f'struct {original_name}'
|
||||||
elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum:
|
elif orig_entry.IsEnum:
|
||||||
orig_type_str = f'enum {original_name}'
|
orig_type_str = f'enum {original_name}'
|
||||||
TypedefNode.OriginalType = orig_type_str
|
TypedefNode.OriginalType = orig_type_str
|
||||||
TypedefNode.set('source', 'annotation_module')
|
TypedefNode.set('source', 'annotation_module')
|
||||||
|
|||||||
@@ -112,42 +112,8 @@ class ConstEvalMixin:
|
|||||||
return self._try_eval_const_expr(node, Gen)
|
return self._try_eval_const_expr(node, Gen)
|
||||||
|
|
||||||
def _try_eval_const_expr(self, node, Gen):
|
def _try_eval_const_expr(self, node, Gen):
|
||||||
import ast
|
from lib.core.ConstEvaluator import ConstEvaluator
|
||||||
if isinstance(node, ast.Constant):
|
return ConstEvaluator.eval_with_symtab(node, self.SymbolTable)
|
||||||
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
|
|
||||||
|
|
||||||
def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen):
|
def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen):
|
||||||
from lib.core.Handles.HandlesAssign import AssignHandle
|
from lib.core.Handles.HandlesAssign import AssignHandle
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ FIELD_ROUTES = {
|
|||||||
'ArrayPtr': ('ts', 'array_ptr'),
|
'ArrayPtr': ('ts', 'array_ptr'),
|
||||||
'IsState': ('ts', 'is_state'),
|
'IsState': ('ts', 'is_state'),
|
||||||
'OriginalType': ('ts', 'original_type'),
|
'OriginalType': ('ts', 'original_type'),
|
||||||
|
'IsSigned': ('ts', 'is_signed'),
|
||||||
|
|
||||||
# --- SymbolMeta 字段 ---
|
# --- SymbolMeta 字段 ---
|
||||||
'Name': ('sm', 'name'),
|
'Name': ('sm', 'name'),
|
||||||
@@ -87,6 +88,8 @@ FIELD_ROUTES = {
|
|||||||
'IsModuleAlias': ('sm', 'is_module_alias'),
|
'IsModuleAlias': ('sm', 'is_module_alias'),
|
||||||
'ResolvedModule': ('sm', 'resolved_module'),
|
'ResolvedModule': ('sm', 'resolved_module'),
|
||||||
'DefineValue': ('sm', 'define_value'),
|
'DefineValue': ('sm', 'define_value'),
|
||||||
|
'EnumName': ('sm', 'enum_name'),
|
||||||
|
'value': ('sm', 'enum_value'),
|
||||||
|
|
||||||
# --- _kind_flags(独立 bool,存储在 SymbolMeta._kind_flags)---
|
# --- _kind_flags(独立 bool,存储在 SymbolMeta._kind_flags)---
|
||||||
'IsStruct': ('kf', 'IsStruct'),
|
'IsStruct': ('kf', 'IsStruct'),
|
||||||
@@ -127,6 +130,7 @@ class TypeSpec:
|
|||||||
'is_array_ptr', 'array_ptr',
|
'is_array_ptr', 'array_ptr',
|
||||||
'is_state',
|
'is_state',
|
||||||
'original_type',
|
'original_type',
|
||||||
|
'is_signed',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -150,6 +154,7 @@ class TypeSpec:
|
|||||||
self.array_ptr: Any = None # CTypeInfo
|
self.array_ptr: Any = None # CTypeInfo
|
||||||
self.is_state: bool = False
|
self.is_state: bool = False
|
||||||
self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型)
|
self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型)
|
||||||
|
self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base_type(self) -> Any:
|
def base_type(self) -> Any:
|
||||||
@@ -203,6 +208,7 @@ class TypeSpec:
|
|||||||
new.array_ptr = self.array_ptr
|
new.array_ptr = self.array_ptr
|
||||||
new.is_state = self.is_state
|
new.is_state = self.is_state
|
||||||
new.original_type = self.original_type
|
new.original_type = self.original_type
|
||||||
|
new.is_signed = self.is_signed
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
@@ -222,6 +228,7 @@ class SymbolMeta:
|
|||||||
'members',
|
'members',
|
||||||
'is_cpython_object', 'is_packed',
|
'is_cpython_object', 'is_packed',
|
||||||
'define_value',
|
'define_value',
|
||||||
|
'enum_name', 'enum_value',
|
||||||
'is_inline', 'inline_body', 'inline_params',
|
'is_inline', 'inline_body', 'inline_params',
|
||||||
'is_anonymous',
|
'is_anonymous',
|
||||||
'renum_variants',
|
'renum_variants',
|
||||||
@@ -241,6 +248,8 @@ class SymbolMeta:
|
|||||||
self.is_cpython_object: bool = False
|
self.is_cpython_object: bool = False
|
||||||
self.is_packed: bool = False
|
self.is_packed: bool = False
|
||||||
self.define_value: Any = None
|
self.define_value: Any = None
|
||||||
|
self.enum_name: str = "" # 枚举成员所属的枚举类名
|
||||||
|
self.enum_value: Any = None # 枚举成员的值
|
||||||
self.is_inline: bool = False
|
self.is_inline: bool = False
|
||||||
self.inline_body: list | None = None
|
self.inline_body: list | None = None
|
||||||
self.inline_params: 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_cpython_object = self.is_cpython_object
|
||||||
new.is_packed = self.is_packed
|
new.is_packed = self.is_packed
|
||||||
new.define_value = self.define_value
|
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.is_inline = self.is_inline
|
||||||
new.inline_body = self.inline_body
|
new.inline_body = self.inline_body
|
||||||
new.inline_params = list(self.inline_params) if self.inline_params else None
|
new.inline_params = list(self.inline_params) if self.inline_params else None
|
||||||
|
|||||||
Reference in New Issue
Block a user