- Gen 内部 1742 处 HandlesX.func() 改 self.Gen.Y.method() 链式调用 - 数据类/常量迁移 GenTypes.vp(10 类 + CLASS_META_*/META_*/SEQ_KIND_*/FIELD_MAX 等) - 管线/保留文件经 GenApi.vp 模块级入口(48 函数带类型注解,从 Gen 方法签名自动生成) - 删除 26 个纯委托 Handles 文件,仅留 5 个实体文件(Base/Translator/Expr/ExprCall/ExprCallTable) - 修复字段分裂:TypeGenErr CurrentFile/TraceCount 链式化;CallGenBase TempDir/Cexport 真源化
1080 lines
54 KiB
Plaintext
1080 lines
54 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import stdlib
|
||
import viperlib
|
||
import w32.fileio as fileio
|
||
import lib.core.CompilerFactory as CompilerFactory
|
||
import lib.core.Handles.HandlesBase as HandlesBase
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
import lib.core.StubMerger as StubMerger
|
||
import lib.core.VLogger as VLogger
|
||
import lib.Projectrans.Config as Config
|
||
import lib.Projectrans.Utils as Utils
|
||
|
||
|
||
import lib.core.Gen.ExprGenBase as ExprGenBase
|
||
import lib.core.StubMergerCollect as StubMergerCollect
|
||
import lib.core.StubMergerStore as StubMergerStore
|
||
|
||
# ============================================================
|
||
# ExprGenCdef - ExprGenMixin 拆分(阶段 D):跨模块 CDefine 查找
|
||
#
|
||
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
|
||
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
|
||
# @t.NoVTable:静态绑定。
|
||
# ============================================================
|
||
@t.NoVTable
|
||
class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||
"""跨模块 CDefine 查找"""
|
||
|
||
# ============================================================
|
||
# _build_source_path_from_sha1 - 通过 SHA1 从存储器构建源 .vp/.py 文件路径
|
||
#
|
||
# .vpi 文件可能未生成(Phase1 未输出 vpi),此时回退读取源 .py 文件。
|
||
# 从 StubMerger 全局存储器查找 SHA1 对应的相对路径,
|
||
# 根据 rel_path 前缀选择基础目录:
|
||
# - rel_path 以 "lib/" 开头 → App 源文件,用 {Config.SourceDir}/{rel_path}
|
||
# - 其他 → includes 文件,用 {Config.IncludesDir}/{rel_path}
|
||
#
|
||
# Returns:
|
||
# stdlib.malloc 分配的路径字符串(调用者负责 free),None 失败
|
||
# ============================================================
|
||
def _build_source_path_from_sha1(self, sha1: str) -> str:
|
||
"""通过 SHA1 从全局存储器构建源 .py 文件路径"""
|
||
if sha1 is None:
|
||
return None
|
||
if Config.IncludesDir is None:
|
||
return None
|
||
# 从 StubMerger 全局存储器获取相对路径数组
|
||
rel_arr_ptr: bytes | t.CPtr = StubMergerStore.GetSha1StoreRelArrPtr()
|
||
count: int = StubMergerStore.GetSha1StoreCount()
|
||
if rel_arr_ptr is None or count <= 0:
|
||
return None
|
||
sha1_arr_ptr: bytes | t.CPtr = StubMergerStore.GetSha1StoreArrPtr()
|
||
if sha1_arr_ptr is None:
|
||
return None
|
||
# 遍历查找匹配的 SHA1
|
||
idx_s: int = -1
|
||
for i in range(count):
|
||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||
cur_sha1: str = sha1_arr_ptr + sidx
|
||
if cur_sha1[0] == '\0':
|
||
continue
|
||
if string.strcmp(cur_sha1, sha1) == 0:
|
||
idx_s = i
|
||
break
|
||
if idx_s < 0:
|
||
return None
|
||
# 获取相对路径(MAX_REL_PATH_LEN=256,避免跨模块 CDefine 解析问题)
|
||
MAX_RPL: t.CSizeT = 256
|
||
ridx: t.CSizeT = t.CSizeT(idx_s) * MAX_RPL
|
||
rel_path: str = rel_arr_ptr + ridx
|
||
if rel_path[0] == '\0':
|
||
return None
|
||
# 选择基础目录:rel_path 以 "lib/" 开头 → App 源文件(SourceDir);
|
||
# 以 "includes/" 开头 → includes 文件(去掉 "includes/" 前缀)。
|
||
# 其他 rel_path(如 VKernel 的 "drivers/core/cpu/cpu.vp")无前缀,
|
||
# 无法从 rel_path 判断归属:先试 SourceDir(App 文件),文件不存在
|
||
# 再试 IncludesDir(includes 文件的 RelPath 同样无前缀存储)。
|
||
# 避免路径构建错误导致跨模块 CDefine 查找静默失败。
|
||
base_dir: str = None
|
||
rel_used: str = rel_path
|
||
if string.strlen(rel_path) >= 4:
|
||
if (rel_path[0] == 'l' and rel_path[1] == 'i' and
|
||
rel_path[2] == 'b' and rel_path[3] == '/'):
|
||
base_dir = Config.SourceDir if Config.SourceDir is not None else Config.IncludesDir
|
||
if base_dir is None and string.strlen(rel_path) >= 9:
|
||
if (rel_path[0] == 'i' and rel_path[1] == 'n' and
|
||
rel_path[2] == 'c' and rel_path[3] == 'l' and
|
||
rel_path[4] == 'u' and rel_path[5] == 'd' and
|
||
rel_path[6] == 'e' and rel_path[7] == 's' and
|
||
rel_path[8] == '/'):
|
||
rel_used = rel_path + 9
|
||
base_dir = Config.IncludesDir
|
||
if base_dir is None:
|
||
base_dir = Config.SourceDir if Config.SourceDir is not None else Config.IncludesDir
|
||
# 构建完整路径: {base_dir}/{rel_used}
|
||
base_len: t.CSizeT = string.strlen(base_dir)
|
||
rel_len: t.CSizeT = string.strlen(rel_used)
|
||
path_len: t.CSizeT = base_len + rel_len + 2
|
||
buf: str = stdlib.malloc(path_len)
|
||
if buf is None:
|
||
return None
|
||
viperlib.snprintf(buf, path_len, "%s/%s", base_dir, rel_used)
|
||
# 存在性检查:SourceDir 下不存在且 IncludesDir 不同 → 重试 IncludesDir
|
||
pf_chk: fileio.File | t.CPtr = fileio.File(buf, fileio.MODE.R)
|
||
if pf_chk.closed:
|
||
pf_chk.close()
|
||
if Config.IncludesDir is not None and base_dir != Config.IncludesDir:
|
||
stdlib.free(buf)
|
||
base_len2: t.CSizeT = string.strlen(Config.IncludesDir)
|
||
path_len2: t.CSizeT = base_len2 + rel_len + 2
|
||
buf = stdlib.malloc(path_len2)
|
||
if buf is None:
|
||
return None
|
||
viperlib.snprintf(buf, path_len2, "%s/%s", Config.IncludesDir, rel_used)
|
||
pf_chk2: fileio.File | t.CPtr = fileio.File(buf, fileio.MODE.R)
|
||
if pf_chk2.closed:
|
||
pf_chk2.close()
|
||
stdlib.free(buf)
|
||
return None
|
||
pf_chk2.close()
|
||
else:
|
||
stdlib.free(buf)
|
||
return None
|
||
else:
|
||
pf_chk.close()
|
||
return buf
|
||
# ============================================================
|
||
# _lookup_cross_module_cdefine - 跨模块查找 CDefine 常量
|
||
#
|
||
# 当当前模块的 CDefine 表中找不到某个 Name 时,从 from_imports
|
||
# 解析出源模块,再从该模块的 pyi 文件中解析 CDefine 常量值。
|
||
# 找到后缓存到当前模块的 CDefine 表中,避免重复查找。
|
||
#
|
||
# pyi 文件格式: "NAME: t.CDefine = value"
|
||
# ============================================================
|
||
def _lookup_cross_module_cdefine(self, pool: memhub.MemBuddy | t.CPtr,
|
||
name: str,
|
||
from_imports: str,
|
||
imported_modules: str = None,
|
||
depth: int = 0,
|
||
node: ast.AST | t.CPtr = None) -> t.CInt64T:
|
||
"""跨模块查找 CDefine 常量,返回值(64 位)或 -1(未找到)
|
||
|
||
查找顺序:
|
||
1. from_imports 精确匹配(from X import NAME)
|
||
2. from_imports star 回退(from X import *)
|
||
3. imported_modules 遍历(import X):当通过 import X 导入模块时,
|
||
模块中定义的 CDefine 常量可通过此路径找到(如方法签名默认参数引用)
|
||
|
||
depth: 递归深度(子模块递归/imported_modules 遍历的内部调用递增)。
|
||
node: 触发查找的 AST 节点(递归内传 None,line 0;顶层调用点传实际节点)。
|
||
"""
|
||
# 递归深度守卫:子模块递归(from .X import NAME re-export 链)与
|
||
# imported_modules 遍历组合可能形成循环(模块间互相 from import),
|
||
# 无上限时无限递归 → 每次递归 pool.alloc 缓冲(rc_sub_buf/rc_full_mod/
|
||
# rc_fi/im_buf/sub_fi)→ O(n²) 累积 → 主池 1.5GB OOM
|
||
# (NewAstTest CONST_INT 单次查找 14593 次调用,fi 恒为 CONST_INT:ast)。
|
||
# 正常跨模块 CDefine 查找深度 < 8(如 ast → ast.base),32 上限 fail-fast
|
||
# 暴露循环 import 链(而非静默 OOM)。报错带 node 行号 + 当前递归模块链。
|
||
if depth > 32:
|
||
err_buf: str = pool.alloc(256)
|
||
if err_buf is not None:
|
||
viperlib.snprintf(err_buf, 256,
|
||
"跨模块 CDefine 查找递归过深(疑似模块循环 import/re-export): %s (depth=%d fi=%s)",
|
||
name, depth,
|
||
from_imports if from_imports is not None else "(nil)")
|
||
self.Gen.TypeGenErr.fatal_error(node, err_buf, "InternalCompilerError")
|
||
self.Gen.TypeGenErr.fatal_error(node,
|
||
"跨模块 CDefine 查找递归过深(疑似模块循环 import/re-export)", "InternalCompilerError")
|
||
# 入口处清零标志,确保所有早退路径(return -1)都返回"未找到"状态
|
||
# 避免递归调用时前一次成功的标志残留导致误判
|
||
self.Gen.TypeGenCDef.set_cdefine_found(0)
|
||
if name is None:
|
||
return -1
|
||
if from_imports is None:
|
||
from_imports = ""
|
||
|
||
# 1. 从 from_imports 查找名称对应的模块名
|
||
# 先尝试精确匹配(allow_star_fallback=0),避免 CDefine 常量被 star import 误导
|
||
mod_name_raw: str = self.Gen.ImportsGen.lookup_from_import(from_imports, name, 0)
|
||
if mod_name_raw is None:
|
||
# 精确匹配失败:尝试 star import 回退
|
||
mod_name_raw = self.Gen.ImportsGen.lookup_from_import(from_imports, name, 1)
|
||
|
||
# 截断模块名到 NUL 结尾:lookup_from_import 返回指向 from_imports 内部的
|
||
# 指针(非 NUL 结尾,后随空格分隔的其他条目,如 "ast CONST_STR:ast ...")。
|
||
# 不截断会污染 base_mod:strlen 读到整个 from_imports 末尾 → rc_full_mod
|
||
# 每层累积整个列表 + ".base"(dump:ast.base.base.base 无限递归根因),
|
||
# 且缓存 key 错乱("CONST_INT@ast CONST_STR:ast ...")无法命中。
|
||
# 与 _lookup_sha1_from_modname_raw 的截断逻辑一致(空格/冒号/NUL 分隔)。
|
||
base_mod: str = None
|
||
if mod_name_raw is not None:
|
||
mbl: t.CSizeT = 0
|
||
while mod_name_raw[mbl] != ' ' and mod_name_raw[mbl] != '\0' \
|
||
and mod_name_raw[mbl] != ':':
|
||
mbl += 1
|
||
mb_buf: str = pool.alloc(mbl + 1)
|
||
if mb_buf is not None:
|
||
mi2: t.CSizeT
|
||
for mi2 in range(mbl):
|
||
mb_buf[mi2] = mod_name_raw[mi2]
|
||
mb_buf[mbl] = '\0'
|
||
base_mod = mb_buf
|
||
while base_mod is not None and base_mod[0] == '.':
|
||
base_mod = base_mod + 1
|
||
|
||
# 跨模块 CDefine 查找缓存(perm_pool 永久,跨文件复用):
|
||
# 首次查找成功后结果缓存,后续文件(含 reset_to(mark2)/模块切换)直接命中,
|
||
# 避免 CONST_INT 跨模块递归查找反复触发(NewAstTest OOM 根因——
|
||
# 14593 次调用全部重复递归 ast → ast.base → ...)。
|
||
# key = "name@源模块"(源模块维度,用去点后的 base_mod 保证一致),
|
||
# 保持模块隔离:不同源模块的同名 CDefine 值不同时不串值。
|
||
# 仅 ALL_CAPS 全局唯一宏名才进入本函数(_is_cdefine_name_pattern 已过滤)。
|
||
xkey_buf: str = None
|
||
if base_mod is not None:
|
||
xk_len: t.CSizeT = string.strlen(name) + string.strlen(base_mod) + 2
|
||
xkey_buf = pool.alloc(xk_len)
|
||
if xkey_buf is not None:
|
||
viperlib.snprintf(xkey_buf, xk_len, "%s@%s", name, base_mod)
|
||
xval: str = self.Gen.TypeGenCDef.lookup_xmod_cdefine(xkey_buf)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||
if self.Gen.TypeGenCDef.is_cdefine_str() != 0:
|
||
self.Gen.TypeGenCDef.register_cdefine_string(pool, name, xval)
|
||
elif self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||
xd_v: double = string.atof(xval)
|
||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, xd_v)
|
||
else:
|
||
xv_i: t.CInt64T = string.atoll(xval)
|
||
self.Gen.TypeGenCDef.register_cdefine_constant(pool, name, xv_i)
|
||
return string.atoll(xval)
|
||
|
||
# 2. from_imports 查找失败:直接回退到 imported_modules 遍历(步骤 9.6)
|
||
# 注意:star fallback 可能返回错误模块(如 stdint),常量实际不在其中,
|
||
# 步骤 9.6 会在该模块查找失败后继续遍历 imported_modules
|
||
if mod_name_raw is None:
|
||
# from_imports 完全没有匹配(精确和 star 都失败)
|
||
# 直接进入 imported_modules 遍历(步骤 9.6)
|
||
if imported_modules is None:
|
||
return -1
|
||
# 跳过 from_imports 模块读取,直接走步骤 9.6 的 imported_modules 遍历
|
||
# 设置 result_found=0 跳过步骤 3-9,直接到 9.6
|
||
self.Gen.TypeGenCDef.set_cdefine_found(0)
|
||
# 直接遍历 imported_modules
|
||
im_len: t.CSizeT = string.strlen(imported_modules)
|
||
im_ci: t.CSizeT = 0
|
||
while im_ci < im_len:
|
||
while im_ci < im_len and imported_modules[im_ci] == ' ':
|
||
im_ci += 1
|
||
if im_ci >= im_len:
|
||
break
|
||
im_start: t.CSizeT = im_ci
|
||
while im_ci < im_len and imported_modules[im_ci] != ' ':
|
||
im_ci += 1
|
||
im_end: t.CSizeT = im_ci
|
||
im_nlen: t.CSizeT = im_end - im_start
|
||
if im_nlen > 0 and im_nlen < 256:
|
||
im_buf: str = pool.alloc(im_nlen + 1)
|
||
if im_buf is not None:
|
||
mk: t.CSizeT = 0
|
||
while mk < im_nlen:
|
||
im_buf[mk] = imported_modules[im_start + mk]
|
||
mk += 1
|
||
im_buf[im_nlen] = '\0'
|
||
sub_fi: str = pool.alloc(im_nlen + 3)
|
||
if sub_fi is not None:
|
||
sub_fi[0] = '*'
|
||
sub_fi[1] = ':'
|
||
mk2: t.CSizeT = 0
|
||
while mk2 < im_nlen:
|
||
sub_fi[2 + mk2] = im_buf[mk2]
|
||
mk2 += 1
|
||
sub_fi[2 + im_nlen] = '\0'
|
||
sub_val: t.CInt64T = self._lookup_cross_module_cdefine(pool, name, sub_fi, None, depth + 1, node)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||
return sub_val
|
||
return -1
|
||
|
||
# 2. 截断模块名 → 去前导点 → 精确+后缀查找 SHA1(复用 HandlesExprCall 公共逻辑)
|
||
sha1: str = self.Gen.CallGenBase._lookup_sha1_from_modname_raw(pool, mod_name_raw)
|
||
if sha1 is None:
|
||
return -1
|
||
|
||
# 5. 获取 temp_dir
|
||
temp_dir: str = self.Gen.TypeGenBase.get_temp_dir()
|
||
if temp_dir is None:
|
||
return -1
|
||
|
||
# 6. 构建 vpi 文件路径
|
||
td_len: t.CSizeT = string.strlen(temp_dir)
|
||
pyi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "vpi")
|
||
if pyi_path is None:
|
||
return -1
|
||
|
||
# 7. 读取 vpi 文件;若不存在或内容过短(空 stub)则回退读取源 .vp/.py 文件
|
||
PYI_READ_BUF_SIZE: t.CSizeT = 65536
|
||
pyi_buf: bytes = stdlib.malloc(PYI_READ_BUF_SIZE)
|
||
if pyi_buf is None:
|
||
stdlib.free(pyi_path)
|
||
return -1
|
||
pf: fileio.File | t.CPtr = fileio.File(pyi_path, fileio.MODE.R)
|
||
need_py_fallback: int = 0
|
||
bytes_read: LONG = 0
|
||
if pf.closed:
|
||
# .vpi 文件不存在:回退读取源 .vp/.py 文件
|
||
need_py_fallback = 1
|
||
else:
|
||
bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE)
|
||
pf.close()
|
||
# vpi 内容过短(< 10 字节)视为空 stub,回退 .py
|
||
if bytes_read < 10:
|
||
need_py_fallback = 1
|
||
else:
|
||
if bytes_read < PYI_READ_BUF_SIZE:
|
||
pyi_buf[bytes_read] = 0
|
||
else:
|
||
pyi_buf[PYI_READ_BUF_SIZE - 1] = 0
|
||
# vpi(存根签名文件)中的 CDefine 声明可能只带名字不带值
|
||
# (Converter 旧版只对 CONST_INT/BOOL 等输出 "= value",CONST_FLOAT
|
||
# 等不输出 → numpy 的 pi/e 在 stub 中无值),真正的值在源
|
||
# .vp/.py 文件中。旧启发式"vpi 中任一 CDefine 带值 → 不读源"是错的:
|
||
# 模块同时含 int CDefine(带值,如 numpy.MAX_NDIM=4)与 float
|
||
# CDefine(无值,如 pi)时,int 行让 cd_sig=1 而漏回退源 → pi
|
||
# 解析失败 → 退化 @pi 全局指针 → float<->ptr 报错(NumpyTest 根因)。
|
||
# 改为按目标名判定:仅当 vpi 中 name 的 CDefine 行带值时才信任
|
||
# vpi,否则(name 行无值 / name 不在 vpi / 整个 vpi 无带值 CDefine)
|
||
# 一律回退读源文件。
|
||
cd_sig: int = 0
|
||
name_has_val: int = 0
|
||
cs_name_len: t.CSizeT = string.strlen(name)
|
||
cs_total: t.CSizeT = string.strlen(pyi_buf)
|
||
cs_i: t.CSizeT = 0
|
||
while cs_i + 9 < cs_total:
|
||
if (pyi_buf[cs_i] == 't' and pyi_buf[cs_i + 1] == '.' and
|
||
pyi_buf[cs_i + 2] == 'C' and pyi_buf[cs_i + 3] == 'D' and
|
||
pyi_buf[cs_i + 4] == 'e' and pyi_buf[cs_i + 5] == 'f' and
|
||
pyi_buf[cs_i + 6] == 'i' and pyi_buf[cs_i + 7] == 'n' and
|
||
pyi_buf[cs_i + 8] == 'e'):
|
||
# 检查该行剩余部分是否有 '='(带值声明才在 vpi 中匹配)
|
||
cd_eq: int = 0
|
||
cs_j: t.CSizeT = cs_i + 9
|
||
while cs_j < cs_total and pyi_buf[cs_j] != '\n':
|
||
if pyi_buf[cs_j] == '=':
|
||
cd_eq = 1
|
||
break
|
||
cs_j += 1
|
||
if cd_eq != 0:
|
||
cd_sig = 1
|
||
# 定位该行行首,检查是否以 "name:" 开头(目标名带值)
|
||
cs_line_start: t.CSizeT = cs_i
|
||
while cs_line_start > 0 and pyi_buf[cs_line_start - 1] != '\n':
|
||
cs_line_start -= 1
|
||
if cs_i - cs_line_start >= cs_name_len + 1:
|
||
nm_ok: int = 1
|
||
for ki2 in range(cs_name_len):
|
||
if pyi_buf[cs_line_start + ki2] != name[ki2]:
|
||
nm_ok = 0
|
||
break
|
||
if nm_ok == 1 and pyi_buf[cs_line_start + cs_name_len] == ':':
|
||
name_has_val = 1
|
||
cs_i += 1
|
||
if cd_sig == 0 or name_has_val == 0:
|
||
need_py_fallback = 1
|
||
stdlib.free(pyi_path)
|
||
|
||
if need_py_fallback != 0:
|
||
# 从 SHA1 存储器查找相对路径,构建 {base_dir}/{rel_path}
|
||
src_path: str = self._build_source_path_from_sha1(sha1)
|
||
if src_path is None:
|
||
# 存储器中找不到 SHA1 = 编译器 bug(Phase1/Phase2 未填充存储器)
|
||
# 报错终止,不静默返回 -1(避免后续生成错误的 @UNDEFINED 全局变量引用)
|
||
err_buf: str = pool.alloc(512)
|
||
if err_buf is not None:
|
||
viperlib.snprintf(err_buf, 512,
|
||
"跨模块 CDefine 查找失败:SHA1 %s 不在存储器中(base_mod=%s name=%s)。"
|
||
"Phase1/Phase2 未正确填充 PopulateSha1MapStore/AppendToSha1MapStore",
|
||
sha1, base_mod, name)
|
||
VLogger.error(err_buf, "XMOD-CD")
|
||
stdlib.free(pyi_buf)
|
||
return -1
|
||
pf = fileio.File(src_path, fileio.MODE.R)
|
||
stdlib.free(src_path)
|
||
if pf.closed:
|
||
stdlib.free(pyi_buf)
|
||
return -1
|
||
bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE)
|
||
pf.close()
|
||
if bytes_read <= 0:
|
||
stdlib.free(pyi_buf)
|
||
return -1
|
||
if bytes_read < PYI_READ_BUF_SIZE:
|
||
pyi_buf[bytes_read] = 0
|
||
else:
|
||
pyi_buf[PYI_READ_BUF_SIZE - 1] = 0
|
||
|
||
# 8. 在 pyi_buf 中查找 "name: t.CDefine = value" 行
|
||
# 格式: NAME: t.CDefine = value
|
||
name_len: t.CSizeT = string.strlen(name)
|
||
total_len: t.CSizeT = string.strlen(pyi_buf)
|
||
pos: t.CSizeT = 0
|
||
result_val: t.CInt64T = 0
|
||
result_found: int = 0
|
||
res_is_double: int = 0
|
||
res_is_str: int = 0
|
||
while pos < total_len:
|
||
# 找到行首
|
||
line_start: t.CSizeT = pos
|
||
# 找到行尾
|
||
while pos < total_len and pyi_buf[pos] != '\n':
|
||
pos += 1
|
||
line_len: t.CSizeT = pos - line_start
|
||
if pos < total_len:
|
||
pos += 1 # 跳过 '\n'
|
||
|
||
# 检查行是否以 "name:" 开头
|
||
if line_len < name_len + 1:
|
||
continue
|
||
match_ok: int = 1
|
||
for ki in range(name_len):
|
||
if pyi_buf[line_start + ki] != name[ki]:
|
||
match_ok = 0
|
||
break
|
||
if match_ok == 0:
|
||
continue
|
||
if pyi_buf[line_start + name_len] != ':':
|
||
continue
|
||
|
||
# 检查行是否包含 "t.CDefine"
|
||
# 在行中查找 "t.CDefine"
|
||
has_cdefine: int = 0
|
||
ci: t.CSizeT = line_start + name_len + 1
|
||
while ci + 8 <= line_start + line_len:
|
||
if (pyi_buf[ci] == 't' and pyi_buf[ci + 1] == '.' and
|
||
pyi_buf[ci + 2] == 'C' and pyi_buf[ci + 3] == 'D' and
|
||
pyi_buf[ci + 4] == 'e' and pyi_buf[ci + 5] == 'f' and
|
||
pyi_buf[ci + 6] == 'i' and pyi_buf[ci + 7] == 'n' and
|
||
pyi_buf[ci + 8] == 'e'):
|
||
has_cdefine = 1
|
||
break
|
||
ci += 1
|
||
if has_cdefine == 0:
|
||
continue
|
||
|
||
# 找到 "=" 后面的值
|
||
eq_pos: t.CSizeT = line_start + name_len + 1
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '=':
|
||
eq_pos += 1
|
||
if eq_pos >= line_start + line_len:
|
||
continue
|
||
eq_pos += 1 # 跳过 '='
|
||
|
||
# 跳过空格
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
|
||
# 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / t.CInt(...) 等类型构造函数
|
||
# 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF)
|
||
# 如果是,跳过 "t.CXxx(" 前缀,解析括号内的值,忽略结尾 ')'
|
||
is_type_ctor: int = 0
|
||
if eq_pos + 2 < line_start + line_len:
|
||
if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.':
|
||
# 找到 '(' 的位置
|
||
paren_pos: t.CSizeT = eq_pos + 2
|
||
while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(':
|
||
paren_pos += 1
|
||
if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(':
|
||
is_type_ctor = 1
|
||
eq_pos = paren_pos + 1 # 跳过 '('
|
||
# 跳过括号内可能的前导空格
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
|
||
# 括号包裹标记:(1 << 23) / (512) / (A | B)
|
||
is_paren_expr: int = 0
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '(':
|
||
is_paren_expr = 1
|
||
eq_pos += 1
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
|
||
# === 解析左操作数 token(数字 / hex / 负号 / 名称) ===
|
||
# 负号标记
|
||
is_neg: int = 0
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-':
|
||
is_neg = 1
|
||
eq_pos += 1
|
||
val_str_start: t.CSizeT = eq_pos
|
||
val_str_len: t.CSizeT = 0
|
||
is_hex: int = 0
|
||
is_float_val: int = 0
|
||
is_name_val: int = 0
|
||
is_str_val: int = 0
|
||
# 字符串值(如 ZLIB_VERSION: t.CDefine = "1.3.2"):读引号内内容。
|
||
# 跨模块读回此前不支持引号 → val_str_len=0 被跳过 → "跨模块 CDefine
|
||
# 未找到"(test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '"':
|
||
is_str_val = 1
|
||
eq_pos += 1 # 跳过开引号
|
||
val_str_start = eq_pos
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '"':
|
||
val_str_len += 1
|
||
eq_pos += 1
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '"':
|
||
eq_pos += 1 # 跳过闭引号
|
||
if eq_pos + 1 < line_start + line_len:
|
||
if pyi_buf[eq_pos] == '0' and (pyi_buf[eq_pos + 1] == 'x' or pyi_buf[eq_pos + 1] == 'X'):
|
||
is_hex = 1
|
||
val_str_len = 2
|
||
eq_pos += 2
|
||
elif (pyi_buf[eq_pos] >= 'A' and pyi_buf[eq_pos] <= 'Z') or \
|
||
(pyi_buf[eq_pos] >= 'a' and pyi_buf[eq_pos] <= 'z') or \
|
||
pyi_buf[eq_pos] == '_':
|
||
is_name_val = 1
|
||
while eq_pos < line_start + line_len:
|
||
c_tk: t.CChar = pyi_buf[eq_pos]
|
||
if (c_tk >= 'A' and c_tk <= 'Z') or (c_tk >= 'a' and c_tk <= 'z') or \
|
||
(c_tk >= '0' and c_tk <= '9') or c_tk == '_':
|
||
val_str_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
# 数字/hex 字符续读(字符串值已整体读取,跳过)
|
||
while eq_pos < line_start + line_len and is_name_val == 0 and is_str_val == 0:
|
||
ch: t.CChar = pyi_buf[eq_pos]
|
||
if is_hex == 1:
|
||
if ((ch >= '0' and ch <= '9') or
|
||
(ch >= 'a' and ch <= 'f') or
|
||
(ch >= 'A' and ch <= 'F')):
|
||
val_str_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
else:
|
||
if ch >= '0' and ch <= '9':
|
||
val_str_len += 1
|
||
eq_pos += 1
|
||
elif ch == '.' and is_float_val == 0:
|
||
# 浮点值:'3.14159'('.' 只允许一次)
|
||
is_float_val = 1
|
||
val_str_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
|
||
if val_str_len == 0 and is_str_val == 0:
|
||
continue
|
||
|
||
# 复制左 token 到缓冲区
|
||
val_buf: str = pool.alloc(val_str_len + 1)
|
||
if val_buf is None:
|
||
continue
|
||
for vi in range(val_str_len):
|
||
val_buf[vi] = pyi_buf[val_str_start + vi]
|
||
val_buf[val_str_len] = '\0'
|
||
|
||
# 左 token 求值
|
||
lval: t.CInt64T = 0
|
||
l_is_double: int = 0
|
||
ldbl: double = 0.0
|
||
if is_str_val != 0:
|
||
# 字符串 CDefine(如 ZLIB_VERSION = "1.3.2"):注册字符串值
|
||
# (含空串 ""),result_found 标记 + res_is_str 供尾部跳过整数
|
||
# 注册/缓存(否则 register_cdefine_constant 把字符串当 0 整数)
|
||
self.Gen.TypeGenCDef.register_cdefine_string(pool, name, val_buf)
|
||
result_val = 0
|
||
result_found = 1
|
||
res_is_str = 1
|
||
elif is_name_val != 0:
|
||
# True/False 布尔字面量 → 1/0(对齐 TPC:bool 在 CDefine 语境按整数处理)
|
||
if string.strcmp(val_buf, "True") == 0:
|
||
lval = 1
|
||
elif string.strcmp(val_buf, "False") == 0:
|
||
lval = 0
|
||
else:
|
||
# 名称引用:查当前 CDefine 表(如 FOREGROUND_COMBO = FOREGROUND_RED)
|
||
lval = self.Gen.TypeGenCDef.lookup_cdefine_constant(val_buf)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() == 0:
|
||
# 名称未注册:该行无法求值,跳过
|
||
continue
|
||
elif is_hex == 1:
|
||
# 手动解析十六进制(跳过 0x 前缀)——64 位累加,
|
||
# 0xFFFFFFFF=4294967295 保持全精度(常量生成端 i32 截断回 -1)
|
||
hex_result: t.CInt64T = 0
|
||
hex_buf: str = val_buf + 2 # 跳过 "0x"
|
||
for hi in range(val_str_len - 2):
|
||
hc: t.CChar = hex_buf[hi]
|
||
hd: int = 0
|
||
if hc >= '0' and hc <= '9':
|
||
hd = hc - '0'
|
||
elif hc >= 'a' and hc <= 'f':
|
||
hd = hc - 'a' + 10
|
||
elif hc >= 'A' and hc <= 'F':
|
||
hd = hc - 'A' + 10
|
||
else:
|
||
break
|
||
hex_result = hex_result * 16 + hd
|
||
lval = hex_result
|
||
elif is_float_val != 0:
|
||
l_is_double = 1
|
||
ldbl = string.atof(val_buf)
|
||
lval = string.atoll(val_buf)
|
||
else:
|
||
lval = string.atoll(val_buf)
|
||
if is_neg != 0:
|
||
lval = -lval
|
||
if l_is_double != 0:
|
||
ldbl = -ldbl
|
||
|
||
# 跳过空格,检查是否有二元运算符
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
|
||
# 解析运算符(<< >> | & ^ + - * /)
|
||
cd_op: int = 0
|
||
if eq_pos + 1 < line_start + line_len:
|
||
if pyi_buf[eq_pos] == '<' and pyi_buf[eq_pos + 1] == '<':
|
||
cd_op = 1 # LShift
|
||
eq_pos += 2
|
||
elif pyi_buf[eq_pos] == '>' and pyi_buf[eq_pos + 1] == '>':
|
||
cd_op = 2 # RShift
|
||
eq_pos += 2
|
||
if cd_op == 0 and eq_pos < line_start + line_len:
|
||
if pyi_buf[eq_pos] == '|':
|
||
cd_op = 3 # BitOr
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '&':
|
||
cd_op = 4 # BitAnd
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '^':
|
||
cd_op = 5 # BitXor
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '+':
|
||
cd_op = 6 # Add
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '-':
|
||
cd_op = 7 # Sub
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '*':
|
||
cd_op = 8 # Mult
|
||
eq_pos += 1
|
||
elif pyi_buf[eq_pos] == '/':
|
||
cd_op = 9 # Div
|
||
eq_pos += 1
|
||
|
||
if cd_op != 0:
|
||
# === 解析右操作数 token ===
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
r_neg: int = 0
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-':
|
||
r_neg = 1
|
||
eq_pos += 1
|
||
r_start: t.CSizeT = eq_pos
|
||
r_len: t.CSizeT = 0
|
||
r_hex: int = 0
|
||
r_name: int = 0
|
||
if eq_pos + 1 < line_start + line_len:
|
||
if pyi_buf[eq_pos] == '0' and (pyi_buf[eq_pos + 1] == 'x' or pyi_buf[eq_pos + 1] == 'X'):
|
||
r_hex = 1
|
||
r_len = 2
|
||
eq_pos += 2
|
||
elif (pyi_buf[eq_pos] >= 'A' and pyi_buf[eq_pos] <= 'Z') or \
|
||
(pyi_buf[eq_pos] >= 'a' and pyi_buf[eq_pos] <= 'z') or \
|
||
pyi_buf[eq_pos] == '_':
|
||
r_name = 1
|
||
while eq_pos < line_start + line_len:
|
||
c_r: t.CChar = pyi_buf[eq_pos]
|
||
if (c_r >= 'A' and c_r <= 'Z') or (c_r >= 'a' and c_r <= 'z') or \
|
||
(c_r >= '0' and c_r <= '9') or c_r == '_':
|
||
r_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
while eq_pos < line_start + line_len and r_name == 0:
|
||
c_r2: t.CChar = pyi_buf[eq_pos]
|
||
if r_hex == 1:
|
||
if ((c_r2 >= '0' and c_r2 <= '9') or
|
||
(c_r2 >= 'a' and c_r2 <= 'f') or
|
||
(c_r2 >= 'A' and c_r2 <= 'F')):
|
||
r_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
else:
|
||
if c_r2 >= '0' and c_r2 <= '9':
|
||
r_len += 1
|
||
eq_pos += 1
|
||
else:
|
||
break
|
||
if r_len == 0:
|
||
# 运算符后无右操作数:无法求值,跳过该行
|
||
continue
|
||
r_buf: str = pool.alloc(r_len + 1)
|
||
if r_buf is None:
|
||
continue
|
||
for r_i in range(r_len):
|
||
r_buf[r_i] = pyi_buf[r_start + r_i]
|
||
r_buf[r_len] = '\0'
|
||
rval: t.CInt64T = 0
|
||
if r_name != 0:
|
||
# True/False 布尔字面量 → 1/0
|
||
if string.strcmp(r_buf, "True") == 0:
|
||
rval = 1
|
||
elif string.strcmp(r_buf, "False") == 0:
|
||
rval = 0
|
||
else:
|
||
rval = self.Gen.TypeGenCDef.lookup_cdefine_constant(r_buf)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() == 0:
|
||
# 名称未注册:无法求值,跳过该行
|
||
continue
|
||
elif r_hex != 0:
|
||
rhex_v: t.CInt64T = 0
|
||
rh_buf: str = r_buf + 2
|
||
for rh_i in range(r_len - 2):
|
||
rc: t.CChar = rh_buf[rh_i]
|
||
rd: int = 0
|
||
if rc >= '0' and rc <= '9':
|
||
rd = rc - '0'
|
||
elif rc >= 'a' and rc <= 'f':
|
||
rd = rc - 'a' + 10
|
||
elif rc >= 'A' and rc <= 'F':
|
||
rd = rc - 'A' + 10
|
||
else:
|
||
break
|
||
rhex_v = rhex_v * 16 + rd
|
||
rval = rhex_v
|
||
else:
|
||
rval = string.atoll(r_buf)
|
||
if r_neg != 0:
|
||
rval = -rval
|
||
# 计算二元表达式结果(对齐 TPC ConstEvaluator)
|
||
if cd_op == 1:
|
||
result_val = lval << rval
|
||
elif cd_op == 2:
|
||
result_val = lval >> rval
|
||
elif cd_op == 3:
|
||
result_val = lval | rval
|
||
elif cd_op == 4:
|
||
result_val = lval & rval
|
||
elif cd_op == 5:
|
||
result_val = lval ^ rval
|
||
elif cd_op == 6:
|
||
result_val = lval + rval
|
||
elif cd_op == 7:
|
||
result_val = lval - rval
|
||
elif cd_op == 8:
|
||
result_val = lval * rval
|
||
else:
|
||
if rval == 0:
|
||
continue
|
||
result_val = lval // rval
|
||
result_found = 1
|
||
break
|
||
else:
|
||
# 单值(无运算符):括号内单值如 (512) / (-11) 也走这里
|
||
if is_paren_expr != 0:
|
||
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
|
||
eq_pos += 1
|
||
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == ')':
|
||
eq_pos += 1
|
||
if is_float_val != 0:
|
||
# 浮点 CDefine(如 U_M_PI = 3.14159...):
|
||
# 值缓存为 double(register_cdefine_double),供调用处生成
|
||
# double 常量;整数部分供 int 路径使用(is_cdefine_double 标志)。
|
||
self.Gen.TypeGenCDef.register_cdefine_double(pool, name, ldbl)
|
||
result_val = lval
|
||
result_found = 1
|
||
res_is_double = 1
|
||
else:
|
||
result_val = lval
|
||
result_found = 1
|
||
break
|
||
|
||
# 9.5 如果当前模块文件中没找到,递归查找子模块
|
||
# 处理 from .X import NAME 和 from .X import * 的情况
|
||
# 例如 ast.__init__.vp 中 from .base import CONST_INT, ...
|
||
# 需要递归查找 ast.base 子模块中的 CONST_INT: t.CDefine = 1
|
||
if result_found == 0:
|
||
# base_mod 已在函数开头计算(mod_name_raw 去前导点),
|
||
# 供子模块递归构建 "base_mod.X" 全名。
|
||
name_len_rc: t.CSizeT = string.strlen(name)
|
||
rc_pos: t.CSizeT = 0
|
||
while rc_pos < total_len and result_found == 0:
|
||
# 找到行首
|
||
rc_line_start: t.CSizeT = rc_pos
|
||
# 找到行尾
|
||
while rc_pos < total_len and pyi_buf[rc_pos] != '\n':
|
||
rc_pos += 1
|
||
rc_line_len: t.CSizeT = rc_pos - rc_line_start
|
||
if rc_pos < total_len:
|
||
rc_pos += 1
|
||
|
||
# 检查行是否以 "from ." 开头(相对导入子模块)
|
||
if rc_line_len < 12:
|
||
continue
|
||
if pyi_buf[rc_line_start] != 'f' or pyi_buf[rc_line_start+1] != 'r' or \
|
||
pyi_buf[rc_line_start+2] != 'o' or pyi_buf[rc_line_start+3] != 'm' or \
|
||
pyi_buf[rc_line_start+4] != ' ' or pyi_buf[rc_line_start+5] != '.':
|
||
continue
|
||
|
||
# 提取子模块名(从 rc_line_start+6 开始,到空格/tab 为止)
|
||
rc_sub_start: t.CSizeT = rc_line_start + 6
|
||
rc_sub_end: t.CSizeT = rc_sub_start
|
||
while rc_sub_end < rc_line_start + rc_line_len and \
|
||
pyi_buf[rc_sub_end] != ' ' and pyi_buf[rc_sub_end] != '\t':
|
||
rc_sub_end += 1
|
||
rc_sub_len: t.CSizeT = rc_sub_end - rc_sub_start
|
||
if rc_sub_len == 0:
|
||
continue
|
||
|
||
# 检查行是否包含 "import"
|
||
rc_has_import: int = 0
|
||
rc_ipos: t.CSizeT = rc_sub_end
|
||
while rc_ipos + 6 <= rc_line_start + rc_line_len:
|
||
if pyi_buf[rc_ipos] == 'i' and pyi_buf[rc_ipos+1] == 'm' and \
|
||
pyi_buf[rc_ipos+2] == 'p' and pyi_buf[rc_ipos+3] == 'o' and \
|
||
pyi_buf[rc_ipos+4] == 'r' and pyi_buf[rc_ipos+5] == 't':
|
||
rc_has_import = 1
|
||
break
|
||
rc_ipos += 1
|
||
if rc_has_import == 0:
|
||
continue
|
||
|
||
# 检查 NAME 是否在导入列表中,或导入是 *
|
||
# 处理多行导入:from .X import (... NAME, ...)
|
||
# 从 "import" 之后扫描,如果有 "(" 则扫描到 ")" 为止
|
||
rc_imp_start: t.CSizeT = rc_ipos + 6
|
||
rc_star: int = 0
|
||
rc_name_match: int = 0
|
||
|
||
# 确定扫描范围:单行或跨行(括号内)
|
||
rc_scan_end: t.CSizeT = rc_line_start + rc_line_len
|
||
rc_has_paren: int = 0
|
||
rc_pp: t.CSizeT = rc_imp_start
|
||
while rc_pp < rc_line_start + rc_line_len:
|
||
if pyi_buf[rc_pp] == '(':
|
||
rc_has_paren = 1
|
||
break
|
||
if pyi_buf[rc_pp] == '*':
|
||
rc_star = 1
|
||
rc_pp += 1
|
||
if rc_has_paren != 0:
|
||
# 多行导入:从 "(" 之后扫描到 ")" 为止
|
||
rc_scan_end = rc_pp + 1
|
||
rc_paren_closed: int = 0
|
||
rc_sp: t.CSizeT = rc_pp + 1
|
||
while rc_sp < total_len and rc_paren_closed == 0:
|
||
if pyi_buf[rc_sp] == ')':
|
||
rc_paren_closed = 1
|
||
rc_scan_end = rc_sp
|
||
break
|
||
rc_sp += 1
|
||
if rc_paren_closed == 0:
|
||
rc_scan_end = total_len
|
||
|
||
# 在 rc_imp_start 到 rc_scan_end 范围内查找 NAME 和 *
|
||
rc_cpos: t.CSizeT = rc_imp_start
|
||
while rc_cpos < rc_scan_end:
|
||
rc_ch: t.CChar = pyi_buf[rc_cpos]
|
||
if rc_ch == '*':
|
||
rc_star = 1
|
||
# 检查 NAME 是否匹配(作为完整单词)
|
||
if rc_cpos + name_len_rc <= rc_scan_end:
|
||
rc_match: int = 1
|
||
rc_ki: t.CSizeT
|
||
for rc_ki in range(name_len_rc):
|
||
if pyi_buf[rc_cpos + rc_ki] != name[rc_ki]:
|
||
rc_match = 0
|
||
break
|
||
if rc_match == 1:
|
||
# 检查前字符是否是非标识符字符
|
||
rc_before_ok: int = 0
|
||
if rc_cpos == rc_imp_start:
|
||
rc_before_ok = 1
|
||
else:
|
||
rc_before_ch: t.CChar = pyi_buf[rc_cpos - 1]
|
||
if rc_before_ch == ' ' or rc_before_ch == '\t' or \
|
||
rc_before_ch == '(' or rc_before_ch == ',' or \
|
||
rc_before_ch == '\n' or rc_before_ch == '\r':
|
||
rc_before_ok = 1
|
||
# 检查后字符是否是非标识符字符
|
||
rc_after_ok: int = 0
|
||
rc_after_pos: t.CSizeT = rc_cpos + name_len_rc
|
||
if rc_after_pos >= rc_scan_end:
|
||
rc_after_ok = 1
|
||
else:
|
||
rc_after_ch: t.CChar = pyi_buf[rc_after_pos]
|
||
if rc_after_ch == ' ' or rc_after_ch == '\t' or \
|
||
rc_after_ch == ')' or rc_after_ch == ',' or \
|
||
rc_after_ch == '\r' or rc_after_ch == '\n':
|
||
rc_after_ok = 1
|
||
if rc_before_ok == 1 and rc_after_ok == 1:
|
||
rc_name_match = 1
|
||
rc_cpos += 1
|
||
|
||
if rc_star == 0 and rc_name_match == 0:
|
||
continue
|
||
|
||
# 复制子模块名到新缓冲区(pyi_buf + rc_sub_start 不是 NUL 结尾)
|
||
rc_sub_buf: str = pool.alloc(rc_sub_len + 1)
|
||
if rc_sub_buf is None:
|
||
continue
|
||
rc_si: t.CSizeT
|
||
for rc_si in range(rc_sub_len):
|
||
rc_sub_buf[rc_si] = pyi_buf[rc_sub_start + rc_si]
|
||
rc_sub_buf[rc_sub_len] = '\0'
|
||
|
||
# 构建完整子模块名 base_mod.X
|
||
rc_full_len: t.CSizeT = string.strlen(base_mod) + 1 + rc_sub_len + 1
|
||
rc_full_mod: str = pool.alloc(rc_full_len)
|
||
if rc_full_mod is None:
|
||
continue
|
||
viperlib.snprintf(rc_full_mod, rc_full_len, "%s.%s", base_mod, rc_sub_buf)
|
||
|
||
# 防循环:若 base_mod 已以 "."+rc_sub_buf 结尾(如 ast.base 再拼
|
||
# .base → ast.base.base),说明子模块递归在重复追加同一模块段
|
||
# (模块间循环 re-export / 后缀匹配容错命中自身),跳过该次递归
|
||
# (NewAstTest CONST_INT 查找 dump:ast.base.base.base 无限增长根因)。
|
||
rc_blen: t.CSizeT = string.strlen(base_mod)
|
||
if rc_blen > rc_sub_len + 1:
|
||
rc_tail: str = base_mod + (rc_blen - rc_sub_len)
|
||
if rc_tail[0] == '.' and \
|
||
string.strncmp(rc_tail + 1, rc_sub_buf, rc_sub_len) == 0:
|
||
continue
|
||
|
||
# 构建临时 from_imports "name:full_mod"
|
||
rc_fi_len: t.CSizeT = name_len_rc + 1 + string.strlen(rc_full_mod) + 1
|
||
rc_fi: str = pool.alloc(rc_fi_len)
|
||
if rc_fi is None:
|
||
continue
|
||
viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod)
|
||
|
||
# 递归调用查找子模块
|
||
rc_sub_val: int = self._lookup_cross_module_cdefine(pool, name, rc_fi, None, depth + 1, node)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||
result_val = rc_sub_val
|
||
result_found = 1
|
||
|
||
stdlib.free(pyi_buf)
|
||
|
||
# 9.6 from_imports star fallback 模块中未找到:回退到 imported_modules 遍历
|
||
# 当 `from stdint import *` 导致 star fallback 返回 stdint,但目标常量
|
||
# (如 SHARE_READ)实际在 `import w32.fileio` 导入的模块中时,
|
||
# 需要遍历 imported_modules 逐个查找
|
||
if result_found == 0 and imported_modules is not None:
|
||
im2_len: t.CSizeT = string.strlen(imported_modules)
|
||
im2_ci: t.CSizeT = 0
|
||
while im2_ci < im2_len and result_found == 0:
|
||
while im2_ci < im2_len and imported_modules[im2_ci] == ' ':
|
||
im2_ci += 1
|
||
if im2_ci >= im2_len:
|
||
break
|
||
im2_start: t.CSizeT = im2_ci
|
||
while im2_ci < im2_len and imported_modules[im2_ci] != ' ':
|
||
im2_ci += 1
|
||
im2_end: t.CSizeT = im2_ci
|
||
im2_nlen: t.CSizeT = im2_end - im2_start
|
||
if im2_nlen > 0 and im2_nlen < 256:
|
||
im2_buf: str = pool.alloc(im2_nlen + 1)
|
||
if im2_buf is not None:
|
||
mk3: t.CSizeT = 0
|
||
while mk3 < im2_nlen:
|
||
im2_buf[mk3] = imported_modules[im2_start + mk3]
|
||
mk3 += 1
|
||
im2_buf[im2_nlen] = '\0'
|
||
sub_fi2: str = pool.alloc(im2_nlen + 3)
|
||
if sub_fi2 is not None:
|
||
sub_fi2[0] = '*'
|
||
sub_fi2[1] = ':'
|
||
mk4: t.CSizeT = 0
|
||
while mk4 < im2_nlen:
|
||
sub_fi2[2 + mk4] = im2_buf[mk4]
|
||
mk4 += 1
|
||
sub_fi2[2 + im2_nlen] = '\0'
|
||
sub_val2: t.CInt64T = self._lookup_cross_module_cdefine(pool, name, sub_fi2, None, depth + 1, node)
|
||
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
|
||
result_val = sub_val2
|
||
result_found = 1
|
||
|
||
# 10. 缓存到当前模块的 CDefine 表中,并写入跨模块 perm_pool 缓存
|
||
# 浮点 CDefine 已在匹配循环中 register_cdefine_double 缓存
|
||
# (res_is_double=1),此处只缓存整数 CDefine,避免覆盖 double。
|
||
if result_found != 0:
|
||
if res_is_str != 0:
|
||
# 字符串 CDefine:值已在匹配循环 register_cdefine_string(val_buf
|
||
# 是命中行的字符串内容,pool 分配跨函数有效),此处只写跨模块缓存
|
||
if base_mod is not None:
|
||
ck_len_s: t.CSizeT = string.strlen(name) + string.strlen(base_mod) + 2
|
||
ckey_s: str = pool.alloc(ck_len_s)
|
||
if ckey_s is not None:
|
||
viperlib.snprintf(ckey_s, ck_len_s, "%s@%s", name, base_mod)
|
||
self.Gen.TypeGenCDef.register_xmod_cdefine(ckey_s, val_buf, 0, 1)
|
||
elif res_is_double == 0:
|
||
self.Gen.TypeGenCDef.register_cdefine_constant(pool, name, result_val)
|
||
# 跨模块查找缓存(perm_pool 永久,跨文件复用):整数
|
||
# key 与入口查询一致:"name@源模块"(用截断后的 base_mod,
|
||
# 与 mod_name_raw 一致——两者都是去点后的模块名,保证 key 匹配)
|
||
if base_mod is not None:
|
||
ck_len: t.CSizeT = string.strlen(name) + string.strlen(base_mod) + 2
|
||
ckey_buf: str = pool.alloc(ck_len)
|
||
if ckey_buf is not None:
|
||
viperlib.snprintf(ckey_buf, ck_len, "%s@%s", name, base_mod)
|
||
cbuf_i: str = pool.alloc(32)
|
||
if cbuf_i is not None:
|
||
viperlib.snprintf(cbuf_i, 32, "%lld", result_val)
|
||
self.Gen.TypeGenCDef.register_xmod_cdefine(ckey_buf, cbuf_i, 0, 0)
|
||
else:
|
||
# 浮点:从本地表取回 %.17g 文本,写入跨模块缓存(保精度)
|
||
if base_mod is not None:
|
||
ck_len2: t.CSizeT = string.strlen(name) + string.strlen(base_mod) + 2
|
||
ckey2: str = pool.alloc(ck_len2)
|
||
if ckey2 is not None:
|
||
viperlib.snprintf(ckey2, ck_len2, "%s@%s", name, base_mod)
|
||
dval_cc: double = self.Gen.TypeGenCDef.lookup_cdefine_double(name)
|
||
if self.Gen.TypeGenCDef.is_cdefine_double() != 0:
|
||
cbuf_d: str = pool.alloc(64)
|
||
if cbuf_d is not None:
|
||
stdio.snprintf(cbuf_d, 64, "%.17g", dval_cc)
|
||
self.Gen.TypeGenCDef.register_xmod_cdefine(ckey2, cbuf_d, 1, 0)
|
||
self.Gen.TypeGenCDef.set_cdefine_found(1)
|
||
else:
|
||
self.Gen.TypeGenCDef.set_cdefine_found(0)
|
||
|
||
return result_val
|
||
# ============================================================
|
||
# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定
|
||
#
|
||
# CDefine 常量(如 FOREGROUND_GREEN, STD_OUTPUT_HANDLE, SCOPE_MODULE)
|
||
# 都遵循 ALL_CAPS 约定:仅含大写字母 A-Z、数字 0-9、下划线 _,
|
||
# 且至少含一个大写字母。
|
||
#
|
||
# Python 关键字(match, if, for)和变量名(self, pool, builder)
|
||
# 都含小写字母,不会匹配,从而避免 fail-fast 误报。
|
||
#
|
||
# 返回: 1=符合 CDefine 命名约定, 0=不符合
|
||
# ============================================================
|
||
def _is_cdefine_name_pattern(self, name: str) -> int:
|
||
"""检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)"""
|
||
if name is None:
|
||
return 0
|
||
has_upper: int = 0
|
||
i: t.CSizeT = 0
|
||
while name[i] != '\0':
|
||
c: t.CChar = name[i]
|
||
if c >= 'a' and c <= 'z':
|
||
return 0
|
||
if c >= 'A' and c <= 'Z':
|
||
has_upper = 1
|
||
i += 1
|
||
return has_upper
|
||
# ============================================================
|
||
# 翻译变量引用(Name 节点)→ load
|
||
# ============================================================
|
||
def _const_int_for_cdefine(self, pool: memhub.MemBuddy | t.CPtr,
|
||
value: t.CInt64T) -> llvmlite.Value | t.CPtr:
|
||
"""CDefine 整数常量 → LLVM 常量(对齐 TPC TypeConvert 的 64 位升级)
|
||
|
||
规则(与 translate_constant 的 i32 溢出升级一致,但保留 0xFFFFFFFF 语义):
|
||
值超 32 位无符号范围(> 0xFFFFFFFF)→ i64 全精度常量
|
||
(如 sys.maxsize = 9223372036854775807);
|
||
否则 → i32 常量,内部 t.CInt 截断(0xFFFFFFFF → -1,保持既有
|
||
INVALID_HANDLE_VALUE / WAIT_FAILED = -1 语义不变,避免 i32 4294967295
|
||
生成非法 LLVM IR 文本 "i32 4294967295")。
|
||
|
||
注意:不能用 `value > 4294967295` 直接比较——TPV 编译自身源码时大数字面量
|
||
(> 0x7FFFFFFF)在字面量层回绕成 i32(sext 后等于 -1),阈值恒成立导致所有
|
||
正数 CDefine 都被升 i64(INVALID_FILE_ATTRIBUTES 0xFFFFFFFF 从 i32 -1 变
|
||
i64 4294967295 → 与 _get_attrs 的 sext(-1) 比较失败,SysLibTest exists FAIL 根因)。
|
||
改用截断回比较:t.CUInt32T(value) 回绕后还原,与 value 不等即超 u32 范围。
|
||
"""
|
||
if value >= 0 and t.CUInt64T(t.CUInt32T(value)) != value:
|
||
return llvmlite.const_int64(pool, value)
|
||
return llvmlite.const_int32(pool, t.CInt(value)) |