refactor(gen): TypeGenMixin 拆 5 组(Base/CDef/CType/Resolve/Err,2643→44 行)

This commit is contained in:
TermiNexus committed 2026-08-17 07:21:00 +08:00
1 parent 65cf71ff7e
commit 81d4ff3ac4
8 files changed
+2746 -2606

No files matched your search

+8
View File
@@ -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,
+239
View File
@@ -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
+306
View File
@@ -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
+330
View File
@@ -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
+397
View File
@@ -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
+5 -2
View File
@@ -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