Files
TransPyC/lib/core/Translator/BaseTranslator.py
T
TermiNexus 5680592f37 feat(tpc): 新增 --func-hotspot 函数热点统计,Ctrl+C 时落盘
启用后为每个函数定义生成 internal i64 计数器并在入口递增;各模块 Ctrl+C 处理器以追加方式写最终文件(含 main 的模块启动时清空一次),经 llvm.global_ctors 自注册;未传参数时零影响。
2026-09-13 17:50:01 +08:00

165 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import vast as ast
from typing import Any, Callable, Dict, TYPE_CHECKING
from lib.core.Exportable import Exportable
if TYPE_CHECKING:
import llvmlite.ir as ir
from lib.core.Handles import (
IfHandle, ForHandle, WhileHandle,
AnnAssignHandle,
HandlesTypeMerge, ExprHandle, BodyHandle,
ReturnHandle, AssignHandle, AugAssignHandle, DeleteHandle,
WithHandle, TryHandle, AssertHandle, RaiseHandle, MatchHandle,
ExprUtils, ExprOpsHandle, ExprAttrHandle, ExprBuiltinHandle,
ExprAsmHandle, ExprFormatHandle, ExprLambdaHandle, ExprCallHandle,
CSpecialCallHandle, TSpecialCallHandle,
ClassHandle,
FunctionHandle,
ImportHandle,
AsyncFunctionHandle
)
from lib.core.Handles.HandlesBase import CTypeInfo
from lib.core.SymbolTable import SymbolTable
from lib.core.SymbolNode import SymbolNode
from lib.constants.config import mode as _ConfigMode
from lib.core.VLogger import get_logger as _vlog
def _StrictLog(logger: Callable[[str], None], msg: str) -> None:
"""在 strict 模式下记录异常日志"""
if _ConfigMode == "strict":
logger(msg)
class BaseTranslatorMixin:
"""代码转换器基础 Mixin
提供 __init__、日志、调试输出与表达式处理等基础能力。
"""
def __init__(self) -> None:
self.VarScopes: list[Dict[str, SymbolNode]] = [{}] # 跟踪变量作用域,第一个是全局作用域
self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型
self.CurrentCReturnTypes: list[CTypeInfo] | None = None # 当前函数的 CReturn 类型列表
self._CurrentCpythonObjectClass: str | None = None # 当前正在处理的 CPython 对象类名
self.FunctionDefCache: dict = {} # 函数定义缓存
self.OriginalLines: list[str] = [] # 原始代码行
self.Content: str = ''
self.DebugFile: str | None = None # 调试输出文件路径
self.IsHeader: bool = False # 是否生成头文件(仅处理定义、宏、导入等,忽略函数体)
self.AnnotationModules: set[str] = set() # 注解模块集合,用于识别类型定义模块
self.Warnings: list[str] = [] # 警告日志
self._ErrorStack: list[tuple[str, str, str]] = [] # 错误栈,按顺序收集错误位置
self.Errors: list[dict[str, str | None]] = [] # 错误日志
self.SliceCount: int = 0 # 切片计数
self.SliceInfos: list = [] # 切片信息列表
self.SliceLevel: int = 3 # 切片优化级别
self.GeneratedTypes: set[str] = set() # 在当前代码中生成的类型(struct/typedef)
self.EmbeddedAssignments: dict[str, list] = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量
self.TypedefAssignments: dict[str, list] = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量
self.ChainAssignmentArrays: list = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...]
self.tree: ast.AST | None = None # 保存解析后的 AST 树
self.LibraryPaths: list[str] = ['.'] # 库搜索路径列表,默认包含当前目录
self.InClass: bool = False # 是否正在处理 class 定义
self._UserTypeModules: dict = {}
self._source_module_sig_files: dict = {}
self._global_function_default_args: dict = {}
self._global_function_param_names: dict = {}
self.exception_registry: dict = {}
self.exception_parents: dict = {}
self._next_exception_code: int = 100
# 以下属性原先在外部懒注入,此处显式初始化以避免 hasattr/getattr 动态反射
self.config: Any = None
self._ImportedModules: set[str] | None = None
self._t_c_imported_names: dict = {}
# 函数热点统计(--func-hotspot):None=未启用(零影响),否则为计数器落盘文件路径
self.FuncHotspotFile: str | None = None
# 注册策略:False=种子 CLI 单模块(main 入口注册);True=Projectrans 多模块
# (每模块 @llvm.global_ctors 自注册,见 BaseGen._InstallFuncHotspotModuleLocal)
self.FuncHotspotModuleLocal: bool = False
# 导出表
self.Exportable = Exportable(filename='')
self.SymbolTable = SymbolTable(self)
self.IfHandler = IfHandle(self)
self.ForHandler = ForHandle(self)
self.WhileHandler = WhileHandle(self)
self.AnnAssignHandler = AnnAssignHandle(self)
self.TypeMergeHandler = HandlesTypeMerge(self)
self.ExprHandler = ExprHandle(self)
self.ExprUtils = ExprUtils(self)
self.ExprOpsHandle = ExprOpsHandle(self)
self.ExprAttrHandle = ExprAttrHandle(self)
self.ExprBuiltinHandle = ExprBuiltinHandle(self)
self.ExprAsmHandle = ExprAsmHandle(self)
self.ExprFormatHandle = ExprFormatHandle(self)
self.ExprLambdaHandle = ExprLambdaHandle(self)
self.ExprCallHandle = ExprCallHandle(self)
self.CSpecialCallHandle = CSpecialCallHandle(self)
self.TSpecialCallHandle = TSpecialCallHandle(self)
self.ClassHandler = ClassHandle(self)
self.FunctionHandler = FunctionHandle(self)
self.ImportHandler = ImportHandle(self)
self.BodyHandler = BodyHandle(self)
self.ReturnHandler = ReturnHandle(self)
self.AssignHandler = AssignHandle(self)
self.AugAssignHandler = AugAssignHandle(self)
self.DeleteHandler = DeleteHandle(self)
self.WithHandler = WithHandle(self)
self.TryHandler = TryHandle(self)
self.AssertHandler = AssertHandle(self)
self.RaiseHandler = RaiseHandle(self)
self.MatchHandler = MatchHandle(self)
self.AsyncHandler = AsyncFunctionHandle(self)
def LogWarning(self, message: str, LineNum: int | None = None) -> None:
"""记录警告
Args:
message: 警告消息
LineNum: 行号(可选)
"""
warning = f"Warning: {message}"
if LineNum is not None:
warning += f" (line {LineNum})"
self.Warnings.append(warning)
def LogError(self, message: str, LineNum: int | None = None) -> None:
"""记录错误
Args:
message: 错误消息
LineNum: 行号
"""
_vlog().error(message)
entry: dict[str, str | int | None] = {'message': message, 'line': LineNum}
self.Errors.append(entry)
# 检查 config 中是否有 debug 文件
DebugFile: str | None = None
if hasattr(self, 'config') and self.config:
DebugFile = getattr(self.config, 'debug', None)
if DebugFile:
with open(DebugFile, 'a', encoding='utf-8') as f:
LineInfo: str = f' line {LineNum}' if LineNum else ''
f.write(f'[ERROR]{LineInfo}: {message}\n')
def SetDebugFile(self, FilePath: str) -> None:
"""设置调试输出文件"""
self.DebugFile = FilePath
def DebugPrint(self, *args: Any, **kwargs: Any) -> None:
"""输出调试信息到文件"""
if self.DebugFile:
with open(self.DebugFile, 'a', encoding='utf-8') as f:
print(*args, file=f, **kwargs)
def HandleExpr(self, Node: ast.AST, UseSingleQuote: bool = False, VarType: ir.Type | None = None) -> Any:
return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType)