refactor(gen): TypeGenMixin 拆 5 组(Base/CDef/CType/Resolve/Err,2643→44 行)
This commit is contained in:
1 parent
65cf71ff7e
commit
81d4ff3ac4
8 files changed
+2746
-2606
No files matched your search
@@ -4,6 +4,11 @@ import memhub
|
||||
import llvmlite
|
||||
import lib.core.Gen.BaseGenMixin as BaseGenMixin
|
||||
import lib.core.Gen.TypeGenMixin as TypeGenMixin
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
import lib.core.Gen.TypeGenCDef as TypeGenCDef
|
||||
import lib.core.Gen.TypeGenCType as TypeGenCType
|
||||
import lib.core.Gen.TypeGenResolve as TypeGenResolve
|
||||
import lib.core.Gen.TypeGenErr as TypeGenErr
|
||||
import lib.core.Gen.StructGenMixin as StructGenMixin
|
||||
import lib.core.Gen.ExprGenMixin as ExprGenMixin
|
||||
import lib.core.Gen.CallGenMixin as CallGenMixin
|
||||
@@ -45,6 +50,9 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
|
||||
TypeGenBase.TypeGenBase, TypeGenCDef.TypeGenCDef,
|
||||
TypeGenCType.TypeGenCType, TypeGenResolve.TypeGenResolve,
|
||||
TypeGenErr.TypeGenErr,
|
||||
StructGenMixin.StructGenMixin, ExprGenMixin.ExprGenMixin,
|
||||
CallGenMixin.CallGenMixin, CallGenBase.CallGenBase,
|
||||
CallGenLeafKit.CallGenLeafKit, CallGenCBuiltin.CallGenCBuiltin,
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeGenBase - TypeGenMixin 拆分(阶段 D):字段 + InitTypeGen + trace/临时目录/generic 上下文
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenBase:
|
||||
"""字段 + InitTypeGen + trace/临时目录/generic 上下文"""
|
||||
|
||||
# --- 仿 Python Traceback 调用栈(原 _g_trace_frames/_g_trace_count) ---
|
||||
TraceFrames: HandlesType.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽)
|
||||
TraceCount: int
|
||||
|
||||
# --- 全局 temp_dir(原 _g_temp_dir) ---
|
||||
TempDir: str
|
||||
|
||||
# --- 全局泛型特化上下文(原 _g_generic_tp_names/_g_generic_type_args) ---
|
||||
GenericTpNames: list[str] | t.CPtr
|
||||
GenericTypeArgs: list[str] | t.CPtr
|
||||
# 嵌套安全栈:set_generic_context 压入外层值,clear_generic_context 弹出
|
||||
# 恢复(原单槽赋值:嵌套特化/泛型函数翻译退出时把外层上下文清成 None →
|
||||
# 外层方法体后续的 T 替换丢失 → T.__sizeof__() NameError,VectorGenericTest
|
||||
# 特化 Vector[int].__init__ 回归根因)。
|
||||
GenericCtxStack: t.CSizeT | t.CPtr # i64* 固定数组:每层 2 个槽(tp_names, type_args 指针)
|
||||
GenericCtxDepth: int
|
||||
|
||||
# --- 全局 CDefine 编译期常量表(原 _g_cdefine_*) ---
|
||||
CDefineNames: list[str] | t.CPtr
|
||||
CDefineValues: list[str] | t.CPtr
|
||||
CDefineDoubleFlags: list[int] | t.CPtr
|
||||
CDefineStrFlags: list[int] | t.CPtr # 1=字符串值(如 ZLIB_VERSION: t.CDefine = "1.3.2")
|
||||
CDefineIsDouble: int
|
||||
CDefineIsStr: int
|
||||
CDefineFound: int
|
||||
|
||||
# --- 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用) ---
|
||||
# 2026-08-14:跨模块 CDefine 查找(_lookup_cross_module_cdefine)结果缓存到
|
||||
# perm_pool,reset_to(mark2)/clear_cdefine_constants 不清除 → 跨文件复用,
|
||||
# CONST_INT 递归查找只做一次(NewAstTest OOM 根因)。
|
||||
XmodCdefNames: list[str] | t.CPtr
|
||||
XmodCdefValues: list[str] | t.CPtr
|
||||
XmodCdefDoubleFlags: list[int] | t.CPtr
|
||||
XmodCdefStrFlags: list[int] | t.CPtr
|
||||
|
||||
# --- 当前模块 SHA1(原 _g_current_module_sha1) ---
|
||||
CurrentModuleSha1: str
|
||||
|
||||
# --- 全局 CTypedef 表(原 _g_ctypedef_*) ---
|
||||
CTypedefNames: list[str] | t.CPtr
|
||||
CTypedefTypeStrs: list[str] | t.CPtr
|
||||
CTypedefFound: int
|
||||
CTypedefResolveDepth: int
|
||||
CTypedefVisiting: list[str] | t.CPtr
|
||||
|
||||
# --- 常量整数表达式计算成功标志(原 _g_const_eval_ok) ---
|
||||
ConstEvalOk: int
|
||||
|
||||
# --- 全局当前文件名(原 _g_current_file) ---
|
||||
CurrentFile: str
|
||||
def InitTypeGen(self) -> int:
|
||||
"""初始化类型 Mixin 字段(子类构造时内联调用,规避 NoVTable 继承符号不转发)"""
|
||||
if self is None:
|
||||
return 1
|
||||
self.TraceFrames = None
|
||||
self.TraceCount = 0
|
||||
self.TempDir = None
|
||||
self.GenericTpNames = None
|
||||
self.GenericTypeArgs = None
|
||||
self.GenericCtxStack = None
|
||||
self.GenericCtxDepth = 0
|
||||
self.CDefineNames = None
|
||||
self.CDefineValues = None
|
||||
self.CDefineDoubleFlags = None
|
||||
self.CDefineStrFlags = None
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
self.CDefineFound = 0
|
||||
self.XmodCdefNames = None
|
||||
self.XmodCdefValues = None
|
||||
self.XmodCdefDoubleFlags = None
|
||||
self.XmodCdefStrFlags = None
|
||||
self.CurrentModuleSha1 = None
|
||||
self.CTypedefNames = None
|
||||
self.CTypedefTypeStrs = None
|
||||
self.CTypedefFound = 0
|
||||
self.CTypedefResolveDepth = 0
|
||||
self.CTypedefVisiting = None
|
||||
self.ConstEvalOk = 0
|
||||
self.CurrentFile = None
|
||||
return 0
|
||||
# ============================================================
|
||||
# P2 迁移方法(函数体来自 HandlesType.vp,全局变量改 self.字段,
|
||||
# 同模块函数调用改 self.方法;签名与 HandlesType 原函数一致)
|
||||
# ============================================================
|
||||
|
||||
def _ensure_trace_init(self) -> int:
|
||||
"""确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)"""
|
||||
if self.TraceFrames is not None:
|
||||
return 1
|
||||
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
|
||||
self.TraceFrames = CompilerFactory.get_perm_pool().alloc(entry_size * TRACE_MAX)
|
||||
if self.TraceFrames is None:
|
||||
return 0
|
||||
string.memset(self.TraceFrames, 0, entry_size * TRACE_MAX)
|
||||
return 1
|
||||
def _get_trace_frame(self, i: int) -> HandlesType.TraceFrame | t.CPtr:
|
||||
"""获取第 i 个 TraceFrame 槽位"""
|
||||
if self.TraceFrames is None or i < 0 or i >= TRACE_MAX:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(self.TraceFrames) + i * entry_size
|
||||
return (HandlesType.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
|
||||
"""压入一个翻译上下文帧(进入新的翻译作用域时调用)"""
|
||||
if self._ensure_trace_init() == 0:
|
||||
return
|
||||
if self.TraceCount >= TRACE_MAX:
|
||||
return
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
if frame is None:
|
||||
return
|
||||
frame.file_name = file_name
|
||||
frame.lineno = lineno
|
||||
frame.col_start = col_start
|
||||
frame.col_end = col_end
|
||||
self.TraceCount += 1
|
||||
def pop_trace(self):
|
||||
"""弹出栈顶帧(退出翻译作用域时调用)"""
|
||||
if self.TraceCount <= 0:
|
||||
return
|
||||
self.TraceCount -= 1
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
frame.col_start = 0
|
||||
frame.col_end = 0
|
||||
def clear_trace(self):
|
||||
"""清空调用栈(每个文件翻译开始前调用)"""
|
||||
i: int
|
||||
for i in range(self.TraceCount):
|
||||
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(i)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
frame.col_start = 0
|
||||
frame.col_end = 0
|
||||
self.TraceCount = 0
|
||||
def set_temp_dir(self, temp_dir: str) -> None:
|
||||
"""设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)"""
|
||||
self.TempDir = temp_dir
|
||||
def get_temp_dir(self) -> str:
|
||||
"""获取全局 temp_dir"""
|
||||
return self.TempDir
|
||||
def set_current_module_sha1(self, sha1: str) -> None:
|
||||
"""设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)"""
|
||||
self.CurrentModuleSha1 = sha1
|
||||
def _dbg_check_ast_floats(self, mb: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr, tag: str):
|
||||
"""已移除调试插桩(占位保留签名,避免外部调用引用失败)"""
|
||||
pass
|
||||
def set_generic_context(self, tp_names: list[str] | t.CPtr,
|
||||
type_args: list[str] | t.CPtr):
|
||||
"""设置泛型特化上下文(进入泛型类方法体翻译时调用),嵌套安全
|
||||
|
||||
先压栈当前(外层)上下文,再设置新值。clear_generic_context 弹出恢复,
|
||||
避免嵌套特化/泛型函数翻译退出时清空外层上下文(T.__sizeof__() 回归根因)。
|
||||
"""
|
||||
if self.GenericCtxStack is None:
|
||||
self.GenericCtxStack = stdlib.malloc(8 * 2 * 32)
|
||||
if self.GenericCtxStack is None:
|
||||
self.GenericTpNames = tp_names
|
||||
self.GenericTypeArgs = type_args
|
||||
return
|
||||
self.GenericCtxDepth = 0
|
||||
if self.GenericCtxDepth < 32:
|
||||
self.GenericCtxStack[self.GenericCtxDepth * 2] = t.CSizeT(self.GenericTpNames)
|
||||
self.GenericCtxStack[self.GenericCtxDepth * 2 + 1] = t.CSizeT(self.GenericTypeArgs)
|
||||
self.GenericCtxDepth += 1
|
||||
self.GenericTpNames = tp_names
|
||||
self.GenericTypeArgs = type_args
|
||||
|
||||
def clear_generic_context(self):
|
||||
"""清除泛型特化上下文(离开泛型类方法体翻译时调用),恢复外层而非置 None"""
|
||||
if self.GenericCtxDepth > 0:
|
||||
self.GenericCtxDepth -= 1
|
||||
self.GenericTpNames = (list[str] | t.CPtr)(t.CVoid(
|
||||
self.GenericCtxStack[self.GenericCtxDepth * 2], t.CPtr))
|
||||
self.GenericTypeArgs = (list[str] | t.CPtr)(t.CVoid(
|
||||
self.GenericCtxStack[self.GenericCtxDepth * 2 + 1], t.CPtr))
|
||||
else:
|
||||
self.GenericTpNames = None
|
||||
self.GenericTypeArgs = None
|
||||
def resolve_generic_type_name(self, name: str) -> str:
|
||||
"""如果 name 是泛型类型参数,返回对应的具体类型名;否则返回 name 本身
|
||||
|
||||
用于表达式中的 T 替换(如 T.__sizeof__() → int.__sizeof__())
|
||||
"""
|
||||
if name is None:
|
||||
return name
|
||||
if self.GenericTpNames is not None and self.GenericTypeArgs is not None:
|
||||
rg_n: t.CSizeT = len(self.GenericTpNames)
|
||||
rg_i: t.CSizeT
|
||||
for rg_i in range(rg_n):
|
||||
rg_tpn: str = self.GenericTpNames.get(rg_i)
|
||||
if rg_tpn is not None and string.strcmp(name, rg_tpn) == 0:
|
||||
rg_ta: str = self.GenericTypeArgs.get(rg_i)
|
||||
if rg_ta is not None:
|
||||
return rg_ta
|
||||
return name
|
||||
@@ -0,0 +1,306 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# TypeGenCDef - TypeGenMixin 拆分(阶段 D):CDefine 编译期常量表(register/lookup/is/set/clear)
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenCDef(TypeGenBase.TypeGenBase):
|
||||
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
|
||||
|
||||
def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: t.CInt64T) -> None:
|
||||
"""注册 CDefine 编译期常量到本地表
|
||||
|
||||
值以十进制字符串存储(64 位 %lld)。大整数 CDefine(如
|
||||
sys.maxsize = 9223372036854775807)必须全精度保存,否则 %d 32 位截断
|
||||
成 -1(0xFFFFFFFF)→ 读回 4294967295(SysLibTest maxsize FAIL 根因)。
|
||||
0xFFFFFFFF 仍存为 "4294967295",常量生成端 const_int32 内部截断回 -1。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
viperlib.snprintf(val_buf, 32, "%lld", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: double) -> None:
|
||||
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
|
||||
|
||||
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
|
||||
"""
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
val_buf: str = pool.alloc(32)
|
||||
if val_buf is not None:
|
||||
# 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的
|
||||
# %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926,
|
||||
# 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。
|
||||
stdio.snprintf(val_buf, 32, "%.17g", value)
|
||||
self.CDefineValues.append(val_buf)
|
||||
else:
|
||||
self.CDefineValues.append("0")
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(1)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(0)
|
||||
# fail-fast:CDefine 值缓冲区分配失败必须终止编译,
|
||||
if val_buf is None:
|
||||
VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG")
|
||||
HandlesType.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError")
|
||||
def register_cdefine_string(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, value: str) -> None:
|
||||
"""注册字符串 CDefine 编译期常量(如 ZLIB_VERSION: t.CDefine = "1.3.2")
|
||||
|
||||
字符串值深拷贝到 pool(AST 节点的 str_val 可能被 pool 操作覆写,
|
||||
与浮点 CDefine 的恢复同理)。
|
||||
"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
if value is None:
|
||||
HandlesType.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError")
|
||||
return
|
||||
if self.CDefineNames is None:
|
||||
self.CDefineNames = list[str](pool, 64)
|
||||
self.CDefineValues = list[str](pool, 64)
|
||||
self.CDefineDoubleFlags = list[int](pool, 64)
|
||||
self.CDefineStrFlags = list[int](pool, 64)
|
||||
self.CDefineNames.append(name)
|
||||
vlen: t.CSizeT = string.strlen(value)
|
||||
vcopy: str = pool.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
HandlesType.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError")
|
||||
return
|
||||
string.strcpy(vcopy, value)
|
||||
self.CDefineValues.append(vcopy)
|
||||
if self.CDefineDoubleFlags is not None:
|
||||
self.CDefineDoubleFlags.append(0)
|
||||
if self.CDefineStrFlags is not None:
|
||||
self.CDefineStrFlags.append(1)
|
||||
# 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。
|
||||
# 跨模块字符串 CDefine 读回(_lookup_cross_module_cdefine 字符串分支只调
|
||||
# 本函数 + 尾部 set_cdefine_found,无 lookup_cdefine_string 回查)→ 若此处
|
||||
# 不设标志,属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 →
|
||||
# IR 生成 inttoptr i32 0(NULL)→ 运行时报 (null-) + strlen(NULL-) 崩溃
|
||||
# (test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)。
|
||||
self.CDefineIsStr = 1
|
||||
self.CDefineFound = 1
|
||||
# ============================================================
|
||||
# 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用)
|
||||
# ============================================================
|
||||
def register_xmod_cdefine(self, name: str, value_str: str,
|
||||
is_double: int, is_str: int) -> None:
|
||||
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(跨文件复用)
|
||||
|
||||
Args:
|
||||
name: CDefine 常量名(如 CONST_INT)
|
||||
value_str: 值文本(十进制/浮点/字符串)
|
||||
is_double: 1=浮点值
|
||||
is_str: 1=字符串值
|
||||
"""
|
||||
if name is None or value_str is None:
|
||||
return
|
||||
# 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定)
|
||||
if self.XmodCdefNames is not None:
|
||||
x_n: t.CSizeT = len(self.XmodCdefNames)
|
||||
x_i: t.CSizeT
|
||||
for x_i in range(x_n):
|
||||
x_nm: str = self.XmodCdefNames.get(x_i)
|
||||
if x_nm is not None and string.strcmp(x_nm, name) == 0:
|
||||
return
|
||||
perm: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
|
||||
if self.XmodCdefNames is None:
|
||||
self.XmodCdefNames = list[str](perm, 64)
|
||||
self.XmodCdefValues = list[str](perm, 64)
|
||||
self.XmodCdefDoubleFlags = list[int](perm, 64)
|
||||
self.XmodCdefStrFlags = list[int](perm, 64)
|
||||
# key/value 深拷贝到 perm_pool:入参(pool.alloc 临时缓冲)在
|
||||
# reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活
|
||||
klen: t.CSizeT = string.strlen(name)
|
||||
kcopy: str = perm.alloc(klen + 1)
|
||||
if kcopy is None:
|
||||
return
|
||||
string.strcpy(kcopy, name)
|
||||
vlen: t.CSizeT = string.strlen(value_str)
|
||||
vcopy: str = perm.alloc(vlen + 1)
|
||||
if vcopy is None:
|
||||
return
|
||||
string.strcpy(vcopy, value_str)
|
||||
self.XmodCdefNames.append(kcopy)
|
||||
self.XmodCdefValues.append(vcopy)
|
||||
if self.XmodCdefDoubleFlags is not None:
|
||||
self.XmodCdefDoubleFlags.append(is_double)
|
||||
if self.XmodCdefStrFlags is not None:
|
||||
self.XmodCdefStrFlags.append(is_str)
|
||||
def lookup_xmod_cdefine(self, name: str) -> str:
|
||||
"""查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志
|
||||
|
||||
Returns:
|
||||
值文本(命中),未命中返回 None
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if name is None or self.XmodCdefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.XmodCdefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.XmodCdefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.XmodCdefValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return val_str
|
||||
return None
|
||||
def lookup_cdefine_constant(self, name: str) -> t.CInt64T:
|
||||
"""查找 CDefine 编译期常量
|
||||
|
||||
返回找到的值(64 位,大整数 CDefine 如 sys.maxsize 全精度)。
|
||||
由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
|
||||
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
|
||||
调用方应在调用后检查 _g_cdefine_found。
|
||||
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
# 字符串 CDefine(如 ZLIB_VERSION="1.3.2"):整数查询路径
|
||||
# 标记 is_str,调用方改用 lookup_cdefine_string 取字符串。
|
||||
self.CDefineIsStr = 1
|
||||
return 0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
return string.atoll(val_str)
|
||||
return string.atoll(val_str)
|
||||
return 0
|
||||
def lookup_cdefine_double(self, name: str) -> double:
|
||||
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
|
||||
|
||||
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
|
||||
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return 0.0
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return 0.0
|
||||
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
|
||||
self.CDefineIsDouble = 1
|
||||
ret_d: double = string.atof(val_str)
|
||||
return ret_d
|
||||
ret_i2: double = double(string.atoll(val_str))
|
||||
return ret_i2
|
||||
return 0.0
|
||||
def lookup_cdefine_string(self, name: str) -> str:
|
||||
"""查找 CDefine 编译期字符串值(found=1 且 is_str=1 时有效)
|
||||
|
||||
返回的字符串指针位于 pool 内(当前模块生命周期内有效),
|
||||
调用方应尽快用于 create_global_string 拷贝到 LLVM 常量。
|
||||
"""
|
||||
self.CDefineFound = 0
|
||||
self.CDefineIsDouble = 0
|
||||
self.CDefineIsStr = 0
|
||||
if self.CDefineNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CDefineNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CDefineNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
val_str: str = self.CDefineValues.get(i)
|
||||
if val_str is not None:
|
||||
self.CDefineFound = 1
|
||||
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
|
||||
self.CDefineIsStr = 1
|
||||
return val_str
|
||||
return val_str
|
||||
return None
|
||||
def is_cdefine_str(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是字符串常量"""
|
||||
return self.CDefineIsStr
|
||||
def is_cdefine_double(self) -> int:
|
||||
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
|
||||
return self.CDefineIsDouble
|
||||
def is_cdefine_found(self) -> int:
|
||||
"""检查上次 lookup_cdefine_constant 是否找到值"""
|
||||
return self.CDefineFound
|
||||
def set_cdefine_found(self, val: int) -> None:
|
||||
"""设置 cdefine_found 标志(供跨模块查找函数使用)"""
|
||||
self.CDefineFound = val
|
||||
def clear_cdefine_constants(self) -> None:
|
||||
"""清空 CDefine 常量表(模块切换时调用)"""
|
||||
self.CDefineNames = None
|
||||
self.CDefineValues = None
|
||||
self.CDefineDoubleFlags = None
|
||||
self.CDefineStrFlags = None
|
||||
self.CDefineIsStr = 0
|
||||
@@ -0,0 +1,330 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenCType(TypeGenBase.TypeGenBase):
|
||||
"""CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)"""
|
||||
|
||||
def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, type_str: str) -> None:
|
||||
"""注册 CTypedef 到本地表
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
name: CTypedef 名称(如 "HANDLE")
|
||||
type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr")
|
||||
"""
|
||||
if name is None or type_str is None or pool is None:
|
||||
return
|
||||
if self.CTypedefNames is None:
|
||||
self.CTypedefNames = list[str](pool, 64)
|
||||
self.CTypedefTypeStrs = list[str](pool, 64)
|
||||
# 去重:若已存在同名 CTypedef,更新其类型字符串
|
||||
if self.CTypedefNames is not None:
|
||||
exist_n: t.CSizeT = len(self.CTypedefNames)
|
||||
ei: t.CSizeT
|
||||
for ei in range(exist_n):
|
||||
en: str = self.CTypedefNames.get(ei)
|
||||
if en is not None and string.strcmp(en, name) == 0:
|
||||
# 已存在,更新类型字符串
|
||||
self.CTypedefTypeStrs.set(ei, type_str)
|
||||
return
|
||||
self.CTypedefNames.append(name)
|
||||
self.CTypedefTypeStrs.append(type_str)
|
||||
def lookup_ctypedef(self, name: str) -> str:
|
||||
"""查找 CTypedef,返回类型表达式字符串
|
||||
|
||||
返回找到的类型表达式字符串,未找到返回 None。
|
||||
调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。
|
||||
"""
|
||||
self.CTypedefFound = 0
|
||||
if name is None:
|
||||
return None
|
||||
if self.CTypedefNames is None:
|
||||
return None
|
||||
n: t.CSizeT = len(self.CTypedefNames)
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
nm: str = self.CTypedefNames.get(i)
|
||||
if nm is not None and string.strcmp(nm, name) == 0:
|
||||
ts: str = self.CTypedefTypeStrs.get(i)
|
||||
self.CTypedefFound = 1
|
||||
return ts
|
||||
return None
|
||||
def is_ctypedef_found(self) -> int:
|
||||
"""检查上次 lookup_ctypedef 是否找到值"""
|
||||
return self.CTypedefFound
|
||||
def clear_ctypedefs(self) -> None:
|
||||
"""清空 CTypedef 表(模块切换时调用)"""
|
||||
self.CTypedefNames = None
|
||||
self.CTypedefTypeStrs = None
|
||||
self.CTypedefResolveDepth = 0
|
||||
self.CTypedefVisiting = None
|
||||
def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
|
||||
"""将 CTypedef 名加入正在解析列表(循环检测)
|
||||
|
||||
Returns:
|
||||
0=成功加入(无循环),1=检测到循环
|
||||
"""
|
||||
if name is None:
|
||||
return 0
|
||||
if self.CTypedefVisiting is None:
|
||||
self.CTypedefVisiting = list[str](pool, 32)
|
||||
if self.CTypedefVisiting is None:
|
||||
return 0
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
vi: t.CSizeT
|
||||
for vi in range(vn):
|
||||
vs: str = self.CTypedefVisiting.get(vi)
|
||||
if vs is not None and string.strcmp(vs, name) == 0:
|
||||
return 1 # 循环检测
|
||||
self.CTypedefVisiting.append(name)
|
||||
return 0
|
||||
def _ctypedef_pop_visiting(self) -> None:
|
||||
"""从正在解析列表弹出最后一个 CTypedef 名"""
|
||||
if self.CTypedefVisiting is None:
|
||||
return
|
||||
vn: t.CSizeT = len(self.CTypedefVisiting)
|
||||
if vn > 0:
|
||||
self.CTypedefVisiting.pop()
|
||||
def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int:
|
||||
"""检测类型注解是否为 t.CTypedef
|
||||
|
||||
Args:
|
||||
annotation: 类型注解 AST 节点
|
||||
|
||||
Returns:
|
||||
1=是 t.CTypedef,0=否
|
||||
"""
|
||||
if annotation is None:
|
||||
return 0
|
||||
if annotation.kind() != ast.ASTKind.Attribute:
|
||||
return 0
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
|
||||
if at.attr is None:
|
||||
return 0
|
||||
if string.strcmp(at.attr, "CTypedef") != 0:
|
||||
return 0
|
||||
if at.value is None or at.value.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if mod_nm.id is None:
|
||||
return 0
|
||||
if string.strcmp(mod_nm.id, "t") != 0:
|
||||
return 0
|
||||
return 1
|
||||
def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明
|
||||
|
||||
在 _translate_module_level 中、模块级变量预注册之前调用,
|
||||
确保 CTypedef 名称在类型解析时可用。
|
||||
|
||||
Args:
|
||||
pool: 内存池
|
||||
tree: 模块 AST 根节点
|
||||
|
||||
Returns:
|
||||
注册的 CTypedef 数量
|
||||
"""
|
||||
if pool is None or tree is None:
|
||||
return 0
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
n: t.CSizeT = len(ch)
|
||||
count: int = 0
|
||||
i: t.CSizeT
|
||||
for i in range(n):
|
||||
child: ast.AST | t.CPtr = ch.get(i)
|
||||
if child is None:
|
||||
continue
|
||||
if child.kind() != ast.ASTKind.AnnAssign:
|
||||
continue
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
|
||||
# 检测注解是否为 t.CTypedef
|
||||
if self._is_ctypedef_annotation(aa.annotation) == 0:
|
||||
continue
|
||||
# 提取目标名称(必须是 Name 节点)
|
||||
if aa.target is None or aa.target.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
if tgt.id is None:
|
||||
continue
|
||||
# 提取类型表达式字符串(从 value AST 节点)
|
||||
if aa.value is None:
|
||||
continue
|
||||
type_str: str = HandlesType._get_type_name_from_annotation(pool, aa.value)
|
||||
if type_str is None:
|
||||
continue
|
||||
# 注册 CTypedef
|
||||
self.register_ctypedef(pool, tgt.id, type_str)
|
||||
count += 1
|
||||
return count
|
||||
def _eval_const_int_expr(self, node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None,
|
||||
from_imports: str = None,
|
||||
imported_modules: str = None) -> int:
|
||||
"""递归计算常量整数表达式
|
||||
|
||||
pool/from_imports/imported_modules:跨模块 CDefine 查找上下文
|
||||
(t.CArray count 引用依赖模块的 CDefine,如 SHA512_BLOCK_LEN 定义在
|
||||
hashlib/__sha512.vp,本地 CDefine 表每模块清空,需跨模块回退查找)。
|
||||
"""
|
||||
if node is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
# Constant: 整数字面量
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
self.ConstEvalOk = 1
|
||||
return cn.int_val
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# Name: CDefine 常量名(本地表优先,未命中走跨模块查找)
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
val: int = HandlesType.lookup_cdefine_constant(nm.id)
|
||||
if HandlesType.is_cdefine_found() == 0:
|
||||
# 本地表未命中:跨模块 CDefine 查找
|
||||
# 用 HandlesExpr 模块级委托(self._lookup_cross_module_cdefine 是
|
||||
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
x_val: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, nm.id, from_imports, imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.ConstEvalOk = 1
|
||||
return x_val
|
||||
# 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景)
|
||||
fb_cdf: str = VLogger.fmt_buf()
|
||||
if fb_cdf is not None:
|
||||
viperlib.snprintf(fb_cdf, 1024,
|
||||
"[CDEF-MISS] name=%s fi=%s im=%s",
|
||||
nm.id,
|
||||
from_imports if from_imports is not None else "(null)",
|
||||
imported_modules if imported_modules is not None else "(null)")
|
||||
VLogger.error(fb_cdf, "CDEF")
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return val
|
||||
|
||||
# Attribute: 模块限定常量名,如 hashlib.MD5_DIGEST_LEN
|
||||
# (t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] 的 count 是 Attribute,
|
||||
# 复用跨模块 CDefine 查找:*:模块 → 源文件提取;re-export 常量由
|
||||
# _lookup_cross_module_cdefine 的 from-import 递归子模块兜底)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at.attr is None:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
at_mod: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if at_mod.id is not None:
|
||||
if (from_imports is not None or imported_modules is not None) \
|
||||
and pool is not None:
|
||||
mod_len: t.CSizeT = string.strlen(at_mod.id)
|
||||
fi_buf: str = pool.alloc(mod_len + 3)
|
||||
if fi_buf is not None:
|
||||
fi_buf[0] = '*'
|
||||
fi_buf[1] = ':'
|
||||
for mi in range(mod_len):
|
||||
fi_buf[2 + mi] = at_mod.id[mi]
|
||||
fi_buf[2 + mod_len] = '\0'
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
av: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, at.attr, fi_buf, imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.ConstEvalOk = 1
|
||||
return av
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# BinOp: 算术/位运算
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
# 递归计算左操作数
|
||||
lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 递归计算右操作数
|
||||
rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules)
|
||||
if self.ConstEvalOk == 0:
|
||||
return 0
|
||||
# 根据运算符执行计算
|
||||
if bop.op == ast.OpKind.Add:
|
||||
self.ConstEvalOk = 1
|
||||
return lv + rv
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
self.ConstEvalOk = 1
|
||||
return lv - rv
|
||||
if bop.op == ast.OpKind.Mult:
|
||||
self.ConstEvalOk = 1
|
||||
return lv * rv
|
||||
if bop.op == ast.OpKind.Div:
|
||||
# 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355)
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.FloorDiv:
|
||||
if rv == 0:
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
self.ConstEvalOk = 1
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
self.ConstEvalOk = 1
|
||||
return lv | rv
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
self.ConstEvalOk = 1
|
||||
return lv & rv
|
||||
# 不支持的运算符
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
|
||||
# 不支持的节点类型
|
||||
self.ConstEvalOk = 0
|
||||
return 0
|
||||
@@ -0,0 +1,397 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.CompilerFactory as CompilerFactory
|
||||
|
||||
|
||||
import lib.core.Gen.TypeGenBase as TypeGenBase
|
||||
|
||||
# ============================================================
|
||||
# TypeGenErr - TypeGenMixin 拆分(阶段 D):错误上报/源行读取/类型推断(fatal_error/infer_* 等)
|
||||
#
|
||||
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||||
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
|
||||
# @t.NoVTable:静态绑定。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
"""错误上报/源行读取/类型推断(fatal_error/infer_* 等)"""
|
||||
|
||||
def _read_source_line(self, file_path: str, lineno: int) -> str:
|
||||
"""从源文件读取第 lineno 行内容"""
|
||||
if file_path is None or lineno <= 0:
|
||||
return None
|
||||
f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
return None
|
||||
# 按文件实际大小分配缓冲区:固定 256KB 会截断大源文件,末尾行号读不到 →
|
||||
# 误报"文件不存在或行号超出范围"(如 CallGenMixin.vp 555KB/9236 行的第
|
||||
# 8390 行)。64MB 上限防御异常超大文件整体读取。
|
||||
fsize: LONGLONG = f.size()
|
||||
if fsize <= 0 or fsize > 67108864:
|
||||
f.close()
|
||||
return None
|
||||
src_size: t.CSizeT = t.CSizeT(fsize)
|
||||
buf: bytes = stdlib.malloc(src_size + 1)
|
||||
if buf is None:
|
||||
f.close()
|
||||
return None
|
||||
bytes_read: LONG = f.read_all(buf, ULONG(src_size + 1))
|
||||
f.close()
|
||||
if bytes_read <= 0:
|
||||
stdlib.free(buf)
|
||||
return None
|
||||
# 逐行查找第 lineno 行
|
||||
cur_line: int = 1
|
||||
line_start: t.CSizeT = 0
|
||||
for i in range(bytes_read):
|
||||
if buf[i] == '\n':
|
||||
if cur_line == lineno:
|
||||
line_len: t.CSizeT = i - line_start
|
||||
if line_len > 0 and buf[line_start + line_len - 1] == '\r':
|
||||
line_len -= 1
|
||||
line_buf: bytes = stdlib.malloc(line_len + 1)
|
||||
if line_buf is not None:
|
||||
string.strncpy(line_buf, buf + line_start, line_len)
|
||||
line_buf[line_len] = '\0'
|
||||
stdlib.free(buf)
|
||||
return line_buf
|
||||
stdlib.free(buf)
|
||||
return None
|
||||
cur_line += 1
|
||||
line_start = i + 1
|
||||
stdlib.free(buf)
|
||||
return None
|
||||
def read_source_line(self, file_path: str, lineno: int) -> str:
|
||||
"""公开包装:从源文件读取第 lineno 行内容(供 traceback 展示)"""
|
||||
return self._read_source_line(file_path, lineno)
|
||||
def dump_parse_traceback(self, file_path: str):
|
||||
"""解析失败时以 Python 风格输出 traceback(仿 fatal_error)"""
|
||||
err_line: int = ast.get_parse_err_line()
|
||||
err_col: int = ast.get_parse_err_col()
|
||||
err_msg: str = ast.get_parse_err_msg()
|
||||
stdio.printf("Traceback (most recent call last):\n")
|
||||
if file_path is None or file_path[0] == 0:
|
||||
file_path = "<unknown>"
|
||||
if err_line > 0:
|
||||
stdio.printf(' File "%s", line %d\n', file_path, err_line)
|
||||
src: str = self._read_source_line(file_path, err_line)
|
||||
if src is not None:
|
||||
stdio.printf(" %s\n", src)
|
||||
# 列标记:在出错 token 起始列下方标 ^(parser 的 col_offset 是 0-based,
|
||||
# 前缀 4 空格 + err_col 个空格后落点恰好是该 token 首字符)
|
||||
if err_col > 0:
|
||||
stdio.printf(" ")
|
||||
c: int
|
||||
for c in range(err_col):
|
||||
stdio.printf(" ")
|
||||
stdio.printf("^\n")
|
||||
stdlib.free(src)
|
||||
else:
|
||||
stdio.printf(' File "%s"\n', file_path)
|
||||
if err_msg is None or err_msg[0] == 0:
|
||||
err_msg = "语法错误"
|
||||
stdio.printf("SyntaxError: %s\n", err_msg)
|
||||
def fatal_error(self, node: ast.AST | t.CPtr, msg: str,
|
||||
err_type: str = "SyntaxError",
|
||||
col_start: int = 0, col_end: int = 0):
|
||||
"""以 Python 风格报错并退出(支持多帧、错误类型、列范围)
|
||||
|
||||
向后兼容:err_type/col_start/col_end 有默认值,旧调用 fatal_error(node, msg) 仍可用。
|
||||
"""
|
||||
stdio.printf("Traceback (most recent call last):\n")
|
||||
# 输出调用栈帧(从底到顶)
|
||||
i: int
|
||||
for i in range(self.TraceCount):
|
||||
frame: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(i)
|
||||
if frame is not None and frame.file_name is not None:
|
||||
if frame.lineno > 0:
|
||||
stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno)
|
||||
src: str = self._read_source_line(frame.file_name, frame.lineno)
|
||||
if src is not None:
|
||||
stdio.printf(" %s\n", src)
|
||||
stdlib.free(src)
|
||||
else:
|
||||
stdio.printf(' File "%s"\n', frame.file_name)
|
||||
# 输出当前帧(node 对应的位置)
|
||||
lineno: int = 0
|
||||
if node is not None:
|
||||
lineno = node.lineno
|
||||
file_name: str = self.CurrentFile
|
||||
if file_name is None:
|
||||
file_name = "<unknown>"
|
||||
# 行号兜底:克隆/构造节点 lineno 可能为 0(如泛型特化 _clone_arguments 的
|
||||
# ast.Arg 构造器硬编码 0,astaux.vp L139)。此时回退到 trace 栈最后一个
|
||||
# 有效帧(文件+行号)作为出错位置,避免输出误导性的 "line 0"。
|
||||
if lineno <= 0 and self.TraceCount > 0:
|
||||
ti_b: int = self.TraceCount - 1
|
||||
while ti_b >= 0:
|
||||
tfb: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(ti_b)
|
||||
if tfb is not None and tfb.file_name is not None and tfb.lineno > 0:
|
||||
file_name = tfb.file_name
|
||||
lineno = tfb.lineno
|
||||
break
|
||||
ti_b -= 1
|
||||
# 行号合理性防御:先读取该行源码,验证 node.lineno 是否落在当前文件内。
|
||||
# 若读不到(文件不存在或行号超出范围),说明文件/行号归属不可信
|
||||
# (如 AST 树被内存复用/串扰后跨文件报错),打印警告而非误导性行号。
|
||||
src_line: str = None
|
||||
line_ok: int = 1
|
||||
if lineno > 0 and string.strcmp(file_name, "<unknown>") != 0:
|
||||
src_line = self._read_source_line(file_name, lineno)
|
||||
if src_line is None:
|
||||
line_ok = 0
|
||||
if line_ok == 0:
|
||||
stdio.printf(' File "%s", line %d (!! 无法读取该行源码:文件不存在或行号超出范围,错误可能来自被复用的 AST 树,请以错误消息为准)\n',
|
||||
file_name, lineno)
|
||||
else:
|
||||
stdio.printf(' File "%s", line %d\n', file_name, lineno)
|
||||
if src_line is not None:
|
||||
stdio.printf(" %s\n", src_line)
|
||||
# 列范围标记:在源代码行下方用 ^ 标记出错范围
|
||||
if col_start > 0 and col_end >= col_start:
|
||||
stdio.printf(" ")
|
||||
j: int
|
||||
for j in range(col_end):
|
||||
if j >= col_start - 1 and j < col_end:
|
||||
stdio.printf("^")
|
||||
else:
|
||||
stdio.printf(" ")
|
||||
stdio.printf("\n")
|
||||
stdlib.free(src_line)
|
||||
# 输出错误类型 + 消息
|
||||
if err_type is None or err_type[0] == 0:
|
||||
err_type = "SyntaxError"
|
||||
stdio.printf("%s: %s\n", err_type, msg)
|
||||
sys.exit(1)
|
||||
|
||||
def fatal_type_error(self, node: ast.AST | t.CPtr, msg: str,
|
||||
col_start: int = 0, col_end: int = 0):
|
||||
"""以 Python 风格报错并退出(TypeError 版本)"""
|
||||
self.fatal_error(node, msg, "TypeError", col_start, col_end)
|
||||
def try_extract_callable_ret(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
annot: ast.AST | t.CPtr,
|
||||
imported_modules: str,
|
||||
from_imports: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""提取 t.Callable 注解的返回类型 LLVMType;非 Callable 注解返回 None"""
|
||||
if annot is None or annot.kind() != ast.ASTKind.Subscript:
|
||||
return None
|
||||
sub_cr: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot)
|
||||
if sub_cr.value is None or sub_cr.value.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
at_cr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub_cr.value)
|
||||
if at_cr.attr is None or string.strcmp(at_cr.attr, "Callable") != 0:
|
||||
return None
|
||||
# slice 必须是 Tuple(elts=[args_list, ret_node])
|
||||
if sub_cr.slice is None or sub_cr.slice.kind() != ast.ASTKind.Tuple:
|
||||
return None
|
||||
tp_cr: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub_cr.slice)
|
||||
if tp_cr.elts is None or len(tp_cr.elts) != 2:
|
||||
return None
|
||||
ret_node_cr: ast.AST | t.CPtr = tp_cr.elts.get(1)
|
||||
if ret_node_cr is None:
|
||||
return None
|
||||
return HandlesType.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans)
|
||||
def has_decorator_marker(self, node: ast.AST | t.CPtr,
|
||||
marker_name: str) -> int:
|
||||
"""检测类型注解中是否包含指定的装饰器标记"""
|
||||
if node is None or marker_name is None:
|
||||
return 0
|
||||
|
||||
k: int = node.kind()
|
||||
|
||||
# Attribute 节点: t.CExtern, t.State, t.CExport, t.CInline
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
if at.attr is not None:
|
||||
if string.strcmp(at.attr, marker_name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# BinOp 节点: int | t.CExtern(递归检测左右子节点)
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
if self.has_decorator_marker(bop.left, marker_name) != 0:
|
||||
return 1
|
||||
if self.has_decorator_marker(bop.right, marker_name) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
return 0
|
||||
def is_pass_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> int:
|
||||
"""检测函数体是否为 pass(空体或仅含 pass 语句)"""
|
||||
if body is None:
|
||||
return 1
|
||||
bn: t.CSizeT = len(body)
|
||||
if bn == 0:
|
||||
return 1
|
||||
if bn == 1:
|
||||
stmt: ast.AST | t.CPtr = body.get(0)
|
||||
if stmt is not None and stmt.kind() == ast.ASTKind.Pass:
|
||||
return 1
|
||||
return 0
|
||||
def get_llvm_type_bits(self, ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""获取 LLVM 整数类型的位宽,非整数类型返回 0"""
|
||||
if ty is None:
|
||||
return 0
|
||||
match ty:
|
||||
case llvmlite.LLVMType.Int(bits):
|
||||
return bits
|
||||
case _:
|
||||
return 0
|
||||
def infer_expr_type(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
param_types: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""推断表达式的 LLVM 类型
|
||||
|
||||
param_types 格式: "name:bits,name:bits,..."
|
||||
"""
|
||||
if node is None:
|
||||
return llvmlite.Int32(pool)
|
||||
|
||||
k: int = node.kind()
|
||||
|
||||
if k == ast.ASTKind.Constant:
|
||||
return llvmlite.Int32(pool)
|
||||
|
||||
elif k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is not None and param_types is not None:
|
||||
# 在 param_types 中查找: "name:bits" 格式
|
||||
search_key: str = pool.alloc(64)
|
||||
if search_key is not None:
|
||||
viperlib.snprintf(search_key, 64, "%s:", nm.id)
|
||||
found: str = string.strstr(param_types, search_key)
|
||||
if found is not None:
|
||||
colon_pos: t.CSizeT = string.strlen(nm.id) + 1
|
||||
bits_str: str = found + colon_pos
|
||||
bits: int = 0
|
||||
for bi in range(4):
|
||||
ch: t.CChar = bits_str[bi]
|
||||
if ch >= '0' and ch <= '9':
|
||||
bits = bits * 10 + (ch - '0')
|
||||
else:
|
||||
break
|
||||
if bits == 64:
|
||||
return llvmlite.Int64(pool)
|
||||
elif bits == 16:
|
||||
return llvmlite.Int16(pool)
|
||||
elif bits == 8:
|
||||
return llvmlite.Int8(pool)
|
||||
return llvmlite.Int32(pool)
|
||||
|
||||
elif k == ast.ASTKind.BinOp:
|
||||
binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
lhs_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type(
|
||||
pool, binop.left, param_types)
|
||||
rhs_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type(
|
||||
pool, binop.right, param_types)
|
||||
lhs_bits: int = self.get_llvm_type_bits(lhs_ty)
|
||||
rhs_bits: int = self.get_llvm_type_bits(rhs_ty)
|
||||
if lhs_bits >= rhs_bits:
|
||||
return lhs_ty
|
||||
return rhs_ty
|
||||
|
||||
return llvmlite.Int32(pool)
|
||||
def infer_return_type(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
param_types: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""扫描函数体中的 return 语句,推断返回类型"""
|
||||
if body is None:
|
||||
return llvmlite.Int32(pool)
|
||||
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
bn: t.CSizeT = len(body)
|
||||
for bi in range(bn):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None and stmt.kind() == ast.ASTKind.Return:
|
||||
rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(stmt)
|
||||
if rt.value is not None:
|
||||
expr_ty: llvmlite.LLVMType | t.CPtr = self.infer_expr_type(
|
||||
pool, rt.value, param_types)
|
||||
if expr_ty is not None:
|
||||
cur_bits: int = self.get_llvm_type_bits(ret_ty)
|
||||
new_bits: int = self.get_llvm_type_bits(expr_ty)
|
||||
if new_bits > cur_bits:
|
||||
ret_ty = expr_ty
|
||||
return ret_ty
|
||||
def build_param_types_str(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
args_node: ast.AST | t.CPtr) -> str:
|
||||
"""构建参数类型编码字符串 "name:bits,name:bits,..." """
|
||||
if args_node is None:
|
||||
return None
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is None:
|
||||
return None
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = len(alist)
|
||||
if an == 0:
|
||||
return None
|
||||
|
||||
buf_size: t.CSizeT = an * 32 + 1
|
||||
buf: str = pool.alloc(buf_size)
|
||||
if buf is None:
|
||||
return None
|
||||
buf[0] = '\0'
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is not None and arg.arg is not None:
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
# 直接调用 map_t_type 解析 Attribute 注解
|
||||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||||
if at.attr is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
bits: int = self.get_llvm_type_bits(param_ty)
|
||||
if bits == 0:
|
||||
bits = 32
|
||||
tmp: str = pool.alloc(32)
|
||||
if tmp is not None:
|
||||
viperlib.snprintf(tmp, 32, "%s:%d", arg.arg, bits)
|
||||
if ai > 0:
|
||||
self._strappend(buf, buf_size, ",")
|
||||
self._strappend(buf, buf_size, tmp)
|
||||
return buf
|
||||
def _strappend(self, dst: str, dst_size: t.CSizeT, src: str):
|
||||
"""将 src 追加到 dst 末尾"""
|
||||
if dst is None or src is None:
|
||||
return
|
||||
dlen: t.CSizeT = string.strlen(dst)
|
||||
slen: t.CSizeT = string.strlen(src)
|
||||
remain: t.CSizeT = dst_size - dlen
|
||||
if remain <= 0:
|
||||
return
|
||||
# 内联 min(slen, remain - 1) 避免 builtin min 未定义(TransPyV 无 builtin min)
|
||||
limit: t.CSizeT = slen
|
||||
cap: t.CSizeT = remain - 1
|
||||
if cap < limit:
|
||||
limit = cap
|
||||
for i in range(limit):
|
||||
dst[dlen + i] = src[i]
|
||||
dst[dlen + i] = '\0'
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -378,12 +378,15 @@ def ScanCTypedefDeclarations(pool: memhub.MemBuddy | t.CPtr,
|
||||
return 0
|
||||
|
||||
|
||||
def _eval_const_int_expr(node: ast.AST | t.CPtr) -> int:
|
||||
def _eval_const_int_expr(node: ast.AST | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr = None,
|
||||
from_imports: str = None,
|
||||
imported_modules: str = None) -> int:
|
||||
"""递归计算常量整数表达式(委托到 gen._eval_const_int_expr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._eval_const_int_expr(node)
|
||||
return g._eval_const_int_expr(node, pool, from_imports, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user