refactor(gen): P6 方法化 - StmtGen/AssignGen/VarGen/ImportsGen/TranslatorGen Mixin
5 个新 Mixin(92 方法)承接 HandlesBody/If/While/For/Return/Nonlocal/Match/Enum/AnnAssign/AugAssign/Var/Imports/Translator/Main 的无状态函数与 _g_ 全局;15 个 Handles 模块改为一行委托(调用方零改动);Generator 组合扩展至 12 Mixin,__init__ 初始化 8 个新字段;BuildPipeline/main 注入 14 个模块 set_global_gen;修复 ImportsGenMixin 与 TypeGenMixin 的 CurrentFile 重复字段冲突(改 HandlesType 委托,延迟 import 规避循环依赖)。
This commit is contained in:
1 parent
451be82b32
commit
6677da99f7
22 files changed
+4123
-2234
No files matched your search
@@ -20,6 +20,18 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesMatch as HandlesMatch
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesMain as HandlesMain
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.StubGen.Converter as StubConverter
|
||||
import lib.Projectrans.Config as Config
|
||||
@@ -156,6 +168,21 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
|
||||
HandlesExprCall.set_global_gen(gen)
|
||||
HandlesFunctions.set_global_gen(gen)
|
||||
HandlesClassDef.set_global_gen(gen)
|
||||
# P6: 注入语句/赋值/变量/导入/翻译驱动模块的单例
|
||||
HandlesImports.set_global_gen(gen)
|
||||
HandlesBody.set_global_gen(gen)
|
||||
HandlesIf.set_global_gen(gen)
|
||||
HandlesWhile.set_global_gen(gen)
|
||||
HandlesFor.set_global_gen(gen)
|
||||
HandlesReturn.set_global_gen(gen)
|
||||
HandlesNonlocal.set_global_gen(gen)
|
||||
HandlesMatch.set_global_gen(gen)
|
||||
HandlesEnum.set_global_gen(gen)
|
||||
HandlesAnnAssign.set_global_gen(gen)
|
||||
HandlesAugAssign.set_global_gen(gen)
|
||||
HandlesVar.set_global_gen(gen)
|
||||
HandlesTranslator.set_global_gen(gen)
|
||||
HandlesMain.set_global_gen(gen)
|
||||
# 设置当前文件名(供报错使用)
|
||||
HandlesType.set_current_file(file_path)
|
||||
# 同步到 HandlesImports(import 时 SHA1 检查报错需要当前文件名,循环依赖无法直接读 HandlesType)
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
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.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# AssignGenMixin - 赋值翻译 Mixin(P6 方法化)
|
||||
#
|
||||
# 从 HandlesAssign/HandlesAnnAssign/HandlesAugAssign 迁移:
|
||||
# 模块级无状态函数(trans/pool 首参)→ 类方法;全局状态
|
||||
# (HandlesAnnAssign._g_recover_found)→ 本类字段 RecoverFound。
|
||||
#
|
||||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 trans/pool 首参),仅函数体内的
|
||||
# 本模块函数调用改为 self.xxx(...)
|
||||
# 2. 外部模块调用(HandlesType.xxx/HandlesExpr.xxx 等)保留模块前缀
|
||||
# 3. 原 Handles 模块函数保留为"委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class AssignGenMixin:
|
||||
"""赋值翻译 Mixin(P6 方法化)"""
|
||||
|
||||
# --- 原 HandlesAnnAssign._g_recover_found 模块级全局(迁移为实例字段) ---
|
||||
RecoverFound: int
|
||||
|
||||
# ============================================================
|
||||
# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数)
|
||||
#
|
||||
# 支持两种形式:
|
||||
# 1. Attribute(Name('t'), 'CDefine')
|
||||
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
|
||||
# ============================================================
|
||||
def is_cdefine_annotation(self, annot: ast.AST | t.CPtr) -> int:
|
||||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if self.is_cdefine_annotation(bop.left) != 0:
|
||||
return 1
|
||||
if self.is_cdefine_annotation(bop.right) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
|
||||
#
|
||||
# 支持的表达式形式:
|
||||
# 1. Constant(INT) — 如 0x0002, 42
|
||||
# 2. BinOp(BitOr/BitAnd) — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
# 3. Name — 引用已注册的 CDefine 常量
|
||||
# 4. Call — 如 t.CUnsignedLong(-11) → 取第一个参数
|
||||
# 5. UnaryOp(USub/UAdd/Invert) — 如 -11
|
||||
# ============================================================
|
||||
def extract_cdefine_int_value(self, val_node: ast.AST | t.CPtr) -> int:
|
||||
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp)"""
|
||||
if val_node is None:
|
||||
return 0
|
||||
k: int = val_node.kind()
|
||||
|
||||
# Case 1: Constant(INT) — 如 0x0002
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||||
if cn.const_kind != ast.CONST_INT:
|
||||
return 0
|
||||
return cn.int_val
|
||||
|
||||
# Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node)
|
||||
left_val: int = self.extract_cdefine_int_value(bop.left)
|
||||
right_val: int = self.extract_cdefine_int_value(bop.right)
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
return left_val | right_val
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
return left_val & right_val
|
||||
if bop.op == ast.OpKind.Add:
|
||||
return left_val + right_val
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
return left_val - right_val
|
||||
return 0
|
||||
|
||||
# Case 3: Name — 引用已注册的 CDefine 常量
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node)
|
||||
if nm.id is not None:
|
||||
looked_up: int = HandlesType.lookup_cdefine_constant(nm.id)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return looked_up
|
||||
return 0
|
||||
|
||||
# Case 4: Call — 如 t.CUnsignedLong(-11)
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node)
|
||||
# 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||||
cl_args_list: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
if cl_args_list is not None and cl_args_list.__len__() > 0:
|
||||
first_arg: ast.AST | t.CPtr = cl_args_list.get(0)
|
||||
arg_val: int = self.extract_cdefine_int_value(first_arg)
|
||||
return arg_val
|
||||
return 0
|
||||
|
||||
# Case 5: UnaryOp — 如 -11
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node)
|
||||
operand_val: int = self.extract_cdefine_int_value(uop.operand)
|
||||
if uop.op == ast.OpKind.USub:
|
||||
return -operand_val
|
||||
if uop.op == ast.OpKind.UAdd:
|
||||
return operand_val
|
||||
if uop.op == ast.OpKind.Invert:
|
||||
return ~operand_val
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _register_cdefine_from_value - 注册 CDefine 常量(浮点/整数自动识别)
|
||||
#
|
||||
# 浮点字面量(如 vipermath 的 U_M_PI: t.CDefine = 3.14159...)走
|
||||
# register_cdefine_double,否则 translate_value 查表得 0 生成
|
||||
# ret i32 0(llc 报错 "value doesn't match function result type")。
|
||||
# ============================================================
|
||||
def _register_cdefine_from_value(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, val_node: ast.AST | t.CPtr) -> None:
|
||||
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数)"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
if val_node is not None and val_node.kind() == ast.ASTKind.Constant:
|
||||
cn_fp: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||||
if cn_fp.const_kind == ast.CONST_FLOAT:
|
||||
# 源文件重读恢复(最可靠:AST 节点 float_val 可能被 pool 操作覆写,
|
||||
# 源文件文本不受影响;用输出参数绕开跨模块 double 返回值传递 bug)
|
||||
use_val: double = cn_fp.float_val
|
||||
rec_d: t.CDouble = 0.0
|
||||
if self._recover_cdefine_float(name, t.CPtr(c.Addr(rec_d))) != 0:
|
||||
use_val = rec_d
|
||||
# CDEF-DBG: 打印 float_val 读取(定位浮点 CDefine 值错误)
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
# 位模式拆解:把 float_val / rec_d 的 8 字节拷贝到 u64,再拆高低 32 位
|
||||
# 用于确认"哪一半被覆写 + 被谁覆写"(若与 int_val/const_kind 位模式重叠即锁布局 bug)
|
||||
fv_bits: t.CUInt64T = 0
|
||||
string.memcpy(t.CVoid(t.CUInt64T(c.Addr(fv_bits)), t.CPtr),
|
||||
t.CVoid(t.CUInt64T(c.Addr(cn_fp.float_val)), t.CPtr), 8)
|
||||
rec_bits: t.CUInt64T = 0
|
||||
string.memcpy(t.CVoid(t.CUInt64T(c.Addr(rec_bits)), t.CPtr),
|
||||
t.CVoid(t.CUInt64T(c.Addr(rec_d)), t.CPtr), 8)
|
||||
stdio.snprintf(fb_cd, 1024,
|
||||
"REG-SRC: %s kind=%d const_kind=%d ptr=%p\n"
|
||||
" fv=%.17g %a hi=%08llx lo=%08llx\n"
|
||||
" int_val=%lld bits=%016llx const_kind_hex=%x str_val=%p\n"
|
||||
" rec=%.17g %a hi=%08llx lo=%08llx use=%.17g",
|
||||
name, val_node.kind(), cn_fp.const_kind, t.CSizeT(cn_fp),
|
||||
cn_fp.float_val, cn_fp.float_val,
|
||||
t.CUInt64T(fv_bits >> 32), t.CUInt64T(fv_bits & 0xFFFFFFFF),
|
||||
cn_fp.int_val, t.CUInt64T(cn_fp.int_val), cn_fp.const_kind,
|
||||
t.CSizeT(cn_fp.str_val),
|
||||
rec_d, rec_d,
|
||||
t.CUInt64T(rec_bits >> 32), t.CUInt64T(rec_bits & 0xFFFFFFFF),
|
||||
use_val)
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
HandlesType.register_cdefine_double(pool, name, use_val)
|
||||
return
|
||||
val_fp: int = self.extract_cdefine_int_value(val_node)
|
||||
HandlesType.register_cdefine_constant(pool, name, val_fp)
|
||||
|
||||
# ============================================================
|
||||
# 源文件重读恢复 CDefine 浮点值
|
||||
#
|
||||
# 背景:AST 节点的 float_val/str_val 字段可能被 pool 分配操作覆写
|
||||
# (MemBuddy 内存冲突),导致注册的浮点 CDefine 值错误(llc ret i32 0)。
|
||||
# 本函数直接读源文件找 "NAME: t.CDefine = value" 行,atof 解析 value——
|
||||
# 源文件文本不受 pool 影响,是最可靠的恢复路径。
|
||||
#
|
||||
# 原模块级 _g_recover_found 全局已迁移为实例字段 self.RecoverFound。
|
||||
# ============================================================
|
||||
|
||||
def _recover_found(self) -> int:
|
||||
"""检查最近一次 _recover_cdefine_float 是否成功"""
|
||||
return self.RecoverFound
|
||||
|
||||
def _recover_cdefine_float(self, name: str, out: t.CDouble | t.CPtr) -> int:
|
||||
"""从当前模块源文件恢复浮点 CDefine 值,写入 out[0],成功返回 1
|
||||
|
||||
用输出参数传递 double,避免 TPV 跨模块 double 返回值传递 bug。
|
||||
"""
|
||||
self.RecoverFound = 0
|
||||
fp: str = HandlesType.get_current_file()
|
||||
if fp is None or name is None or out is None:
|
||||
return 0
|
||||
f: fileio.File | t.CPtr = fileio.File(fp, fileio.MODE.R)
|
||||
if f.closed:
|
||||
return 0
|
||||
BUF_SZ: t.CSizeT = 1048576
|
||||
buf: bytes = stdlib.malloc(BUF_SZ)
|
||||
if buf is None:
|
||||
f.close()
|
||||
return 0
|
||||
nrd: LONG = f.read_all(buf, BUF_SZ)
|
||||
f.close()
|
||||
if nrd <= 0:
|
||||
stdlib.free(buf)
|
||||
return 0
|
||||
if nrd < BUF_SZ:
|
||||
buf[nrd] = 0
|
||||
else:
|
||||
buf[BUF_SZ - 1] = 0
|
||||
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
total_len: t.CSizeT = string.strlen(buf)
|
||||
pos: t.CSizeT = 0
|
||||
while pos < total_len:
|
||||
line_start: t.CSizeT = pos
|
||||
while pos < total_len and buf[pos] != '\n':
|
||||
pos += 1
|
||||
line_len: t.CSizeT = pos - line_start
|
||||
if pos < total_len:
|
||||
pos += 1
|
||||
|
||||
# 匹配 "name:"
|
||||
if line_len < name_len + 1:
|
||||
continue
|
||||
match_ok: int = 1
|
||||
ki: t.CSizeT
|
||||
for ki in range(name_len):
|
||||
if buf[line_start + ki] != name[ki]:
|
||||
match_ok = 0
|
||||
break
|
||||
if match_ok == 0:
|
||||
continue
|
||||
if buf[line_start + name_len] != ':':
|
||||
continue
|
||||
|
||||
# 行内包含 "t.CDefine"
|
||||
has_cd: int = 0
|
||||
ci: t.CSizeT = line_start + name_len + 1
|
||||
while ci + 8 <= line_start + line_len:
|
||||
if (buf[ci] == 't' and buf[ci + 1] == '.' and buf[ci + 2] == 'C' and
|
||||
buf[ci + 3] == 'D' and buf[ci + 4] == 'e' and buf[ci + 5] == 'f' and
|
||||
buf[ci + 6] == 'i' and buf[ci + 7] == 'n' and buf[ci + 8] == 'e'):
|
||||
has_cd = 1
|
||||
break
|
||||
ci += 1
|
||||
if has_cd == 0:
|
||||
continue
|
||||
|
||||
# 找 '='
|
||||
eq: t.CSizeT = line_start
|
||||
while eq < line_start + line_len and buf[eq] != '=':
|
||||
eq += 1
|
||||
if eq >= line_start + line_len:
|
||||
continue
|
||||
eq += 1
|
||||
while eq < line_start + line_len and buf[eq] == ' ':
|
||||
eq += 1
|
||||
val_start: t.CSizeT = eq
|
||||
while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' \
|
||||
and buf[eq] != '#' and buf[eq] != '\r' and buf[eq] != '\n':
|
||||
eq += 1
|
||||
if eq == val_start:
|
||||
continue
|
||||
|
||||
val_txt: str = stdlib.malloc(eq - val_start + 1)
|
||||
if val_txt is None:
|
||||
stdlib.free(buf)
|
||||
return 0
|
||||
vi: t.CSizeT
|
||||
for vi in range(eq - val_start):
|
||||
val_txt[vi] = buf[val_start + vi]
|
||||
val_txt[eq - val_start] = 0
|
||||
stdlib.free(buf)
|
||||
# 用 atof_out(输出参数)绕开跨模块 double 返回值传递 bug
|
||||
if string.atof_out(val_txt, out) != 0:
|
||||
self.RecoverFound = 1
|
||||
return 1
|
||||
return 0
|
||||
|
||||
stdlib.free(buf)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _annotation_contains_name - 递归检查注解中是否包含指定名称
|
||||
#
|
||||
# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。
|
||||
# ============================================================
|
||||
def _annotation_contains_name(self, annot: ast.AST | t.CPtr, name: str) -> int:
|
||||
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含"""
|
||||
if annot is None or name is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot)
|
||||
if nm.id is not None and string.strcmp(nm.id, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if self._annotation_contains_name(bop.left, name) != 0:
|
||||
return 1
|
||||
if self._annotation_contains_name(bop.right, name) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _is_ptr_element_annotation - 检查注解是否为 bytes|t.CPtr 或 str|t.CPtr
|
||||
#
|
||||
# 返回 1=是(下标按 8 字节步长, i8** 语义), 0=否(下标按 1 字节步长, i8* 语义)
|
||||
#
|
||||
# 规则:
|
||||
# bytes|t.CPtr / str|t.CPtr → i8**(8 字节步长)→ 返回 1
|
||||
# t.CChar|t.CPtr / t.CInt8T|t.CPtr → i8*(1 字节步长)→ 返回 0
|
||||
# 纯 bytes / str → i8*(1 字节步长)→ 返回 0
|
||||
#
|
||||
# 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算
|
||||
# ============================================================
|
||||
def _is_ptr_element_annotation(self, annot: ast.AST | t.CPtr) -> int:
|
||||
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k != ast.ASTKind.BinOp:
|
||||
return 0
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if bop.op != ast.OpKind.BitOr:
|
||||
return 0
|
||||
if self._annotation_contains_name(annot, "str") != 0:
|
||||
return 1
|
||||
if self._annotation_contains_name(annot, "bytes") != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _init_global_array_from_list — 从列表字面量初始化全局数组
|
||||
#
|
||||
# 为每个元素生成 GEP + store 指令,将值存入全局数组的对应位置。
|
||||
# 适用于模块级 t.CArray[elem_ty, count] = [v0, v1, ...] 的初始化。
|
||||
#
|
||||
# Args:
|
||||
# builder: IRBuilder
|
||||
# pool: 编译器内存池
|
||||
# mod: LLVMModule
|
||||
# array_alloca: 全局数组变量的 Value 引用(类型为 [N x elem_ty]*)
|
||||
# list_node: ast.List 节点
|
||||
# trans: Translator 对象
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,1 失败
|
||||
# ============================================================
|
||||
def _init_global_array_from_list(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
array_alloca: llvmlite.Value | t.CPtr,
|
||||
list_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""从列表字面量初始化全局数组,为每个元素生成 GEP + store"""
|
||||
if builder is None or array_alloca is None or list_node is None:
|
||||
return 1
|
||||
|
||||
# 获取数组类型(Pointee of [N x elem_ty]*)
|
||||
arr_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if array_alloca.Ty is not None:
|
||||
arr_ty = array_alloca.Ty.Pointee
|
||||
if arr_ty is None:
|
||||
return 1
|
||||
|
||||
# 匹配数组类型获取元素类型
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
match arr_ty:
|
||||
case llvmlite.LLVMType.Array(et, _):
|
||||
elem_ty = et
|
||||
if elem_ty is None:
|
||||
return 1
|
||||
|
||||
# 获取列表元素
|
||||
lst: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if lst is None or lst.elts is None:
|
||||
return 1
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = lst.elts
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 为每个元素生成 GEP + store
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
elem_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, elem_node, None, 0, trans)
|
||||
if elem_val is not None:
|
||||
idx_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, i)
|
||||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||||
builder, arr_ty, elem_ty, array_alloca, idx_val)
|
||||
if elem_ptr is not None:
|
||||
# 类型转换(如 i32 → i8 截断)
|
||||
store_val: llvmlite.Value | t.CPtr = elem_val
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, elem_val, elem_ptr.Ty.Pointee, elem_node)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr)
|
||||
i += 1
|
||||
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _apply_aug_op - 应用增强赋值的二元运算
|
||||
#
|
||||
# 支持浮点运算、指针算术: ptr += int / ptr -= int
|
||||
# 整数运算自动类型提升
|
||||
# ============================================================
|
||||
def _apply_aug_op(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
op: int,
|
||||
lhs: llvmlite.Value | t.CPtr,
|
||||
rhs: llvmlite.Value | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None,
|
||||
trans: HT.Translator | t.CPtr = None,
|
||||
lhs_node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""应用增强赋值的二元运算(浮点 + 指针算术 + 整数运算)"""
|
||||
lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty)
|
||||
rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty)
|
||||
lhs_fbits: int = HandlesExpr.get_llvm_float_bits(lhs.Ty)
|
||||
rhs_fbits: int = HandlesExpr.get_llvm_float_bits(rhs.Ty)
|
||||
|
||||
# 浮点运算: 任一操作数为浮点时,使用浮点指令(必须在指针算术之前检查,
|
||||
# 因为 float 的 int bits 为 0,会被误认为指针)
|
||||
if lhs_fbits != 0 or rhs_fbits != 0:
|
||||
# 确定目标浮点类型(使用较大的位宽)
|
||||
target_fbits: int = lhs_fbits
|
||||
if rhs_fbits > target_fbits:
|
||||
target_fbits = rhs_fbits
|
||||
target_float_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
if target_fbits == 32:
|
||||
target_float_ty = llvmlite.Float(pool)
|
||||
# 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc)
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, target_float_ty, node)
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, target_float_ty, node)
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_fadd(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Sub:
|
||||
return llvmlite.build_fsub(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mult:
|
||||
return llvmlite.build_fmul(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Div:
|
||||
return llvmlite.build_fdiv(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mod:
|
||||
return llvmlite.build_frem(builder, lhs, rhs)
|
||||
return None
|
||||
|
||||
# 指针算术: ptr += int / ptr -= int → getelementptr(按元素大小缩放)
|
||||
# 对齐 TPC HandlesAugAssign.py L140-149 / L170-180
|
||||
if lhs_bits == 0 and rhs_bits != 0:
|
||||
if op == ast.OpKind.Add or op == ast.OpKind.Sub:
|
||||
return HandlesExpr.translate_ptr_arith(pool, builder, lhs, rhs, op)
|
||||
return None
|
||||
|
||||
# 整数运算:类型提升
|
||||
if lhs_bits > rhs_bits and rhs_bits > 0:
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty, node)
|
||||
elif rhs_bits > lhs_bits and lhs_bits > 0:
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty, node)
|
||||
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_add(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Sub:
|
||||
return llvmlite.build_sub(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mult:
|
||||
return llvmlite.build_mul(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Div:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.FloorDiv:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mod:
|
||||
return llvmlite.build_srem(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitAnd:
|
||||
return llvmlite.build_and(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitOr:
|
||||
return llvmlite.build_or(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitXor:
|
||||
return llvmlite.build_xor(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.LShift:
|
||||
return llvmlite.build_shl(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.RShift:
|
||||
# 无符号 >> → lshr(逻辑右移),有符号 >> → ashr(算术右移)
|
||||
# 对齐 TPC ExprGen.emit_binary_op:i8/i16 默认无符号;其余查操作数无符号性
|
||||
if lhs_bits == 8 or lhs_bits == 16:
|
||||
return llvmlite.build_lshr(builder, lhs, rhs)
|
||||
if lhs_node is not None and trans is not None:
|
||||
if HandlesExpr._node_type_unsigned(pool, lhs_node, trans) != 0:
|
||||
return llvmlite.build_lshr(builder, lhs, rhs)
|
||||
return llvmlite.build_ashr(builder, lhs, rhs)
|
||||
return None
|
||||
@@ -9,6 +9,11 @@ import lib.core.Gen.ExprGenMixin as ExprGenMixin
|
||||
import lib.core.Gen.CallGenMixin as CallGenMixin
|
||||
import lib.core.Gen.FuncGenMixin as FuncGenMixin
|
||||
import lib.core.Gen.ClassGenMixin as ClassGenMixin
|
||||
import lib.core.Gen.ImportsGenMixin as ImportsGenMixin
|
||||
import lib.core.Gen.StmtGenMixin as StmtGenMixin
|
||||
import lib.core.Gen.AssignGenMixin as AssignGenMixin
|
||||
import lib.core.Gen.VarGenMixin as VarGenMixin
|
||||
import lib.core.Gen.TranslatorGenMixin as TranslatorGenMixin
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
@@ -29,7 +34,9 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
|
||||
StructGenMixin.StructGenMixin, ExprGenMixin.ExprGenMixin,
|
||||
CallGenMixin.CallGenMixin, FuncGenMixin.FuncGenMixin,
|
||||
ClassGenMixin.ClassGenMixin):
|
||||
ClassGenMixin.ClassGenMixin, ImportsGenMixin.ImportsGenMixin,
|
||||
StmtGenMixin.StmtGenMixin, AssignGenMixin.AssignGenMixin,
|
||||
VarGenMixin.VarGenMixin, TranslatorGenMixin.TranslatorGenMixin):
|
||||
"""生成器:多继承 Mixin 组合(对象化迁移宿主)"""
|
||||
|
||||
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
|
||||
@@ -112,6 +119,17 @@ class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
|
||||
self.VtMethodNames = None
|
||||
self.VtParentSha1s = None
|
||||
self.VtMethodCount = 0
|
||||
# ---- ImportsGenMixin 字段 ----
|
||||
self.ReexportSha1s = None
|
||||
self.ReexportFuncs = None
|
||||
self.ReexportSrcs = None
|
||||
self.ReexportCount = 0
|
||||
# ---- StmtGenMixin 字段 ----
|
||||
self.CifEvalOk = 0
|
||||
self.EnumTable = None
|
||||
self.EnumCount = 0
|
||||
# ---- AssignGenMixin 字段 ----
|
||||
self.RecoverFound = 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -0,0 +1,622 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import stdio
|
||||
import sys
|
||||
import w32.fileio as fileio
|
||||
import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ImportsGenMixin - 导入处理 Mixin(对象化 P6-D,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 从 HandlesImports.vp 迁移:
|
||||
# 全局状态(_g_reexport_sha1s/_g_reexport_funcs/_g_reexport_srcs/
|
||||
# _g_reexport_count/_g_current_file)→ 本类字段
|
||||
# 模块级函数(add_imported_module/is_module_imported/...)→ 本类方法
|
||||
#
|
||||
# 迁移原则(与 P1-P5 Mixin 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 pool 首参),仅函数体内的全局变量改为 self.字段
|
||||
# 2. 本模块内部函数调用改为 self.方法;跨模块调用(StubMerger 等)保留模块前缀
|
||||
# 3. HandlesImports.vp 原函数保留为"委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesImports 保持一致)
|
||||
# ============================================================
|
||||
MAX_REEXPORT: t.CDefine = 512
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ImportsGenMixin - 导入处理
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ImportsGenMixin:
|
||||
"""导入处理 Mixin(P6 方法化)"""
|
||||
|
||||
# --- 全局 re-export 映射表(原 _g_reexport_sha1s/_g_reexport_funcs/
|
||||
# _g_reexport_srcs/_g_reexport_count) ---
|
||||
ReexportSha1s: bytes
|
||||
ReexportFuncs: bytes
|
||||
ReexportSrcs: bytes
|
||||
ReexportCount: int
|
||||
|
||||
# 注意:不声明 CurrentFile 字段——TypeGenMixin 已声明(Generator 展平块
|
||||
# 只有一份,跨父类不去重规则下重复声明会导致字段错位)。本 Mixin 的
|
||||
# set_current_file 与 CurrentFile 读取统一经 HandlesType 委托(延迟 import
|
||||
# 规避 HandlesType↔HandlesImports 循环依赖)。
|
||||
|
||||
# ============================================================
|
||||
# 添加已导入模块名
|
||||
# ============================================================
|
||||
def add_imported_module(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
imported_modules: str,
|
||||
name: str) -> str:
|
||||
"""记录已导入的模块名,返回新的 imported_modules 字符串指针"""
|
||||
if name is None:
|
||||
return imported_modules
|
||||
if imported_modules is None:
|
||||
nlen: t.CSizeT = string.strlen(name)
|
||||
buf: t.CChar | t.CPtr = pool.alloc(nlen + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, name)
|
||||
return buf
|
||||
return None
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(imported_modules)
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
new_len: t.CSizeT = old_len + 1 + name_len
|
||||
buf2: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf2 is not None:
|
||||
string.strcpy(buf2, imported_modules)
|
||||
buf2[old_len] = ' '
|
||||
string.strcpy(buf2 + old_len + 1, name)
|
||||
return buf2
|
||||
return imported_modules
|
||||
|
||||
# ============================================================
|
||||
# 检查模块是否已导入
|
||||
# ============================================================
|
||||
def is_module_imported(self, imported_modules: str, name: str) -> int:
|
||||
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配)"""
|
||||
if name is None or imported_modules is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = imported_modules
|
||||
total_len: t.CSizeT = string.strlen(imported_modules)
|
||||
ci: t.CSizeT = 0
|
||||
while ci < total_len:
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
word_start: t.CSizeT = ci
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
word_len: t.CSizeT = ci - word_start
|
||||
if word_len == name_len:
|
||||
match: int = 1
|
||||
for ei in range(name_len):
|
||||
if cur[word_start + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
if match == 1:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 添加 from-import 名称映射
|
||||
# ============================================================
|
||||
def add_from_import(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
from_imports: str,
|
||||
local_name: str,
|
||||
module_name: str,
|
||||
original_name: str = None) -> str:
|
||||
"""添加 from-import 映射,返回新的 from_imports 字符串
|
||||
|
||||
格式:
|
||||
无别名: "local_name:module_name"
|
||||
有别名: "local_name:module_name:original_name"
|
||||
(original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰)
|
||||
"""
|
||||
if local_name is None or module_name is None:
|
||||
return from_imports
|
||||
entry: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if entry is None:
|
||||
return from_imports
|
||||
if original_name is not None and string.strcmp(original_name, local_name) != 0:
|
||||
viperlib.snprintf(entry, 256, "%s:%s:%s", local_name, module_name, original_name)
|
||||
else:
|
||||
viperlib.snprintf(entry, 256, "%s:%s", local_name, module_name)
|
||||
if from_imports is None:
|
||||
return entry
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(from_imports)
|
||||
entry_len: t.CSizeT = string.strlen(entry)
|
||||
new_len: t.CSizeT = old_len + 1 + entry_len
|
||||
buf: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, from_imports)
|
||||
buf[old_len] = ' '
|
||||
string.strcpy(buf + old_len + 1, entry)
|
||||
return buf
|
||||
return from_imports
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回原始函数名(别名场景)
|
||||
#
|
||||
# 对于 from X import Y as Z,返回 Y(源模块中的真实函数名)。
|
||||
# 无别名时返回 None(local_name 即为原始名)。
|
||||
# ============================================================
|
||||
def lookup_from_import_original(self, from_imports: str,
|
||||
local_name: str) -> str:
|
||||
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到"""
|
||||
if local_name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(local_name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到第一个 ':' 的位置
|
||||
colon1: t.CSizeT = ci
|
||||
while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ':
|
||||
colon1 += 1
|
||||
if colon1 >= total_len or cur[colon1] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon1 - ci
|
||||
# 跳过 star import
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
continue
|
||||
# 比较名称
|
||||
if entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != local_name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
# 找到匹配,检查是否有第三个字段(原始名)
|
||||
pos: t.CSizeT = colon1 + 1
|
||||
# 跳过模块名
|
||||
while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0':
|
||||
pos += 1
|
||||
if pos < total_len and cur[pos] == ':':
|
||||
# 有第三个字段: original_name
|
||||
orig_start: t.CSizeT = pos + 1
|
||||
orig_end: t.CSizeT = orig_start
|
||||
while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0':
|
||||
orig_end += 1
|
||||
orig_len: t.CSizeT = orig_end - orig_start
|
||||
if orig_len > 0:
|
||||
orig_buf: str = cur + orig_start
|
||||
# 返回指向内部的指针(调用方需在使用期内保持 from_imports 有效)
|
||||
return orig_buf
|
||||
return None
|
||||
return None
|
||||
# 跳到下一个条目
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回模块名或 None
|
||||
#
|
||||
# allow_star_fallback: 是否允许 star import 回退(默认 1=允许)。
|
||||
# 当查询明确模块名(如 "BuildPipeline")时,应传 0 禁用回退,
|
||||
# 避免被 star import 模块名误导(如 from stdint import * 后
|
||||
# 查询 "BuildPipeline" 错误回退到 "stdint")。
|
||||
# ============================================================
|
||||
def lookup_from_import(self, from_imports: str, name: str,
|
||||
allow_star_fallback: int = 1) -> str:
|
||||
"""查找 from-import 名称,返回模块名或 None
|
||||
|
||||
支持 star import: 如果 from_imports 中有 "*:module" 条目,
|
||||
且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。
|
||||
"""
|
||||
if name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
star_mod: str = None
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到 ':' 的位置
|
||||
colon_pos: t.CSizeT = ci
|
||||
while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ':
|
||||
colon_pos += 1
|
||||
if colon_pos >= total_len or cur[colon_pos] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon_pos - ci
|
||||
# 检测 star import ("*:module")
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
mod_start: t.CSizeT = colon_pos + 1
|
||||
mod_end: t.CSizeT = mod_start
|
||||
while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':':
|
||||
mod_end += 1
|
||||
star_mod = cur + mod_start
|
||||
# 比较名称
|
||||
elif entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
mod_start2: t.CSizeT = colon_pos + 1
|
||||
mod_end2: t.CSizeT = mod_start2
|
||||
# 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符)
|
||||
while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':':
|
||||
mod_end2 += 1
|
||||
return cur + mod_start2
|
||||
# 跳到下一个条目
|
||||
ci = colon_pos
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
# 未找到精确匹配,仅在允许时回退到 star import
|
||||
if allow_star_fallback == 0:
|
||||
return None
|
||||
return star_mod
|
||||
|
||||
# ============================================================
|
||||
# register_reexport - 注册 re-export 映射
|
||||
#
|
||||
# 在 HandleImportFromNames 中调用:当处理 from .X import Y 时,
|
||||
# 记录当前模块(通过 ModuleSha1)re-export 了函数 Y,源模块为 X。
|
||||
#
|
||||
# 幂等:重复注册相同映射不会增加条目。
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。
|
||||
# ============================================================
|
||||
def register_reexport(self, mod_sha1: str, func_name: str, source_module: str) -> int:
|
||||
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败"""
|
||||
if mod_sha1 is None or func_name is None or source_module is None:
|
||||
return -1
|
||||
# 懒初始化
|
||||
if self.ReexportSha1s is None:
|
||||
self.ReexportSha1s = stdlib.malloc(MAX_REEXPORT * 17)
|
||||
self.ReexportFuncs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
self.ReexportSrcs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
if self.ReexportSha1s is None or self.ReexportFuncs is None or self.ReexportSrcs is None:
|
||||
return -1
|
||||
string.memset(self.ReexportSha1s, 0, MAX_REEXPORT * 17)
|
||||
string.memset(self.ReexportFuncs, 0, MAX_REEXPORT * 64)
|
||||
string.memset(self.ReexportSrcs, 0, MAX_REEXPORT * 64)
|
||||
if self.ReexportCount >= MAX_REEXPORT:
|
||||
return -1
|
||||
# 幂等检查:查找是否已存在相同映射
|
||||
for i in range(self.ReexportCount):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(self.ReexportSha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(self.ReexportFuncs + fidx, func_name) == 0:
|
||||
# 已存在,更新 source_module(以防变化;64 字节槽,strncpy 钳制)
|
||||
string.strncpy(self.ReexportSrcs + fidx, source_module, 63)
|
||||
self.ReexportSrcs[fidx + 63] = '\0'
|
||||
return 0
|
||||
# 添加新条目(槽位定长 17/64 字节,strcpy 无界会越界写相邻槽,全部 strncpy 钳制)
|
||||
idx2: t.CSizeT = t.CSizeT(self.ReexportCount) * 17
|
||||
fidx2: t.CSizeT = t.CSizeT(self.ReexportCount) * 64
|
||||
string.strncpy(self.ReexportSha1s + idx2, mod_sha1, 16)
|
||||
self.ReexportSha1s[idx2 + 16] = '\0'
|
||||
string.strncpy(self.ReexportFuncs + fidx2, func_name, 63)
|
||||
self.ReexportFuncs[fidx2 + 63] = '\0'
|
||||
string.strncpy(self.ReexportSrcs + fidx2, source_module, 63)
|
||||
self.ReexportSrcs[fidx2 + 63] = '\0'
|
||||
self.ReexportCount += 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# lookup_reexport - 查找 re-export 映射
|
||||
#
|
||||
# 给定模块 SHA1 和函数名,返回源模块名(如 "ast.lexer")或 None。
|
||||
# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。
|
||||
# ============================================================
|
||||
def lookup_reexport(self, mod_sha1: str, func_name: str) -> str:
|
||||
"""查找 re-export 映射,返回源模块名或 None"""
|
||||
if mod_sha1 is None or func_name is None:
|
||||
return None
|
||||
if self.ReexportSha1s is None or self.ReexportCount <= 0:
|
||||
return None
|
||||
for i in range(self.ReexportCount):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(self.ReexportSha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(self.ReexportFuncs + fidx, func_name) == 0:
|
||||
return self.ReexportSrcs + fidx
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# _resolve_relative_module - 解析相对导入为完整模块名
|
||||
#
|
||||
# 对于 from .X import Y(level=1, module="X")在包 pkg 中:
|
||||
# 解析为 "pkg.X"
|
||||
# 对于 from . import Y(level=1, module=None)在包 pkg 中:
|
||||
# 解析为 "pkg"
|
||||
# 对于 from ..X import Y(level=2, module="X")在包 pkg.sub 中:
|
||||
# 解析为 "pkg.X"(先从 pkg.sub 上溯一级到 pkg,再追加 .X)
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# current_package: 当前文件所属包名(如 "llvmlite"),None 表示无包
|
||||
# level: 相对导入级别(0=绝对,1=., 2=..)
|
||||
# module: ImportFrom 的 module 字段(可能为 None)
|
||||
#
|
||||
# Returns:
|
||||
# 解析后的完整模块名;绝对导入(level<=0)直接返回 module;
|
||||
# 无法解析时返回 module(回退到原始值)
|
||||
# ============================================================
|
||||
def _resolve_relative_module(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
current_package: str,
|
||||
level: t.CInt,
|
||||
module: str) -> str:
|
||||
"""解析相对导入为完整模块名"""
|
||||
if level <= 0:
|
||||
return module
|
||||
if current_package is None:
|
||||
return module
|
||||
|
||||
# 从 current_package 开始,上溯 (level-1) 级
|
||||
pkg: str = current_package
|
||||
up: t.CInt = level - 1
|
||||
while up > 0:
|
||||
pkg_len: t.CSizeT = string.strlen(pkg)
|
||||
last_dot: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < pkg_len:
|
||||
if pkg[i] == '.':
|
||||
last_dot = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无更多父级,包变为空
|
||||
pkg = None
|
||||
break
|
||||
# 截断到最后一个 '.' 处
|
||||
new_pkg: str = pool.alloc(last_dot + 1)
|
||||
if new_pkg is None:
|
||||
return module
|
||||
string.strncpy(new_pkg, pkg, last_dot)
|
||||
new_pkg[last_dot] = '\0'
|
||||
pkg = new_pkg
|
||||
up -= 1
|
||||
|
||||
if module is None:
|
||||
# from . import Y → 模块就是包本身
|
||||
return pkg
|
||||
if pkg is None:
|
||||
# 包已上溯到空,直接用 module
|
||||
return module
|
||||
# 拼接 pkg + "." + module
|
||||
pkg_len2: t.CSizeT = string.strlen(pkg)
|
||||
mod_len: t.CSizeT = string.strlen(module)
|
||||
buf: str = pool.alloc(pkg_len2 + 1 + mod_len + 1)
|
||||
if buf is None:
|
||||
return module
|
||||
string.strcpy(buf, pkg)
|
||||
buf[pkg_len2] = '.'
|
||||
string.strcpy(buf + pkg_len2 + 1, module)
|
||||
return buf
|
||||
|
||||
# ============================================================
|
||||
# compute_package_from_relpath - 从相对路径计算包名
|
||||
#
|
||||
# 包名 = 文件所在目录路径,将 / 和 \ 替换为 .
|
||||
# 对于顶级文件(无目录分隔符),返回 None
|
||||
#
|
||||
# 示例:
|
||||
# "llvmlite/__init__.vp" → "llvmlite"
|
||||
# "llvmlite/__types.vp" → "llvmlite"
|
||||
# "ast/parser.vp" → "ast"
|
||||
# "ast.vp" → None(顶级文件)
|
||||
# ============================================================
|
||||
def compute_package_from_relpath(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
rel_path: str) -> str:
|
||||
"""从相对路径计算包名(目录部分,分隔符替换为 .)"""
|
||||
if rel_path is None:
|
||||
return None
|
||||
rlen: t.CSizeT = string.strlen(rel_path)
|
||||
# 找最后一个 / 或 \
|
||||
last_sep: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < rlen:
|
||||
ch: t.CChar = rel_path[i]
|
||||
if ch == '/' or ch == '\\':
|
||||
last_sep = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无目录分隔符 → 顶级文件,无包
|
||||
return None
|
||||
# 复制目录部分,将 / 和 \ 替换为 .
|
||||
dir_len: t.CSizeT = last_sep
|
||||
buf: str = pool.alloc(dir_len + 1)
|
||||
if buf is None:
|
||||
return None
|
||||
j: t.CSizeT = 0
|
||||
while j < dir_len:
|
||||
ch2: t.CChar = rel_path[j]
|
||||
if ch2 == '/' or ch2 == '\\':
|
||||
buf[j] = '.'
|
||||
else:
|
||||
buf[j] = ch2
|
||||
j += 1
|
||||
buf[dir_len] = '\0'
|
||||
return buf
|
||||
|
||||
# ============================================================
|
||||
# set_current_file - 设置当前编译的文件名
|
||||
#
|
||||
# 与 TypeGenMixin.set_current_file 行为一致(写 CurrentFile 字段),
|
||||
# BuildPipeline/Phase1 通过 HandlesImports.set_current_file 委托调用。
|
||||
# 经 HandlesType 委托(延迟 import 规避循环依赖),字段由 TypeGenMixin 持有。
|
||||
# ============================================================
|
||||
def set_current_file(self, file_path: str) -> None:
|
||||
"""设置当前正在编译的文件名(与 HandlesType.set_current_file 同步调用)"""
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
HandlesType.set_current_file(file_path)
|
||||
|
||||
# ============================================================
|
||||
# _report_import_error - 本地实现 Python 风格报错(避免循环依赖)
|
||||
#
|
||||
# 无法访问 HandlesType.fatal_error(HandlesType import 了本模块,
|
||||
# 若本模块再 import HandlesType 会形成循环依赖),这里用简化格式:
|
||||
# Traceback (most recent call last):
|
||||
# File "<当前文件>", line <N>
|
||||
# ImportError: <msg>
|
||||
# ============================================================
|
||||
def _report_import_error(self, node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
"""以 Python 风格报错并退出(本地实现,避免循环依赖)"""
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
stdio.printf("Traceback (most recent call last):\n")
|
||||
lineno: int = 0
|
||||
if node is not None:
|
||||
lineno = node.lineno
|
||||
file_name: str = HandlesType.get_current_file()
|
||||
if file_name is None:
|
||||
file_name = "<unknown>"
|
||||
stdio.printf(' File "%s", line %d\n', file_name, lineno)
|
||||
# 显示行内内容(读源文件第 lineno 行的实际代码,便于快速定位)
|
||||
if lineno > 0 and file_name is not None:
|
||||
f_err: fileio.File | t.CPtr = fileio.File(file_name, fileio.MODE.R)
|
||||
if not f_err.closed:
|
||||
line_buf_err: bytes = stdlib.malloc(512)
|
||||
if line_buf_err is not None:
|
||||
cur_ln: int = 0
|
||||
while cur_ln < lineno:
|
||||
r_err: LONG = f_err.readline(line_buf_err, 511)
|
||||
if r_err <= 0:
|
||||
break
|
||||
cur_ln += 1
|
||||
if cur_ln == lineno:
|
||||
ll_err: t.CSizeT = string.strlen(line_buf_err)
|
||||
while ll_err > 0 and (line_buf_err[ll_err - 1] == '\n' or line_buf_err[ll_err - 1] == '\r'):
|
||||
ll_err -= 1
|
||||
line_buf_err[ll_err] = '\0'
|
||||
stdio.printf(" %s\n", line_buf_err)
|
||||
break
|
||||
stdlib.free(line_buf_err)
|
||||
f_err.close()
|
||||
stdio.printf("ImportError: %s\n", msg)
|
||||
sys.exit(1)
|
||||
|
||||
# ============================================================
|
||||
# _is_local_module_file - 当前文件同目录存在 {mod_name}.vp/.py
|
||||
#
|
||||
# 多文件项目(如 Test/G4/App 的 caller1.vp import g4node)的兄弟模块
|
||||
# 不在 includes 扫描存储器中(SHA1 在项目源文件列表),检查应豁免。
|
||||
# ============================================================
|
||||
def _is_local_module_file(self, mod_name: str) -> int:
|
||||
"""当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块"""
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
cur: str = HandlesType.get_current_file()
|
||||
if cur is None or mod_name is None:
|
||||
return 0
|
||||
cur_len: t.CSizeT = string.strlen(cur)
|
||||
if cur_len == 0:
|
||||
return 0
|
||||
sep_pos: t.CSizeT = cur_len
|
||||
while sep_pos > 0:
|
||||
sep_pos -= 1
|
||||
ch: t.CChar = cur[sep_pos]
|
||||
if ch == '/' or ch == '\\':
|
||||
sep_pos += 1
|
||||
break
|
||||
mod_len: t.CSizeT = string.strlen(mod_name)
|
||||
path_len: t.CSizeT = sep_pos + mod_len + 5
|
||||
path_buf: bytes = stdlib.malloc(path_len + 1)
|
||||
if path_buf is None:
|
||||
return 0
|
||||
# .vp 文件
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".vp")
|
||||
fex: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex.closed:
|
||||
fex.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
# .py 文件(Python 模块可能无 .vp)
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".py")
|
||||
fex2: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex2.closed:
|
||||
fex2.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
stdlib.free(path_buf)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _check_import_sha1 - 导入时校验模块 SHA1 是否已注册(fast-fail)
|
||||
#
|
||||
# 背景:若 includes 路径配置错误(如 project.json 指向不存在的
|
||||
# ./includes),includes 扫描结果为 0,模块不会注册 SHA1。此前
|
||||
# 错误延迟到实际调用 module.func() 时才报误导性的
|
||||
# "跨模块调用 'bd.alloc' 找不到模块 SHA1"。
|
||||
# 现在在 import 语句处立即检测并报错,快速定位配置问题。
|
||||
#
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查。
|
||||
# ============================================================
|
||||
def _check_import_sha1(self, node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出
|
||||
|
||||
Args:
|
||||
node: Import/ImportFrom AST 节点(提供行号)
|
||||
mod_name: 导入的模块名(如 "memhub"、"w32.fileio")
|
||||
|
||||
Returns:
|
||||
1=检查通过;模块未注册时直接报错退出(不会返回 0)
|
||||
"""
|
||||
if mod_name is None:
|
||||
return 1
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查
|
||||
if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0:
|
||||
return 1
|
||||
mod_sha1: str = StubMerger.LookupSha1ByModName(mod_name)
|
||||
if mod_sha1 is None:
|
||||
# App 兄弟模块豁免:当前文件同目录存在 {mod_name}.vp/.py
|
||||
# (如 Test/G4/App/caller1.vp import g4node——同项目源文件,
|
||||
# SHA1 在项目文件列表而非 includes 扫描存储器,不应报错)
|
||||
if self._is_local_module_file(mod_name) != 0:
|
||||
return 1
|
||||
err_buf: t.CChar | t.CPtr = stdlib.malloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256,
|
||||
"模块 '%s' 未注册 SHA1(includes 扫描未找到该模块,请检查 project.json 的 includes 路径配置)",
|
||||
mod_name)
|
||||
self._report_import_error(node, err_buf)
|
||||
else:
|
||||
self._report_import_error(node, "导入模块 SHA1 未注册(includes 扫描未找到该模块)")
|
||||
return 1
|
||||
@@ -0,0 +1,967 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesMatch as HandlesMatch
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StmtGenMixin - 语句/流程翻译 Mixin(P6 对象化重构 A 组)
|
||||
#
|
||||
# 迁移自 HandlesBody/HandlesIf/HandlesWhile/HandlesFor/HandlesReturn/
|
||||
# HandlesNonlocal/HandlesMatch/HandlesEnum 的模块级函数(trans 首参
|
||||
# 或无状态纯函数 + NewXxxHandle 工厂)→ 类方法;全局状态
|
||||
# (_g_cif_eval_ok/_enum_table/_enum_count)→ 本类字段。
|
||||
#
|
||||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 trans/pool 首参),仅函数体内的
|
||||
# 本模块函数调用改为 self.xxx(...)
|
||||
# 2. 外部模块调用(HandlesVar.xxx/HandlesExpr.xxx/HandlesType.xxx
|
||||
# 等)保留模块前缀(对应模块保留委托层)
|
||||
# 3. trans.XxxH.Handle(...) 子 Handle 分派保留(Handle 类不动,
|
||||
# 由 HandlesTranslator._init_state 通过 NewXxxHandle 工厂创建)
|
||||
# 4. 原 Handles 模块函数保留为"委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型调本类方法
|
||||
# 5. HandlesIf._g_cif_eval_ok → self.CifEvalOk;HandlesEnum
|
||||
# _enum_table/_enum_count → self.EnumTable/self.EnumCount
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesEnum 保持一致,本地副本避免跨模块 CDefine 查找 bug)
|
||||
# ============================================================
|
||||
ENUM_MAX: t.CDefine = 64
|
||||
ENUM_MEMBER_MAX: t.CDefine = 128
|
||||
|
||||
|
||||
# ============================================================
|
||||
# StmtGenMixin - 语句/流程翻译(P6 方法化)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class StmtGenMixin:
|
||||
"""语句/流程翻译 Mixin(P6 方法化)
|
||||
|
||||
迁移自 HandlesBody/HandlesIf/HandlesWhile/HandlesFor/HandlesReturn/
|
||||
HandlesNonlocal/HandlesMatch/HandlesEnum 的模块级函数
|
||||
"""
|
||||
|
||||
# --- 编译期 CIf 求值状态(原 HandlesIf._g_cif_eval_ok) ---
|
||||
CifEvalOk: int
|
||||
|
||||
# --- 枚举注册表(原 HandlesEnum._enum_table/_enum_count) ---
|
||||
EnumTable: HandlesEnum.EnumEntry | t.CPtr
|
||||
EnumCount: int
|
||||
|
||||
# ============================================================
|
||||
# 簇 A:语句分派/流程语句(迁移自 HandlesBody.vp)
|
||||
# ============================================================
|
||||
|
||||
def translate_stmt(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译单条语句,返回新增的变量数"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
if k == ast.ASTKind.Expr:
|
||||
return self.translate_expr_stmt(trans, node)
|
||||
elif k == ast.ASTKind.Assign:
|
||||
return trans.AssignH.Handle(node)
|
||||
elif k == ast.ASTKind.AnnAssign:
|
||||
return trans.AnnAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.FunctionDef:
|
||||
# 嵌套函数定义:提升为顶层函数 + 创建闭包
|
||||
return HandlesFunctions.translate_nested_function_def(trans, node)
|
||||
elif k == ast.ASTKind.Return:
|
||||
return trans.ReturnH.Handle(node)
|
||||
elif k == ast.ASTKind.If:
|
||||
return trans.IfH.Handle(node)
|
||||
elif k == ast.ASTKind.While:
|
||||
return trans.WhileH.Handle(node)
|
||||
elif k == ast.ASTKind.AugAssign:
|
||||
return trans.AugAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.For:
|
||||
return trans.ForH.Handle(node)
|
||||
elif k == ast.ASTKind.ClassDef:
|
||||
return HandlesClassDef.translate_class_def(trans, node)
|
||||
elif k == ast.ASTKind.Import:
|
||||
return trans.ImportsH.HandleImport(node)
|
||||
elif k == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(node)
|
||||
return trans.ImportsH.HandleImportFromNames(node)
|
||||
elif k == ast.ASTKind.Global:
|
||||
return self.translate_global(trans, node)
|
||||
elif k == ast.ASTKind.Nonlocal:
|
||||
return self.translate_nonlocal(trans, node)
|
||||
elif k == ast.ASTKind.Pass:
|
||||
return 0
|
||||
elif k == ast.ASTKind.Break:
|
||||
return self.translate_break(trans)
|
||||
elif k == ast.ASTKind.Continue:
|
||||
return self.translate_continue(trans)
|
||||
elif k == ast.ASTKind.Match:
|
||||
return trans.MatchH.Handle(node)
|
||||
elif k == ast.ASTKind.Delete:
|
||||
return self.translate_delete(trans, node)
|
||||
return 0
|
||||
|
||||
def translate_delete(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 del 语句,返回 0"""
|
||||
if trans is None or node is None:
|
||||
return 0
|
||||
dnode: ast.Delete | t.CPtr = (ast.Delete | t.CPtr)(node)
|
||||
if dnode is None or dnode.targets is None:
|
||||
return 0
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
if pool is None or mod is None or builder is None:
|
||||
return 0
|
||||
tn: t.CSizeT = dnode.targets.__len__()
|
||||
for ti in range(tn):
|
||||
tgt: ast.AST | t.CPtr = dnode.targets.get(ti)
|
||||
if tgt is None:
|
||||
continue
|
||||
# del obj.attr → property deleter
|
||||
if tgt.kind() == ast.ASTKind.Attribute:
|
||||
del_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(tgt)
|
||||
if del_at is not None:
|
||||
HandlesExprCall._try_property_deleter(
|
||||
pool, builder, mod, del_at, trans)
|
||||
return 0
|
||||
|
||||
def translate_global(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 global 语句:记录 global 变量名"""
|
||||
gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node)
|
||||
if gn is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = gn.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
HT.add_global_name(trans, nm.id)
|
||||
return 0
|
||||
|
||||
def translate_nonlocal(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 nonlocal 语句:记录 nonlocal 变量名及其类型
|
||||
|
||||
类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。
|
||||
"""
|
||||
nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node)
|
||||
if nl is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = nl.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
# 查找父作用域中的变量 alloca,获取类型信息
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, nm.id)
|
||||
if var_alloca is not None and var_alloca.Ty is not None:
|
||||
var_ty = var_alloca.Ty.Pointee
|
||||
# Void 类型视为无效(Pointee 访问异常时可能返回 Void),
|
||||
# 设为 None 让 add_nonlocal_name 回退为 i32,避免生成
|
||||
# "bitcast ... to void*" / "load void, void*" 非法 IR
|
||||
if var_ty is not None:
|
||||
match var_ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
var_ty = None
|
||||
case _:
|
||||
pass
|
||||
HT.add_nonlocal_name(trans, nm.id, var_ty)
|
||||
return 0
|
||||
|
||||
def translate_expr_stmt(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译表达式语句(printf 调用等)"""
|
||||
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
|
||||
if ex is None:
|
||||
return 0
|
||||
call_node: ast.AST | t.CPtr = ex.value
|
||||
if call_node is None:
|
||||
return 0
|
||||
ck: int = call_node.kind()
|
||||
if ck != ast.ASTKind.Call:
|
||||
return 0
|
||||
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node)
|
||||
func_node: ast.AST | t.CPtr = cl.func
|
||||
if func_node is None:
|
||||
return 0
|
||||
|
||||
func_name: str = HandlesExpr.get_func_name(func_node)
|
||||
if func_name is None:
|
||||
return 0
|
||||
|
||||
# printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf)
|
||||
if string.strcmp(func_name, "printf") == 0:
|
||||
trans.ExprCallH.HandlePrintfCall(cl)
|
||||
elif string.strcmp(func_name, "print") == 0:
|
||||
trans.ExprCallH.HandlePrintCall(cl)
|
||||
else:
|
||||
# 通用函数调用(返回值丢弃)
|
||||
trans.ExprCallH.HandleCall(call_node)
|
||||
return 0
|
||||
|
||||
def pre_scan_allocas(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描语句中的 AnnAssign,提前创建 alloca
|
||||
|
||||
返回新增的变量数
|
||||
"""
|
||||
if node is None:
|
||||
return 0
|
||||
return trans.AnnAssignH.PreScan(node)
|
||||
|
||||
def pre_scan_scope_decls(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描 Global/Nonlocal 声明,提前注册作用域名称"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Global:
|
||||
return self.translate_global(trans, node)
|
||||
if k == ast.ASTKind.Nonlocal:
|
||||
return self.translate_nonlocal(trans, node)
|
||||
return 0
|
||||
|
||||
def translate_break(self, trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 break 语句:跳转到循环 end 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 break 目标
|
||||
if trans._break_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._break_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句(break 后面的代码不可达)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
def translate_continue(self, trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 continue 目标
|
||||
if trans._continue_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._continue_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
def get_stmt_kind_name(self, node: ast.AST | t.CPtr) -> str:
|
||||
"""获取语句类型名"""
|
||||
if node is None:
|
||||
return None
|
||||
return node.type_name()
|
||||
|
||||
# ============================================================
|
||||
# 簇 B:编译期 CIf 宏求值(迁移自 HandlesIf.vp 模块级函数)
|
||||
# ============================================================
|
||||
|
||||
def _is_cif_attr(self, attr: str) -> int:
|
||||
"""检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)"""
|
||||
if attr is None:
|
||||
return 0
|
||||
if string.strcmp(attr, "CIf") == 0: return 1
|
||||
if string.strcmp(attr, "CIfdef") == 0: return 1
|
||||
if string.strcmp(attr, "CIfndef") == 0: return 1
|
||||
return 0
|
||||
|
||||
def _is_cif_call(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用"""
|
||||
if node is None or node.kind() != ast.ASTKind.Call:
|
||||
return 0
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if cl.func is None:
|
||||
return 0
|
||||
fk: int = cl.func.kind()
|
||||
if fk == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if at.attr is None:
|
||||
return 0
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if vn.id is not None and string.strcmp(vn.id, "c") == 0:
|
||||
return self._is_cif_attr(at.attr)
|
||||
return 0
|
||||
if fk == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func)
|
||||
if nm.id is not None and self._is_cif_attr(nm.id) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _get_platform_macro_value(self, name: str) -> int:
|
||||
"""平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。
|
||||
|
||||
命中置 self.CifEvalOk=1;未命中置 0 返回 0。
|
||||
"""
|
||||
self.CifEvalOk = 0
|
||||
if name is None:
|
||||
return 0
|
||||
triple: str = Config.TargetTriple
|
||||
if triple is None:
|
||||
triple = "x86_64-pc-windows-gnu"
|
||||
is_win: int = 0
|
||||
is_linux: int = 0
|
||||
is_x64: int = 0
|
||||
if string.strstr(triple, "windows") is not None \
|
||||
or string.strstr(triple, "win32") is not None \
|
||||
or string.strstr(triple, "mingw") is not None \
|
||||
or string.strstr(triple, "msvc") is not None:
|
||||
is_win = 1
|
||||
if string.strstr(triple, "linux") is not None:
|
||||
is_linux = 1
|
||||
if string.strstr(triple, "x86_64") is not None:
|
||||
is_x64 = 1
|
||||
# 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致)
|
||||
if string.strcmp(name, "_WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "WIN32") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "_WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "WIN64") == 0: self.CifEvalOk = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "__linux__") == 0: self.CifEvalOk = is_linux; return 1 if is_linux else 0
|
||||
if string.strcmp(name, "__x86_64__") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "__x86_64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "_M_X64") == 0: self.CifEvalOk = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "SIZEOF_VOID_P") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "__SIZEOF_POINTER__") == 0: self.CifEvalOk = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "NDEBUG") == 0: self.CifEvalOk = 1; return 0
|
||||
return 0
|
||||
|
||||
def _cif_name_value(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。
|
||||
|
||||
命中置 self.CifEvalOk=1(值 0 也算命中,如 DISABLED=0);未命中置 0。
|
||||
"""
|
||||
self.CifEvalOk = 0
|
||||
if name is None or trans is None:
|
||||
return 0
|
||||
v: int = HandlesType.lookup_cdefine_constant(name)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.CifEvalOk = 1
|
||||
return v
|
||||
v2: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, name, trans._from_imports, trans._imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.CifEvalOk = 1
|
||||
return v2
|
||||
pv: int = self._get_platform_macro_value(name)
|
||||
if self.CifEvalOk != 0:
|
||||
return pv
|
||||
return 0
|
||||
|
||||
def _cif_attr_value(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
at: ast.Attribute | t.CPtr) -> int:
|
||||
"""Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。
|
||||
|
||||
命中置 self.CifEvalOk=1;未命中置 0。
|
||||
"""
|
||||
self.CifEvalOk = 0
|
||||
if at is None or at.attr is None or at.value is None or trans is None:
|
||||
return 0
|
||||
if at.value.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if vn.id is None:
|
||||
return 0
|
||||
v: int = HandlesType.lookup_cdefine_constant(at.attr)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.CifEvalOk = 1
|
||||
return v
|
||||
# 跨模块: 确定真实模块名(解析 from_imports 别名)
|
||||
real_mod: str = vn.id
|
||||
if trans._from_imports is not None:
|
||||
resolved: str = HandlesImports.lookup_from_import(
|
||||
trans._from_imports, vn.id, 0)
|
||||
if resolved is not None:
|
||||
rm_len: t.CSizeT = 0
|
||||
while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':':
|
||||
rm_len += 1
|
||||
rm_buf: str = pool.alloc(rm_len + 1)
|
||||
if rm_buf is not None:
|
||||
for rm_i in range(rm_len):
|
||||
rm_buf[rm_i] = resolved[rm_i]
|
||||
rm_buf[rm_len] = '\0'
|
||||
real_mod = rm_buf
|
||||
fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod) + 2
|
||||
fi: str = pool.alloc(fi_len)
|
||||
if fi is None:
|
||||
return 0
|
||||
viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod)
|
||||
v2: int = HandlesExpr._lookup_cross_module_cdefine(pool, at.attr, fi)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
self.CifEvalOk = 1
|
||||
return v2
|
||||
return 0
|
||||
|
||||
def _cif_eval_node(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""递归常量求值 CIf 表达式。
|
||||
|
||||
支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine)
|
||||
/ BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=)
|
||||
/ BoolOp(and/or) / UnaryOp(not - + ~)。
|
||||
成功置 self.CifEvalOk=1;失败(含运行时变量)置 0 返回 0。
|
||||
"""
|
||||
if node is None:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
self.CifEvalOk = 1
|
||||
return cn.int_val
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is None:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
return self._cif_name_value(pool, trans, nm.id)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
return self._cif_attr_value(pool, trans, at)
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||||
if uop.operand is None:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
ov: int = self._cif_eval_node(pool, trans, uop.operand)
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0
|
||||
if uop.op == ast.OpKind.USub: return -ov
|
||||
if uop.op == ast.OpKind.UAdd: return ov
|
||||
if uop.op == ast.OpKind.Invert: return ~ov
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node)
|
||||
vals: list[ast.AST | t.CPtr] | t.CPtr = bo.values
|
||||
if vals is None:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
bn: t.CSizeT = vals.__len__()
|
||||
if bo.op == ast.OpKind.And:
|
||||
for bi in range(bn):
|
||||
rv: int = self._cif_eval_node(pool, trans, vals.get(bi))
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
if rv == 0:
|
||||
return 0
|
||||
return 1
|
||||
if bo.op == ast.OpKind.Or:
|
||||
for bi in range(bn):
|
||||
rv: int = self._cif_eval_node(pool, trans, vals.get(bi))
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
if rv != 0:
|
||||
return 1
|
||||
return 0
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node)
|
||||
lv: int = self._cif_eval_node(pool, trans, cmp.left)
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops)
|
||||
comps: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators
|
||||
if ops_list is None or comps is None:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
cc: t.CSizeT = comps.__len__()
|
||||
ci: t.CSizeT
|
||||
for ci in range(cc):
|
||||
rv: int = self._cif_eval_node(pool, trans, comps.get(ci))
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
op_id: int = ops_list.get(ci)
|
||||
ok_cmp: int = 0
|
||||
if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0
|
||||
elif op_id == ast.OpKind.Ne: ok_cmp = 1 if lv != rv else 0
|
||||
elif op_id == ast.OpKind.Lt: ok_cmp = 1 if lv < rv else 0
|
||||
elif op_id == ast.OpKind.Le: ok_cmp = 1 if lv <= rv else 0
|
||||
elif op_id == ast.OpKind.Gt: ok_cmp = 1 if lv > rv else 0
|
||||
elif op_id == ast.OpKind.Ge: ok_cmp = 1 if lv >= rv else 0
|
||||
else:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if ok_cmp == 0:
|
||||
return 0
|
||||
lv = rv
|
||||
return 1
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
lv: int = self._cif_eval_node(pool, trans, bop.left)
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
rv: int = self._cif_eval_node(pool, trans, bop.right)
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
if bop.op == ast.OpKind.Add: return lv + rv
|
||||
if bop.op == ast.OpKind.Sub: return lv - rv
|
||||
if bop.op == ast.OpKind.Mult: return lv * rv
|
||||
if bop.op == ast.OpKind.FloorDiv:
|
||||
if rv == 0:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.Mod:
|
||||
if rv == 0:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
return lv % rv
|
||||
if bop.op == ast.OpKind.BitAnd: return lv & rv
|
||||
if bop.op == ast.OpKind.BitOr: return lv | rv
|
||||
if bop.op == ast.OpKind.BitXor: return lv ^ rv
|
||||
if bop.op == ast.OpKind.LShift: return lv << rv
|
||||
if bop.op == ast.OpKind.RShift: return lv >> rv
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
|
||||
def _evaluate_cif_test(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
test: ast.AST | t.CPtr) -> int:
|
||||
"""求值 CIf 调用(test 必须是 c.CIf 系调用)。
|
||||
|
||||
成功: 置 self.CifEvalOk=1,返回条件值(0/1)
|
||||
失败(运行时变量/未知结构): 置 self.CifEvalOk=0,返回 0
|
||||
"""
|
||||
self.CifEvalOk = 0
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(test)
|
||||
if cl is None or cl.func is None:
|
||||
return 0
|
||||
kind: str = None
|
||||
fk: int = cl.func.kind()
|
||||
if fk == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
kind = at.attr
|
||||
elif fk == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func)
|
||||
kind = nm.id
|
||||
if kind is None:
|
||||
return 0
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
if cargs is None or cargs.__len__() < 1:
|
||||
return 0
|
||||
arg0: ast.AST | t.CPtr = cargs.get(0)
|
||||
if string.strcmp(kind, "CIf") == 0:
|
||||
v: int = self._cif_eval_node(pool, trans, arg0)
|
||||
if self.CifEvalOk == 0:
|
||||
return 0
|
||||
return 1 if v != 0 else 0
|
||||
# CIfdef / CIfndef: 判定宏名是否已定义
|
||||
defined: int = 0
|
||||
if arg0 is not None and arg0.kind() == ast.ASTKind.Name:
|
||||
nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0)
|
||||
if nm0.id is None:
|
||||
return 0
|
||||
self._cif_name_value(pool, trans, nm0.id)
|
||||
defined = self.CifEvalOk
|
||||
elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant:
|
||||
cn0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0)
|
||||
if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None:
|
||||
self._cif_name_value(pool, trans, cn0.str_val)
|
||||
defined = self.CifEvalOk
|
||||
else:
|
||||
return 0
|
||||
elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute:
|
||||
at0: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg0)
|
||||
self._cif_attr_value(pool, trans, at0)
|
||||
defined = self.CifEvalOk
|
||||
else:
|
||||
return 0
|
||||
# 定义判定本身成功(未定义名特判:不报错,defined=0 走 else)
|
||||
self.CifEvalOk = 1
|
||||
if string.strcmp(kind, "CIfdef") == 0:
|
||||
return 1 if defined != 0 else 0
|
||||
# CIfndef
|
||||
return 0 if defined != 0 else 1
|
||||
|
||||
def NewIfHandle(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesIf.IfHandle | t.CPtr:
|
||||
"""创建 IfHandle 实例(迁移自 HandlesIf.NewIfHandle)"""
|
||||
h: HandlesIf.IfHandle | t.CPtr = pool.alloc(HandlesIf.IfHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, HandlesIf.IfHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
# ============================================================
|
||||
# 簇 C:循环/return/match 子 Handle 工厂(迁移自
|
||||
# HandlesWhile/HandlesFor/HandlesReturn/HandlesMatch)
|
||||
# ============================================================
|
||||
|
||||
def NewWhileHandle(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesWhile.WhileHandle | t.CPtr:
|
||||
"""创建 WhileHandle 实例(迁移自 HandlesWhile.NewWhileHandle)"""
|
||||
h: HandlesWhile.WhileHandle | t.CPtr = pool.alloc(HandlesWhile.WhileHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, HandlesWhile.WhileHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
def NewForHandle(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesFor.ForHandle | t.CPtr:
|
||||
"""创建 ForHandle 实例(迁移自 HandlesFor.NewForHandle)"""
|
||||
h: HandlesFor.ForHandle | t.CPtr = pool.alloc(HandlesFor.ForHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, HandlesFor.ForHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
def NewReturnHandle(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesReturn.ReturnHandle | t.CPtr:
|
||||
"""创建 ReturnHandle 实例(迁移自 HandlesReturn.NewReturnHandle)"""
|
||||
h: HandlesReturn.ReturnHandle | t.CPtr = pool.alloc(HandlesReturn.ReturnHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, HandlesReturn.ReturnHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
def NewMatchHandle(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> HandlesMatch.MatchHandle | t.CPtr:
|
||||
"""创建 MatchHandle 实例(迁移自 HandlesMatch.NewMatchHandle)"""
|
||||
h: HandlesMatch.MatchHandle | t.CPtr = pool.alloc(HandlesMatch.MatchHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, HandlesMatch.MatchHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
# ============================================================
|
||||
# 簇 D:nonlocal/闭包 env 访问(迁移自 HandlesNonlocal.vp)
|
||||
# ============================================================
|
||||
|
||||
def _is_void_type(self, ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""判断是否为 Void 类型,是则返回 1,否则 0"""
|
||||
if ty is None:
|
||||
return 0
|
||||
match ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
return 1
|
||||
case _:
|
||||
return 0
|
||||
|
||||
def get_env_ptr_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)"""
|
||||
env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, "_env_ptr")
|
||||
if env_var is not None:
|
||||
return env_var
|
||||
# 创建 alloca 存储 env
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca)
|
||||
return alloca
|
||||
|
||||
def _load_raw_var_ptr(self, trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)
|
||||
|
||||
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
|
||||
"""
|
||||
idx: int = HT.get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
|
||||
|
||||
# 1. 加载 env_ptr
|
||||
env_alloca: llvmlite.Value | t.CPtr = self.get_env_ptr_var(trans)
|
||||
if env_alloca is None:
|
||||
return None
|
||||
env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca)
|
||||
if env_ptr is None:
|
||||
return None
|
||||
|
||||
# 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节
|
||||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 8)
|
||||
addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
# 3. Bitcast to i8** and load the raw pointer
|
||||
ptr_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i8_ptr_ptr_ty)
|
||||
if ptr_addr is None:
|
||||
return None
|
||||
return llvmlite.build_load(builder, i8_ptr_ty, ptr_addr)
|
||||
|
||||
def load_nonlocal_var(self, trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量值
|
||||
|
||||
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
|
||||
"""
|
||||
raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name)
|
||||
if raw_ptr is None:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
|
||||
# 获取变量类型(从注册时存储的类型信息)
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name)
|
||||
if var_ty is None or self._is_void_type(var_ty) != 0:
|
||||
# Void 类型视为无效(会导致 "load void, void*" 非法 IR),回退为 i32
|
||||
var_ty = llvmlite.Int32(pool)
|
||||
|
||||
# bitcast raw i8* to var_ty*
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
|
||||
if var_ptr is None:
|
||||
return None
|
||||
return llvmlite.build_load(builder, var_ty, var_ptr)
|
||||
|
||||
def get_nonlocal_var_ptr(self, trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作
|
||||
|
||||
返回的指针指向父函数的 alloca,store 操作对父函数可见。
|
||||
"""
|
||||
raw_ptr: llvmlite.Value | t.CPtr = self._load_raw_var_ptr(trans, name)
|
||||
if raw_ptr is None:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
|
||||
# 获取变量类型
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name)
|
||||
if var_ty is None or self._is_void_type(var_ty) != 0:
|
||||
# Void 类型视为无效(会导致 "bitcast ... to void*" 非法 IR),回退为 i32
|
||||
var_ty = llvmlite.Int32(pool)
|
||||
|
||||
# bitcast raw i8* to var_ty*
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
return llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
|
||||
|
||||
# ============================================================
|
||||
# 簇 E:枚举注册表(迁移自 HandlesEnum.vp)
|
||||
# ============================================================
|
||||
|
||||
def init_enum_table(self, pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化枚举注册表,返回 1 成功"""
|
||||
if self.EnumTable is not None:
|
||||
return 1
|
||||
|
||||
entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__()
|
||||
self.EnumTable = pool.alloc(entry_size * ENUM_MAX)
|
||||
if self.EnumTable is None:
|
||||
return 0
|
||||
string.memset(self.EnumTable, 0, entry_size * ENUM_MAX)
|
||||
self.EnumCount = 0
|
||||
return 1
|
||||
|
||||
def _get_enum_entry(self, i: int) -> HandlesEnum.EnumEntry | t.CPtr:
|
||||
"""获取第 i 个枚举条目"""
|
||||
if self.EnumTable is None or i < 0 or i >= ENUM_MAX:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesEnum.EnumEntry.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(self.EnumTable) + i * entry_size
|
||||
return (HandlesEnum.EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
|
||||
def _get_enum_member(self, enum_entry: HandlesEnum.EnumEntry | t.CPtr,
|
||||
i: int) -> HandlesEnum.EnumMember | t.CPtr:
|
||||
"""获取枚举中第 i 个成员条目"""
|
||||
if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX:
|
||||
return None
|
||||
member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size
|
||||
return (HandlesEnum.EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
|
||||
def register_enum(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
base_ty: llvmlite.LLVMType | t.CPtr) -> HandlesEnum.EnumEntry | t.CPtr:
|
||||
"""注册枚举类型,返回 EnumEntry 指针"""
|
||||
if self.init_enum_table(pool) == 0:
|
||||
return None
|
||||
|
||||
# 检查是否已注册
|
||||
existing: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
|
||||
if self.EnumCount >= ENUM_MAX:
|
||||
fb_et: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_et is not None:
|
||||
viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name)
|
||||
VLogger.error(fb_et, "ENUM")
|
||||
return None
|
||||
|
||||
entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(self.EnumCount)
|
||||
if entry is None:
|
||||
return None
|
||||
|
||||
# 分配成员数组
|
||||
member_size: t.CSizeT = HandlesEnum.EnumMember.__sizeof__()
|
||||
entry.Members = pool.alloc(member_size * ENUM_MEMBER_MAX)
|
||||
if entry.Members is None:
|
||||
return None
|
||||
string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX)
|
||||
|
||||
# 复制类名
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, name)
|
||||
entry.Name = name_buf
|
||||
|
||||
entry.BaseTy = base_ty
|
||||
entry.MemberCount = 0
|
||||
|
||||
self.EnumCount += 1
|
||||
return entry
|
||||
|
||||
def add_enum_member(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
enum_entry: HandlesEnum.EnumEntry | t.CPtr,
|
||||
member_name: str,
|
||||
member_val: t.CInt64T,
|
||||
member_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""向枚举添加成员,返回成员索引(-1 失败)"""
|
||||
if enum_entry is None or member_name is None or member_ty is None:
|
||||
return -1
|
||||
|
||||
if enum_entry.MemberCount >= ENUM_MEMBER_MAX:
|
||||
fb_em: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_em is not None:
|
||||
viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name)
|
||||
VLogger.error(fb_em, "ENUM")
|
||||
return -1
|
||||
|
||||
idx: int = enum_entry.MemberCount
|
||||
me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(enum_entry, idx)
|
||||
if me is None:
|
||||
return -1
|
||||
|
||||
# 复制成员名
|
||||
name_len: t.CSizeT = string.strlen(member_name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, member_name)
|
||||
me.Name = name_buf
|
||||
|
||||
me.Value = member_val
|
||||
me.Ty = member_ty
|
||||
|
||||
enum_entry.MemberCount = idx + 1
|
||||
return idx
|
||||
|
||||
def find_enum(self, name: str) -> HandlesEnum.EnumEntry | t.CPtr:
|
||||
"""按枚举类名查找,返回 EnumEntry 或 None"""
|
||||
if name is None or self.EnumTable is None:
|
||||
return None
|
||||
for i in range(self.EnumCount):
|
||||
entry: HandlesEnum.EnumEntry | t.CPtr = self._get_enum_entry(i)
|
||||
if entry is not None and entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
def lookup_enum_member(self, enum_name: str,
|
||||
member_name: str) -> HandlesEnum.EnumMember | t.CPtr:
|
||||
"""按枚举类名和成员名查找,返回 EnumMember 或 None"""
|
||||
if enum_name is None or member_name is None:
|
||||
return None
|
||||
entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name)
|
||||
if entry is None:
|
||||
return None
|
||||
for mi in range(entry.MemberCount):
|
||||
me: HandlesEnum.EnumMember | t.CPtr = self._get_enum_member(entry, mi)
|
||||
if me is not None and me.Name is not None:
|
||||
if string.strcmp(me.Name, member_name) == 0:
|
||||
return me
|
||||
return None
|
||||
|
||||
def is_enum_class(self, name: str) -> int:
|
||||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否"""
|
||||
if name is None:
|
||||
return 0
|
||||
if self.find_enum(name) is not None:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_enum_base_type(self, enum_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""按枚举类名获取基准类型"""
|
||||
entry: HandlesEnum.EnumEntry | t.CPtr = self.find_enum(enum_name)
|
||||
if entry is not None:
|
||||
return entry.BaseTy
|
||||
return None
|
||||
@@ -0,0 +1,695 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TranslatorGenMixin - 翻译驱动 Mixin(对象化 P6-E)
|
||||
#
|
||||
# 从 HandlesMain.vp / HandlesTranslator.vp 迁移:模块级纯函数
|
||||
# (trans 首参)→ 类方法。包含:
|
||||
# - 模块级翻译入口(translate_children/create_wrapper_main/
|
||||
# handle_module_level_var 等,原 HandlesMain.vp)
|
||||
# - global/nonlocal 名称管理辅助函数(原 HandlesTranslator.vp)
|
||||
#
|
||||
# 迁移原则(与 P2-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 trans/pool 首参),仅函数体内的
|
||||
# 本模块函数调用改为 self.xxx(...)
|
||||
# 2. 外部模块调用(HandlesType.xxx/HandlesVar.xxx 等)保留模块前缀
|
||||
# 3. HandlesMain/HandlesTranslator 原函数保留为"委托":本地模块级
|
||||
# 单例 _g_gen(BuildPipeline/main 注入)cast 成 Generator 类型
|
||||
# 4. 嵌套函数保持嵌套
|
||||
#
|
||||
# 常量(MAX_VARS/MAX_FUNCS/MAX_GLOBAL_NAMES)与原模块保持一致。
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesTranslator 保持一致)
|
||||
# ============================================================
|
||||
MAX_VARS: t.CDefine = 256
|
||||
MAX_FUNCS: t.CDefine = 256
|
||||
MAX_GLOBAL_NAMES: t.CDefine = 32
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TranslatorGenMixin - 翻译驱动(模块级翻译入口 + 作用域名称管理)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TranslatorGenMixin:
|
||||
"""翻译驱动 Mixin(P6 方法化)"""
|
||||
|
||||
# ============================================================
|
||||
# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数
|
||||
#
|
||||
# 解决翻译顺序依赖问题:Phase 1b 按字母序翻译,后翻译的模块的
|
||||
# CExport 函数无法被先翻译的模块正确识别为裸名调用。
|
||||
# Phase 1a 预注册所有 CExport/State 函数名到全局表。
|
||||
# ============================================================
|
||||
def _register_cexport_from_funcdef(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)"""
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
if trans is None or trans.ModuleSha1 is None:
|
||||
return 0
|
||||
|
||||
# 检查返回类型是否有 CExport 或 State 标记
|
||||
has_export: int = 0
|
||||
has_state: int = 0
|
||||
if fd.returns is not None:
|
||||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||||
|
||||
if has_export != 0 or has_state != 0:
|
||||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||||
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# translate_children - 遍历 AST 子节点并分派翻译
|
||||
#
|
||||
# 对应 TransPyC translator._translate_children()
|
||||
# 共享状态从 trans 获取,imported_modules/from_imports 更新到 trans
|
||||
# ============================================================
|
||||
def translate_children(self, trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""遍历 tree.children 并翻译每个子节点
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
added_total: int = 0
|
||||
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None: continue
|
||||
kd: int = child.kind()
|
||||
|
||||
# _declare_only == 0 时,_translate_module_level 已预处理导入语句,
|
||||
# 此处跳过避免重复处理(from_imports 条目重复)
|
||||
if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom):
|
||||
continue
|
||||
if kd == ast.ASTKind.Import:
|
||||
trans.ImportsH.HandleImport(child)
|
||||
elif kd == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(child)
|
||||
trans.ImportsH.HandleImportFromNames(child)
|
||||
elif kd == ast.ASTKind.FunctionDef:
|
||||
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
|
||||
# Phase 1b 全量翻译:正常翻译函数体
|
||||
if trans._declare_only == 0:
|
||||
added: int = HandlesFunctions.translate_function_def(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 1:
|
||||
self._register_cexport_from_funcdef(trans, child)
|
||||
# 预解析函数签名类型,触发泛型类特化(如 numpy 的 _empty_like
|
||||
# 签名 ndarray[t.CDouble] → 特化结构体注册)。
|
||||
# 1a 阶段在 mark1 之前,特化结构体的 Ty/Fields 分配在 mark1 前,
|
||||
# 不被 1b 的 mark/reset 回收 → 避免 Phase2 翻译 App 文件时 UAF
|
||||
# (Phase1 1b 才触发特化时,结构体 Ty/Fields 在 pool 被 reset 覆写)。
|
||||
# 仅触发特化,不验证结果(1b 全量翻译时仍会重新解析)。
|
||||
self._prescan_funcdef_signatures(trans, child)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
# ClassDef 在模块级直接处理(不需要 builder)
|
||||
# _declare_only=2(import扫描模式)时跳过,只处理 import 依赖
|
||||
if trans._declare_only != 2:
|
||||
HandlesClassDef.translate_class_def(trans, child)
|
||||
elif trans._declare_only == 0 and trans._cur_builder is not None:
|
||||
# 有 builder → 委托 HandlesBody 分派
|
||||
added = HandlesBody.translate_stmt(trans, child)
|
||||
added_total += added
|
||||
elif kd == ast.ASTKind.AnnAssign and trans._declare_only != 2:
|
||||
# 模块级 AnnAssign
|
||||
# _declare_only=2(import扫描模式)时跳过
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine(在 handle_module_level_var 内部判断)
|
||||
# _declare_only=0(全量翻译)时处理所有模块级 AnnAssign
|
||||
added = self.handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 0 and kd == ast.ASTKind.Assign:
|
||||
# 无 builder 的模块级 Assign → 创建全局变量(仅全量翻译模式)
|
||||
added = self.handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
|
||||
return added_total
|
||||
|
||||
# ============================================================
|
||||
# _prescan_funcdef_signatures - 1a 阶段预解析模块级函数签名
|
||||
#
|
||||
# 触发泛型类特化(如 numpy 的 _empty_like 签名 ndarray[t.CDouble]),
|
||||
# 使特化结构体在 mark1 前注册(Ty/Fields 不被 1b 的 mark/reset 回收),
|
||||
# 避免 Phase2 翻译 App 文件时访问悬空结构体(UAF)。
|
||||
# 仅解析类型触发特化,不验证结果(1b 全量翻译时重新解析)。
|
||||
# ============================================================
|
||||
def _prescan_funcdef_signatures(self, trans: HT.Translator | t.CPtr,
|
||||
fd: ast.FunctionDef | t.CPtr) -> None:
|
||||
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化"""
|
||||
if trans is None or fd is None:
|
||||
return
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None:
|
||||
return
|
||||
imp: str = trans._imported_modules
|
||||
fi: str = trans._from_imports
|
||||
if fd.returns is not None:
|
||||
HandlesType.resolve_annotation_type(pool, fd.returns, imp, fi, trans)
|
||||
if fd.args is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args)
|
||||
if ags.args is not None:
|
||||
al: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = al.__len__()
|
||||
ai: t.CSizeT
|
||||
for ai in range(an):
|
||||
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(al.get(ai))
|
||||
if ag is not None and ag.annotation is not None:
|
||||
HandlesType.resolve_annotation_type(pool, ag.annotation, imp, fi, trans)
|
||||
|
||||
# ============================================================
|
||||
# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器
|
||||
#
|
||||
# 生成格式: [N x elem_ty] [elem_ty val0, elem_ty val1, ...]
|
||||
# 用于模块级 t.CArray 列表字面量初始化(不依赖 builder,直接生成常量初始化器)
|
||||
# ============================================================
|
||||
def _build_array_initializer_text(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr,
|
||||
list_node: ast.List | t.CPtr) -> str:
|
||||
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败"""
|
||||
if var_ty is None or list_node is None:
|
||||
return None
|
||||
|
||||
# 重新进行类型转换,确保 TPV 编译器正确识别 ast.List 类型
|
||||
# (避免 init_list_node 初始值为 None 时类型推断退化为 t.CPtr)
|
||||
ln: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if ln is None:
|
||||
return None
|
||||
|
||||
# 从 var_ty 提取数组元素类型和数量
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
arr_count: t.CInt = 0
|
||||
match var_ty:
|
||||
case llvmlite.LLVMType.Array(et, cnt):
|
||||
elem_ty = et
|
||||
arr_count = cnt
|
||||
|
||||
if elem_ty is None or arr_count <= 0:
|
||||
return None
|
||||
|
||||
# 确定元素类型的 IR 表示
|
||||
elem_ir_ty: str = "i8"
|
||||
match elem_ty:
|
||||
case llvmlite.LLVMType.Int(bits):
|
||||
if bits == 8:
|
||||
elem_ir_ty = "i8"
|
||||
elif bits == 16:
|
||||
elem_ir_ty = "i16"
|
||||
elif bits == 32:
|
||||
elem_ir_ty = "i32"
|
||||
elif bits == 64:
|
||||
elem_ir_ty = "i64"
|
||||
|
||||
# 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别)
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = ln.elts
|
||||
if elts is None:
|
||||
return None
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符
|
||||
buf_size: t.CSizeT = 64 + elts_count * 32
|
||||
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
|
||||
if buf is None:
|
||||
return None
|
||||
|
||||
# 写入前缀: "["(类型前缀由 _print_global 输出,初始化器只需元素列表)
|
||||
written: t.CInt = viperlib.snprintf(buf, buf_size, "[")
|
||||
pos: t.CSizeT = t.CSizeT(written)
|
||||
|
||||
# 逐个元素写入
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
# 直接从 Constant 节点提取 int_val(避免 extract_cdefine_int_value 的 t.CInt 截断)
|
||||
elem_val: t.CInt64T = 0
|
||||
if elem_node is not None:
|
||||
ek: int = elem_node.kind()
|
||||
if ek == ast.ASTKind.Constant:
|
||||
ec: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(elem_node)
|
||||
if ec is not None and ec.const_kind == ast.CONST_INT:
|
||||
elem_val = ec.int_val
|
||||
elif ek == ast.ASTKind.UnaryOp:
|
||||
# 负数: UnaryOp(USub, Constant)
|
||||
elem_val = HandlesAnnAssign.extract_cdefine_int_value(elem_node)
|
||||
if i > 0:
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
|
||||
pos += t.CSizeT(written)
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, "%s %lld", elem_ir_ty, elem_val)
|
||||
pos += t.CSizeT(written)
|
||||
i += 1
|
||||
|
||||
# 写入后缀 "]"
|
||||
viperlib.snprintf(buf + pos, buf_size - pos, "]")
|
||||
return buf
|
||||
|
||||
# ============================================================
|
||||
# _build_string_ptr_initializer - 为字符串字面量初始化指针类型全局变量
|
||||
#
|
||||
# 创建内部字符串常量全局 @.str.{var_name} = private constant [len+1 x i8] c"...\00"
|
||||
# 返回 GEP 初始化器文本: getelementptr inbounds ([len+1 x i8], [len+1 x i8]* @.str.{var_name}, i32 0, i32 0)
|
||||
# 用于 b64_tab: t.CArray[t.CChar, None] = "ABC..." 等字符串初始化指针类型
|
||||
# ============================================================
|
||||
def _build_string_ptr_initializer(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
var_name: str,
|
||||
str_val: str) -> str:
|
||||
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败"""
|
||||
if str_val is None or var_name is None:
|
||||
return None
|
||||
|
||||
# 构造内部字符串常量名称: .str.{var_name}
|
||||
str_name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if str_name_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name)
|
||||
|
||||
# 调用 llvmlite.create_global_string 创建字符串常量全局
|
||||
str_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_string(
|
||||
pool, mod, str_name_buf, str_val)
|
||||
if str_gv is None:
|
||||
return None
|
||||
|
||||
# 生成 GEP 初始化器文本
|
||||
str_len: t.CSizeT = string.strlen(str_val)
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if init_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(init_buf, 128,
|
||||
"getelementptr inbounds ([%d x i8], [%d x i8]* @%s, i32 0, i32 0)",
|
||||
str_len + 1, str_len + 1, str_name_buf)
|
||||
return init_buf
|
||||
|
||||
# ============================================================
|
||||
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
|
||||
#
|
||||
# 当用户已定义 main(无 wrapper main builder)时,模块级
|
||||
# AnnAssign/Assign 创建全局变量 @var_name 并注册到 SymTab 模块作用域
|
||||
# 支持整数、列表字面量、字符串字面量初始值
|
||||
# ============================================================
|
||||
def handle_module_level_var(self, trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理模块级变量声明,创建全局变量"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
# CDefine 注解: 编译期常量,不创建全局变量
|
||||
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_cd: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_cd is not None and aa_cd.target is not None:
|
||||
if aa_cd.target.kind() == ast.ASTKind.Name:
|
||||
nm_cd: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa_cd.target)
|
||||
if nm_cd.id is not None:
|
||||
if HandlesAnnAssign.is_cdefine_annotation(aa_cd.annotation) != 0:
|
||||
# 浮点/整数自动识别注册(浮点 CDefine 如 vipermath U_M_PI)
|
||||
HandlesAnnAssign._register_cdefine_from_value(
|
||||
pool, nm_cd.id, aa_cd.value)
|
||||
return 0
|
||||
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量
|
||||
# CDefine 已在上面处理并返回,到这里说明不是 CDefine,直接跳过
|
||||
if trans._declare_only == 1:
|
||||
return 0
|
||||
|
||||
var_name: str = None
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
init_val: t.CInt64T = 0
|
||||
init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str
|
||||
init_str_val: str = None
|
||||
init_list_node: ast.List | t.CPtr = None
|
||||
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None or aa.target is None:
|
||||
return 0
|
||||
if aa.target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
var_name = nm.id
|
||||
# 解析类型
|
||||
if aa.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||||
if resolved is not None:
|
||||
var_ty = resolved
|
||||
# 解析初始值(支持整数、列表字面量、字符串字面量)
|
||||
if aa.value is not None:
|
||||
val_kind: int = aa.value.kind()
|
||||
if val_kind == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(aa.value)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
init_val = cn.int_val
|
||||
init_kind = 1
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn.str_val
|
||||
init_kind = 3
|
||||
elif val_kind == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(aa.value)
|
||||
init_kind = 2
|
||||
elif k == ast.ASTKind.Assign:
|
||||
asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
|
||||
if asgn is None or asgn.targets is None:
|
||||
return 0
|
||||
targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets
|
||||
if targets.__len__() < 1:
|
||||
return 0
|
||||
t0: ast.AST | t.CPtr = targets.get(0)
|
||||
if t0 is None or t0.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0)
|
||||
var_name = nm2.id
|
||||
if asgn.value is not None:
|
||||
val_kind2: int = asgn.value.kind()
|
||||
if val_kind2 == ast.ASTKind.Constant:
|
||||
cn2: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(asgn.value)
|
||||
if cn2.const_kind == ast.CONST_INT:
|
||||
init_val = cn2.int_val
|
||||
init_kind = 1
|
||||
elif cn2.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn2.str_val
|
||||
init_kind = 3
|
||||
elif val_kind2 == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(asgn.value)
|
||||
init_kind = 2
|
||||
|
||||
if var_name is None:
|
||||
return 0
|
||||
|
||||
# 检查是否已注册
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
trans.SymTab, var_name)
|
||||
if existing is not None:
|
||||
return 0
|
||||
|
||||
# 创建全局变量 @var_name
|
||||
# 先确保 var_ty 中的跨模块结构体类型在模块中有 opaque 声明
|
||||
# 否则 @var_name = global %"sha1.ClassName"* zeroinitializer 会报
|
||||
# "use of undefined type named 'sha1.ClassName'" 错误
|
||||
# (如 _mbuddy: memhub.MemManager | t.CPtr → Ptr(Struct("aeb3...MemManager")))
|
||||
llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, var_name, var_ty)
|
||||
if gv is None:
|
||||
return 0
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
# 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值)
|
||||
gv.Linkage = None
|
||||
if init_kind == 1:
|
||||
# 整数初始值
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(48)
|
||||
if init_buf is not None:
|
||||
viperlib.snprintf(init_buf, 48, "%lld", init_val)
|
||||
gv.Initializer = init_buf
|
||||
elif init_kind == 2:
|
||||
# 列表字面量 → 数组初始化器 [N x elem_ty] [elem_ty val0, ...]
|
||||
arr_init: str = self._build_array_initializer_text(pool, var_ty, init_list_node)
|
||||
if arr_init is not None:
|
||||
gv.Initializer = arr_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
elif init_kind == 3:
|
||||
# 字符串字面量 → 创建字符串常量全局 + GEP 引用
|
||||
str_init: str = self._build_string_ptr_initializer(pool, mod, var_name, init_str_val)
|
||||
if str_init is not None:
|
||||
gv.Initializer = str_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
else:
|
||||
# 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer,
|
||||
# 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type"
|
||||
gv.Initializer = "zeroinitializer"
|
||||
|
||||
# 创建 Value 引用(@var_name, 类型为 var_ty*)
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
ref_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if ref_name is not None:
|
||||
viperlib.snprintf(ref_name, 64, "@%s", var_name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, var_ptr_ty, ref_name)
|
||||
|
||||
# 注册到模块作用域
|
||||
if HandlesVar.define_module_var(trans.SymTab, var_name, gv_ref) == 0:
|
||||
# 设置 AnnotClassName(联合类型如 Logger|t.CPtr 简化为 Ptr(i8) 时,
|
||||
# 属性访问需要通过 AnnotClassName 回退到类名查找结构体)
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_ml: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_ml is not None and aa_ml.annotation is not None:
|
||||
cls_nm_ml: str = HandlesType.extract_class_name_from_annotation(
|
||||
aa_ml.annotation, trans._imported_modules)
|
||||
if cls_nm_ml is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
trans.SymTab, var_name, cls_nm_ml)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# create_wrapper_main - 创建包装 main 函数
|
||||
#
|
||||
# 当用户未定义 main 函数时调用。
|
||||
# 创建 main() -> i32 函数 → 设置 trans._cur_func/_cur_builder →
|
||||
# 预扫描 alloca → 翻译子节点 → ret 0
|
||||
# ============================================================
|
||||
def create_wrapper_main(self, trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr,
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""创建包装 main 函数并翻译所有顶层语句
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
i32_ty: i32 LLVMType
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
main_func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||||
pool, mod, "main", i32_ty)
|
||||
if main_func is None:
|
||||
VLogger.error("CreateFunction main returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, main_func, "entry")
|
||||
if entry_blk is None:
|
||||
VLogger.error("CreateBlock returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, main_func)
|
||||
if builder is None:
|
||||
VLogger.error("NewBuilder returned NULL", "TR")
|
||||
return 0
|
||||
llvmlite.position_at_end(builder, entry_blk)
|
||||
|
||||
# 设置当前翻译上下文(供 Handle 通过 self.Trans._cur_builder 访问)
|
||||
trans._cur_func = main_func
|
||||
trans._cur_builder = builder
|
||||
|
||||
# 预处理模块级变量:为 AnnAssign/Assign 创建 LLVM 全局变量
|
||||
# 必须在 pre_scan_allocas 之前执行,否则 PreScan 会创建局部 alloca,
|
||||
# 导致其他函数通过 SSA 编号引用 wrapper main 的局部变量(无效 IR)
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is not None:
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign:
|
||||
self.handle_module_level_var(trans, child)
|
||||
|
||||
# 预扫描顶层语句:为函数内 AnnAssign 提前创建 alloca
|
||||
# (模块级变量已在上面注册到模块作用域,PreScan 的 lookup_current 会跳过它们)
|
||||
if ch is not None:
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
HandlesBody.pre_scan_allocas(trans, child)
|
||||
|
||||
# 翻译子节点
|
||||
added_total: int = self.translate_children(trans, tree)
|
||||
|
||||
# 返回 0
|
||||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
llvmlite.build_ret(builder, zero_val)
|
||||
|
||||
return added_total
|
||||
|
||||
# ============================================================
|
||||
# global/nonlocal 名称管理(迁移自 HandlesTranslator.vp 模块级函数)
|
||||
# ============================================================
|
||||
def add_global_name(self, trans: HT.Translator | t.CPtr, name: str):
|
||||
"""添加一个 global 变量名"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._global_names is None:
|
||||
return
|
||||
# 检查是否已存在
|
||||
if self.is_global_name(trans, name) != 0:
|
||||
return
|
||||
if trans._global_name_count >= MAX_GLOBAL_NAMES:
|
||||
pool_err: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
err_buf: str = None
|
||||
if pool_err is not None:
|
||||
err_buf = pool_err.alloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256, "global 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 global 声明或增大 MAX_GLOBAL_NAMES", MAX_GLOBAL_NAMES)
|
||||
VLogger.error(err_buf, "ScopeDecl")
|
||||
else:
|
||||
VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl")
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + trans._global_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
trans._global_name_count += 1
|
||||
|
||||
def is_global_name(self, trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 global 集合中"""
|
||||
if trans is None or name is None or trans._global_names is None:
|
||||
return 0
|
||||
for i in range(trans._global_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def add_nonlocal_name(self, trans: HT.Translator | t.CPtr, name: str,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = None):
|
||||
"""添加一个 nonlocal 变量名
|
||||
|
||||
Args:
|
||||
name: nonlocal 变量名
|
||||
var_ty: 变量的 LLVM 类型(用于 env 指针数组方案的类型恢复,
|
||||
None 时回退为 i32)
|
||||
"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._nonlocal_names is None:
|
||||
return
|
||||
if self.is_nonlocal_name(trans, name) != 0:
|
||||
# 已存在:更新类型信息(可能在预扫描时类型未知,正式翻译时更新)
|
||||
# _nonlocal_types 每槽 8 字节,存 LLVMType* 指针。
|
||||
# 用 str|t.CPtr (i8**) 二级指针存取(与 _nonlocal_names 模式一致),
|
||||
# [0] 解引用只拷贝 8 字节指针,避免值拷贝 24+ 字节 LLVMType 结构体溢出。
|
||||
if var_ty is not None and trans._nonlocal_types is not None:
|
||||
idx: int = self.get_nonlocal_index(trans, name)
|
||||
if idx >= 0:
|
||||
ty_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + idx * 8
|
||||
ty_slot: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr)
|
||||
ty_slot[0] = var_ty
|
||||
return
|
||||
if trans._nonlocal_name_count >= MAX_GLOBAL_NAMES:
|
||||
pool_err_nl: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
err_buf_nl: str = None
|
||||
if pool_err_nl is not None:
|
||||
err_buf_nl = pool_err_nl.alloc(256)
|
||||
if err_buf_nl is not None:
|
||||
viperlib.snprintf(err_buf_nl, 256, "nonlocal 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", MAX_GLOBAL_NAMES)
|
||||
VLogger.error(err_buf_nl, "ScopeDecl")
|
||||
else:
|
||||
VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl")
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + trans._nonlocal_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
# 存储类型信息(用 str|t.CPtr = i8** 二级指针,与 _nonlocal_names 一致)
|
||||
if trans._nonlocal_types is not None:
|
||||
ty_addr2: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + trans._nonlocal_name_count * 8
|
||||
ty_slot2: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr2)
|
||||
# var_ty 为 None 时存入 i32 作为默认类型
|
||||
stored_ty: llvmlite.LLVMType | t.CPtr = var_ty
|
||||
if stored_ty is None:
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is not None:
|
||||
stored_ty = llvmlite.Int32(pool)
|
||||
ty_slot2[0] = stored_ty
|
||||
trans._nonlocal_name_count += 1
|
||||
trans._closure_env_count += 1
|
||||
|
||||
def get_nonlocal_type(self, trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""获取 nonlocal 变量的 LLVM 类型
|
||||
|
||||
Returns: 找到的类型指针,找不到返回 None
|
||||
"""
|
||||
if trans is None or name is None or trans._nonlocal_types is None:
|
||||
return None
|
||||
idx: int = self.get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
ty_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + idx * 8
|
||||
ty_slot: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr)
|
||||
return (llvmlite.LLVMType | t.CPtr)(ty_slot[0])
|
||||
|
||||
def is_nonlocal_name(self, trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 nonlocal 集合中"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return 0
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def get_nonlocal_index(self, trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return -1
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def clear_scope_names(self, trans: HT.Translator | t.CPtr):
|
||||
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)"""
|
||||
if trans is None:
|
||||
return
|
||||
trans._global_name_count = 0
|
||||
trans._nonlocal_name_count = 0
|
||||
trans._closure_env_count = 0
|
||||
@@ -0,0 +1,392 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin(P6 对象化,wiki/14-oo-refactor.md)
|
||||
#
|
||||
# 从 HandlesVar.vp 迁移:模块级函数(init_vars/find_var/find_var_entry/
|
||||
# lookup_var_entry/set_var_annot_class_name/set_var_ptr_element/add_var/
|
||||
# _alloca_at_entry/get_or_create_var/_create_scope/init_symbol_table/
|
||||
# enter_scope/exit_scope/define_var/define_module_var/lookup_var/
|
||||
# lookup_current/lookup_module_var/is_module_scope/get_or_create_sym)
|
||||
# → 本类方法。
|
||||
#
|
||||
# 迁移原则(与 P1-P5 一致,行为零变化):
|
||||
# 1. 方法保留原函数签名(含 symtab/vars_ptr 等指针首参——self 是宿主
|
||||
# Generator,这些函数操作数据结构指针,self 可能少用,但为风格
|
||||
# 统一仍方法化)
|
||||
# 2. 函数体原样搬入,本模块内部函数调用改为 self.xxx(...);
|
||||
# 跨模块调用保留模块前缀(本模块无跨模块调用)
|
||||
# 3. HandlesVar.vp 原函数保留为"一行委托":本地模块级单例 _g_gen
|
||||
# (BuildPipeline/main 注入)cast 成 Generator 类型后调本类方法
|
||||
# 4. VarEntry/Scope/SymbolTable 数据结构类保留在 HandlesVar.vp
|
||||
# (本类方法签名/函数体经 HandlesVar 前缀引用)
|
||||
#
|
||||
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 常量(与 HandlesVar 保持一致)
|
||||
# ============================================================
|
||||
# 作用域类型常量
|
||||
SCOPE_MODULE: t.CDefine = 0
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
SCOPE_BLOCK: t.CDefine = 2
|
||||
|
||||
# 每个作用域最大变量数
|
||||
MAX_VARS: t.CDefine = 256
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarGenMixin - 变量/作用域符号表 Mixin
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class VarGenMixin:
|
||||
"""变量/作用域 Mixin(P6 方法化)"""
|
||||
# 迁移自 HandlesVar 的模块级函数
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
def init_vars(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组"""
|
||||
size: t.CSizeT = MAX_VARS * HandlesVar.VarEntry.__sizeof__()
|
||||
vars_ptr: HandlesVar.VarEntry | t.CPtr = pool.alloc(size)
|
||||
if vars_ptr is not None:
|
||||
string.memset(vars_ptr, 0, size)
|
||||
return vars_ptr
|
||||
|
||||
# ============================================================
|
||||
# find_var — 在变量表中按名称查找
|
||||
# ============================================================
|
||||
def find_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry.Alloca
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||||
# ============================================================
|
||||
def find_var_entry(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> HandlesVar.VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: HandlesVar.VarEntry | t.CPtr = self.find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||||
#
|
||||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||||
# 通过 AnnotClassName 查找实际结构体类型。
|
||||
# ============================================================
|
||||
def set_var_annot_class_name(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.AnnotClassName = class_name
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
|
||||
#
|
||||
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
|
||||
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
|
||||
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
|
||||
# ============================================================
|
||||
def set_var_ptr_element(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: HandlesVar.VarEntry | t.CPtr = self.lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.IsPtrElement = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# add_var — 添加变量到变量表
|
||||
# ============================================================
|
||||
def add_var(self, vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表"""
|
||||
if name is None or alloca is None or vars_ptr is None:
|
||||
return 1
|
||||
if var_count >= MAX_VARS:
|
||||
return 1
|
||||
entry_size: t.CSizeT = HandlesVar.VarEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||||
entry: HandlesVar.VarEntry | t.CPtr = (HandlesVar.VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||||
# 标准做法:所有 alloca 在函数入口块生成。
|
||||
#
|
||||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||||
# ============================================================
|
||||
def _alloca_at_entry(self, builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
if builder is None or ty is None:
|
||||
return None
|
||||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||||
# ============================================================
|
||||
def get_or_create_var(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
vars_ptr: HandlesVar.VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca"""
|
||||
existing: llvmlite.Value | t.CPtr = self.find_var(vars_ptr, var_count, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if self.add_var(vars_ptr, var_count, name, alloca) != 0:
|
||||
return None
|
||||
return alloca
|
||||
|
||||
# ============================================================
|
||||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||||
# ============================================================
|
||||
def _create_scope(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: HandlesVar.Scope | t.CPtr,
|
||||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点"""
|
||||
scope: HandlesVar.Scope | t.CPtr = pool.alloc(HandlesVar.Scope.__sizeof__())
|
||||
if scope is None:
|
||||
return None
|
||||
string.memset(scope, 0, HandlesVar.Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
scope.Vars = self.init_vars(pool)
|
||||
scope.VarCount = 0
|
||||
scope.Kind = kind
|
||||
if scope.Vars is None:
|
||||
return None
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(self, pool: memhub.MemBuddy | t.CPtr) -> HandlesVar.SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域"""
|
||||
if pool is None:
|
||||
return None
|
||||
symtab: HandlesVar.SymbolTable | t.CPtr = pool.alloc(HandlesVar.SymbolTable.__sizeof__())
|
||||
if symtab is None:
|
||||
return None
|
||||
string.memset(symtab, 0, HandlesVar.SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# 创建根作用域(模块级)
|
||||
root: HandlesVar.Scope | t.CPtr = self._create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None:
|
||||
return None
|
||||
|
||||
symtab.Root = root
|
||||
symtab.Current = root
|
||||
return symtab
|
||||
|
||||
# ============================================================
|
||||
# enter_scope — 进入新作用域
|
||||
# ============================================================
|
||||
def enter_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
kind: int) -> HandlesVar.Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域"""
|
||||
if symtab is None:
|
||||
return None
|
||||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||||
scope: HandlesVar.Scope | t.CPtr = self._create_scope(pool, symtab.Current, kind)
|
||||
if scope is None:
|
||||
return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域"""
|
||||
if symtab is not None and symtab.Current is not None:
|
||||
symtab.Current = symtab.Current.Parent
|
||||
|
||||
# ============================================================
|
||||
# define_var — 在当前作用域定义变量
|
||||
# ============================================================
|
||||
def define_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# define_module_var — 在模块作用域定义变量
|
||||
# ============================================================
|
||||
def define_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
# ============================================================
|
||||
# lookup_var — 从当前作用域逐级向上查找变量
|
||||
# ============================================================
|
||||
def lookup_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: llvmlite.Value | t.CPtr = self.find_var(
|
||||
scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# lookup_current — 仅在当前作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_current(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# lookup_module_var — 在模块作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_module_var(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: HandlesVar.Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# ============================================================
|
||||
# is_module_scope - 判断当前是否在模块级作用域
|
||||
#
|
||||
# 用于区分模块级代码和函数内代码:
|
||||
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
|
||||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||||
# ============================================================
|
||||
def is_module_scope(self, symtab: HandlesVar.SymbolTable | t.CPtr) -> int:
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root)
|
||||
|
||||
Returns: 1=模块级作用域, 0=函数内作用域
|
||||
"""
|
||||
if symtab is None:
|
||||
return 0
|
||||
if symtab.Root is None or symtab.Current is None:
|
||||
return 0
|
||||
# 比较指针:Current 与 Root 相同则为模块级
|
||||
if t.CUInt64T(symtab.Current) == t.CUInt64T(symtab.Root):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||||
# ============================================================
|
||||
def get_or_create_sym(self, symtab: HandlesVar.SymbolTable | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域)"""
|
||||
existing: llvmlite.Value | t.CPtr = self.lookup_current(symtab, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = self._alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
self.define_var(symtab, name, alloca)
|
||||
return alloca
|
||||
@@ -19,6 +19,25 @@ import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.VLogger as VLogger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6 对象化重构:模块级无状态函数已迁移为 lib.core.Gen.AssignGenMixin
|
||||
# 的方法(_g_recover_found 全局迁入 gen 字段 RecoverFound),本模块保留
|
||||
# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAnnAssign - AnnAssign 语句处理(Mixin 继承模式)
|
||||
# ============================================================
|
||||
@@ -32,21 +51,11 @@ import lib.core.VLogger as VLogger
|
||||
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
|
||||
# ============================================================
|
||||
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if is_cdefine_annotation(bop.left) != 0:
|
||||
return 1
|
||||
if is_cdefine_annotation(bop.right) != 0:
|
||||
return 1
|
||||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否(委托到 gen.is_cdefine_annotation)"""
|
||||
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.is_cdefine_annotation(annot)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -61,66 +70,11 @@ def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
# 5. UnaryOp(USub/UAdd/Invert) — 如 -11
|
||||
# ============================================================
|
||||
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
|
||||
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp)"""
|
||||
if val_node is None:
|
||||
return 0
|
||||
k: int = val_node.kind()
|
||||
|
||||
# Case 1: Constant(INT) — 如 0x0002
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||||
if cn.const_kind != ast.CONST_INT:
|
||||
return 0
|
||||
return cn.int_val
|
||||
|
||||
# Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node)
|
||||
left_val: int = extract_cdefine_int_value(bop.left)
|
||||
right_val: int = extract_cdefine_int_value(bop.right)
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
return left_val | right_val
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
return left_val & right_val
|
||||
if bop.op == ast.OpKind.Add:
|
||||
return left_val + right_val
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
return left_val - right_val
|
||||
return 0
|
||||
|
||||
# Case 3: Name — 引用已注册的 CDefine 常量
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node)
|
||||
if nm.id is not None:
|
||||
looked_up: int = HandlesType.lookup_cdefine_constant(nm.id)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return looked_up
|
||||
return 0
|
||||
|
||||
# Case 4: Call — 如 t.CUnsignedLong(-11)
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node)
|
||||
# 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||||
cl_args_list: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
if cl_args_list is not None and cl_args_list.__len__() > 0:
|
||||
first_arg: ast.AST | t.CPtr = cl_args_list.get(0)
|
||||
arg_val: int = extract_cdefine_int_value(first_arg)
|
||||
return arg_val
|
||||
return 0
|
||||
|
||||
# Case 5: UnaryOp — 如 -11
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node)
|
||||
operand_val: int = extract_cdefine_int_value(uop.operand)
|
||||
if uop.op == ast.OpKind.USub:
|
||||
return -operand_val
|
||||
if uop.op == ast.OpKind.UAdd:
|
||||
return operand_val
|
||||
if uop.op == ast.OpKind.Invert:
|
||||
return ~operand_val
|
||||
return 0
|
||||
|
||||
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp,委托到 gen.extract_cdefine_int_value)"""
|
||||
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.extract_cdefine_int_value(val_node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -133,47 +87,11 @@ def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
|
||||
# ============================================================
|
||||
def _register_cdefine_from_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str, val_node: ast.AST | t.CPtr) -> None:
|
||||
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数)"""
|
||||
if pool is None or name is None:
|
||||
return
|
||||
if val_node is not None and val_node.kind() == ast.ASTKind.Constant:
|
||||
cn_fp: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||||
if cn_fp.const_kind == ast.CONST_FLOAT:
|
||||
# 源文件重读恢复(最可靠:AST 节点 float_val 可能被 pool 操作覆写,
|
||||
# 源文件文本不受影响;用输出参数绕开跨模块 double 返回值传递 bug)
|
||||
use_val: double = cn_fp.float_val
|
||||
rec_d: t.CDouble = 0.0
|
||||
if _recover_cdefine_float(name, t.CPtr(c.Addr(rec_d))) != 0:
|
||||
use_val = rec_d
|
||||
# CDEF-DBG: 打印 float_val 读取(定位浮点 CDefine 值错误)
|
||||
fb_cd: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cd is not None:
|
||||
# 位模式拆解:把 float_val / rec_d 的 8 字节拷贝到 u64,再拆高低 32 位
|
||||
# 用于确认"哪一半被覆写 + 被谁覆写"(若与 int_val/const_kind 位模式重叠即锁布局 bug)
|
||||
fv_bits: t.CUInt64T = 0
|
||||
string.memcpy(t.CVoid(t.CUInt64T(c.Addr(fv_bits)), t.CPtr),
|
||||
t.CVoid(t.CUInt64T(c.Addr(cn_fp.float_val)), t.CPtr), 8)
|
||||
rec_bits: t.CUInt64T = 0
|
||||
string.memcpy(t.CVoid(t.CUInt64T(c.Addr(rec_bits)), t.CPtr),
|
||||
t.CVoid(t.CUInt64T(c.Addr(rec_d)), t.CPtr), 8)
|
||||
stdio.snprintf(fb_cd, 1024,
|
||||
"REG-SRC: %s kind=%d const_kind=%d ptr=%p\n"
|
||||
" fv=%.17g %a hi=%08llx lo=%08llx\n"
|
||||
" int_val=%lld bits=%016llx const_kind_hex=%x str_val=%p\n"
|
||||
" rec=%.17g %a hi=%08llx lo=%08llx use=%.17g",
|
||||
name, val_node.kind(), cn_fp.const_kind, t.CSizeT(cn_fp),
|
||||
cn_fp.float_val, cn_fp.float_val,
|
||||
t.CUInt64T(fv_bits >> 32), t.CUInt64T(fv_bits & 0xFFFFFFFF),
|
||||
cn_fp.int_val, t.CUInt64T(cn_fp.int_val), cn_fp.const_kind,
|
||||
t.CSizeT(cn_fp.str_val),
|
||||
rec_d, rec_d,
|
||||
t.CUInt64T(rec_bits >> 32), t.CUInt64T(rec_bits & 0xFFFFFFFF),
|
||||
use_val)
|
||||
VLogger.info(fb_cd, "CDEF-DBG")
|
||||
HandlesType.register_cdefine_double(pool, name, use_val)
|
||||
return
|
||||
val_fp: int = extract_cdefine_int_value(val_node)
|
||||
HandlesType.register_cdefine_constant(pool, name, val_fp)
|
||||
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数,委托到 gen._register_cdefine_from_value)"""
|
||||
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:
|
||||
g._register_cdefine_from_value(pool, name, val_node)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -183,113 +101,29 @@ def _register_cdefine_from_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
# (MemBuddy 内存冲突),导致注册的浮点 CDefine 值错误(llc ret i32 0)。
|
||||
# 本函数直接读源文件找 "NAME: t.CDefine = value" 行,atof 解析 value——
|
||||
# 源文件文本不受 pool 影响,是最可靠的恢复路径。
|
||||
# 原模块级 _g_recover_found 全局已迁移为 gen 字段(RecoverFound)。
|
||||
# ============================================================
|
||||
_g_recover_found: int = 0
|
||||
|
||||
|
||||
def _recover_found() -> int:
|
||||
"""检查最近一次 _recover_cdefine_float 是否成功"""
|
||||
return _g_recover_found
|
||||
"""检查最近一次 _recover_cdefine_float 是否成功(委托到 gen._recover_found)"""
|
||||
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._recover_found()
|
||||
return 0
|
||||
|
||||
|
||||
def _recover_cdefine_float(name: str, out: t.CDouble | t.CPtr) -> int:
|
||||
"""从当前模块源文件恢复浮点 CDefine 值,写入 out[0],成功返回 1
|
||||
|
||||
用输出参数传递 double,避免 TPV 跨模块 double 返回值传递 bug。
|
||||
(委托到 gen._recover_cdefine_float)
|
||||
"""
|
||||
global _g_recover_found
|
||||
_g_recover_found = 0
|
||||
fp: str = HandlesType.get_current_file()
|
||||
if fp is None or name is None or out is None:
|
||||
return 0
|
||||
f: fileio.File | t.CPtr = fileio.File(fp, fileio.MODE.R)
|
||||
if f.closed:
|
||||
return 0
|
||||
BUF_SZ: t.CSizeT = 1048576
|
||||
buf: bytes = stdlib.malloc(BUF_SZ)
|
||||
if buf is None:
|
||||
f.close()
|
||||
return 0
|
||||
nrd: LONG = f.read_all(buf, BUF_SZ)
|
||||
f.close()
|
||||
if nrd <= 0:
|
||||
stdlib.free(buf)
|
||||
return 0
|
||||
if nrd < BUF_SZ:
|
||||
buf[nrd] = 0
|
||||
else:
|
||||
buf[BUF_SZ - 1] = 0
|
||||
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
total_len: t.CSizeT = string.strlen(buf)
|
||||
pos: t.CSizeT = 0
|
||||
while pos < total_len:
|
||||
line_start: t.CSizeT = pos
|
||||
while pos < total_len and buf[pos] != '\n':
|
||||
pos += 1
|
||||
line_len: t.CSizeT = pos - line_start
|
||||
if pos < total_len:
|
||||
pos += 1
|
||||
|
||||
# 匹配 "name:"
|
||||
if line_len < name_len + 1:
|
||||
continue
|
||||
match_ok: int = 1
|
||||
ki: t.CSizeT
|
||||
for ki in range(name_len):
|
||||
if buf[line_start + ki] != name[ki]:
|
||||
match_ok = 0
|
||||
break
|
||||
if match_ok == 0:
|
||||
continue
|
||||
if buf[line_start + name_len] != ':':
|
||||
continue
|
||||
|
||||
# 行内包含 "t.CDefine"
|
||||
has_cd: int = 0
|
||||
ci: t.CSizeT = line_start + name_len + 1
|
||||
while ci + 8 <= line_start + line_len:
|
||||
if (buf[ci] == 't' and buf[ci + 1] == '.' and buf[ci + 2] == 'C' and
|
||||
buf[ci + 3] == 'D' and buf[ci + 4] == 'e' and buf[ci + 5] == 'f' and
|
||||
buf[ci + 6] == 'i' and buf[ci + 7] == 'n' and buf[ci + 8] == 'e'):
|
||||
has_cd = 1
|
||||
break
|
||||
ci += 1
|
||||
if has_cd == 0:
|
||||
continue
|
||||
|
||||
# 找 '='
|
||||
eq: t.CSizeT = line_start
|
||||
while eq < line_start + line_len and buf[eq] != '=':
|
||||
eq += 1
|
||||
if eq >= line_start + line_len:
|
||||
continue
|
||||
eq += 1
|
||||
while eq < line_start + line_len and buf[eq] == ' ':
|
||||
eq += 1
|
||||
val_start: t.CSizeT = eq
|
||||
while eq < line_start + line_len and buf[eq] != ' ' and buf[eq] != '\t' \
|
||||
and buf[eq] != '#' and buf[eq] != '\r' and buf[eq] != '\n':
|
||||
eq += 1
|
||||
if eq == val_start:
|
||||
continue
|
||||
|
||||
val_txt: str = stdlib.malloc(eq - val_start + 1)
|
||||
if val_txt is None:
|
||||
stdlib.free(buf)
|
||||
return 0
|
||||
vi: t.CSizeT
|
||||
for vi in range(eq - val_start):
|
||||
val_txt[vi] = buf[val_start + vi]
|
||||
val_txt[eq - val_start] = 0
|
||||
stdlib.free(buf)
|
||||
# 用 atof_out(输出参数)绕开跨模块 double 返回值传递 bug
|
||||
if string.atof_out(val_txt, out) != 0:
|
||||
_g_recover_found = 1
|
||||
return 1
|
||||
return 0
|
||||
|
||||
stdlib.free(buf)
|
||||
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._recover_cdefine_float(name, out)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -299,26 +133,11 @@ def _recover_cdefine_float(name: str, out: t.CDouble | t.CPtr) -> int:
|
||||
# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。
|
||||
# ============================================================
|
||||
def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int:
|
||||
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含"""
|
||||
if annot is None or name is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot)
|
||||
if nm.id is not None and string.strcmp(nm.id, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if _annotation_contains_name(bop.left, name) != 0:
|
||||
return 1
|
||||
if _annotation_contains_name(bop.right, name) != 0:
|
||||
return 1
|
||||
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含(委托到 gen._annotation_contains_name)"""
|
||||
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._annotation_contains_name(annot, name)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -335,19 +154,11 @@ def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int:
|
||||
# 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算
|
||||
# ============================================================
|
||||
def _is_ptr_element_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k != ast.ASTKind.BinOp:
|
||||
return 0
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if bop.op != ast.OpKind.BitOr:
|
||||
return 0
|
||||
if _annotation_contains_name(annot, "str") != 0:
|
||||
return 1
|
||||
if _annotation_contains_name(annot, "bytes") != 0:
|
||||
return 1
|
||||
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式(委托到 gen._is_ptr_element_annotation)"""
|
||||
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._is_ptr_element_annotation(annot)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -374,51 +185,11 @@ def _init_global_array_from_list(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
array_alloca: llvmlite.Value | t.CPtr,
|
||||
list_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""从列表字面量初始化全局数组,为每个元素生成 GEP + store"""
|
||||
if builder is None or array_alloca is None or list_node is None:
|
||||
return 1
|
||||
|
||||
# 获取数组类型(Pointee of [N x elem_ty]*)
|
||||
arr_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if array_alloca.Ty is not None:
|
||||
arr_ty = array_alloca.Ty.Pointee
|
||||
if arr_ty is None:
|
||||
return 1
|
||||
|
||||
# 匹配数组类型获取元素类型
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
match arr_ty:
|
||||
case llvmlite.LLVMType.Array(et, _):
|
||||
elem_ty = et
|
||||
if elem_ty is None:
|
||||
return 1
|
||||
|
||||
# 获取列表元素
|
||||
lst: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if lst is None or lst.elts is None:
|
||||
return 1
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = lst.elts
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 为每个元素生成 GEP + store
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
elem_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, elem_node, None, 0, trans)
|
||||
if elem_val is not None:
|
||||
idx_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, i)
|
||||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||||
builder, arr_ty, elem_ty, array_alloca, idx_val)
|
||||
if elem_ptr is not None:
|
||||
# 类型转换(如 i32 → i8 截断)
|
||||
store_val: llvmlite.Value | t.CPtr = elem_val
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, elem_val, elem_ptr.Ty.Pointee, elem_node)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr)
|
||||
i += 1
|
||||
|
||||
"""从列表字面量初始化全局数组,为每个元素生成 GEP + store(委托到 gen._init_global_array_from_list)"""
|
||||
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._init_global_array_from_list(builder, pool, mod, array_alloca, list_node, trans)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,24 @@ import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6 对象化重构:模块级无状态函数已迁移为 lib.core.Gen.AssignGenMixin
|
||||
# 的方法,本模块保留同名模块级函数作为"一行委托":延迟 import Gen
|
||||
# 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),再调用
|
||||
# gen 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAugAssign - 增强赋值语句处理(Mixin 继承模式)
|
||||
#
|
||||
@@ -253,79 +271,11 @@ def _apply_aug_op(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None,
|
||||
trans: HT.Translator | t.CPtr = None,
|
||||
lhs_node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""应用增强赋值的二元运算(浮点 + 指针算术 + 整数运算)"""
|
||||
lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty)
|
||||
rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty)
|
||||
lhs_fbits: int = HandlesExpr.get_llvm_float_bits(lhs.Ty)
|
||||
rhs_fbits: int = HandlesExpr.get_llvm_float_bits(rhs.Ty)
|
||||
|
||||
# 浮点运算: 任一操作数为浮点时,使用浮点指令(必须在指针算术之前检查,
|
||||
# 因为 float 的 int bits 为 0,会被误认为指针)
|
||||
if lhs_fbits != 0 or rhs_fbits != 0:
|
||||
# 确定目标浮点类型(使用较大的位宽)
|
||||
target_fbits: int = lhs_fbits
|
||||
if rhs_fbits > target_fbits:
|
||||
target_fbits = rhs_fbits
|
||||
target_float_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
if target_fbits == 32:
|
||||
target_float_ty = llvmlite.Float(pool)
|
||||
# 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc)
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, target_float_ty, node)
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, target_float_ty, node)
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_fadd(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Sub:
|
||||
return llvmlite.build_fsub(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mult:
|
||||
return llvmlite.build_fmul(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Div:
|
||||
return llvmlite.build_fdiv(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mod:
|
||||
return llvmlite.build_frem(builder, lhs, rhs)
|
||||
return None
|
||||
|
||||
# 指针算术: ptr += int / ptr -= int → getelementptr(按元素大小缩放)
|
||||
# 对齐 TPC HandlesAugAssign.py L140-149 / L170-180
|
||||
if lhs_bits == 0 and rhs_bits != 0:
|
||||
if op == ast.OpKind.Add or op == ast.OpKind.Sub:
|
||||
return HandlesExpr.translate_ptr_arith(pool, builder, lhs, rhs, op)
|
||||
return None
|
||||
|
||||
# 整数运算:类型提升
|
||||
if lhs_bits > rhs_bits and rhs_bits > 0:
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty, node)
|
||||
elif rhs_bits > lhs_bits and lhs_bits > 0:
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty, node)
|
||||
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_add(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Sub:
|
||||
return llvmlite.build_sub(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mult:
|
||||
return llvmlite.build_mul(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Div:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.FloorDiv:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mod:
|
||||
return llvmlite.build_srem(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitAnd:
|
||||
return llvmlite.build_and(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitOr:
|
||||
return llvmlite.build_or(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitXor:
|
||||
return llvmlite.build_xor(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.LShift:
|
||||
return llvmlite.build_shl(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.RShift:
|
||||
# 无符号 >> → lshr(逻辑右移),有符号 >> → ashr(算术右移)
|
||||
# 对齐 TPC ExprGen.emit_binary_op:i8/i16 默认无符号;其余查操作数无符号性
|
||||
if lhs_bits == 8 or lhs_bits == 16:
|
||||
return llvmlite.build_lshr(builder, lhs, rhs)
|
||||
if lhs_node is not None and trans is not None:
|
||||
if HandlesExpr._node_type_unsigned(pool, lhs_node, trans) != 0:
|
||||
return llvmlite.build_lshr(builder, lhs, rhs)
|
||||
return llvmlite.build_ashr(builder, lhs, rhs)
|
||||
"""应用增强赋值的二元运算(浮点 + 指针算术 + 整数运算,委托到 gen._apply_aug_op)"""
|
||||
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._apply_aug_op(pool, builder, op, lhs, rhs, node, trans, lhs_node)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -15,63 +15,44 @@ import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesBody - 语句分派(trans 单参模式,全方法调用)
|
||||
# HandlesBody - 语句分派(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。
|
||||
# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 语句翻译分派
|
||||
# ============================================================
|
||||
def translate_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译单条语句,返回新增的变量数"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
if k == ast.ASTKind.Expr:
|
||||
return translate_expr_stmt(trans, node)
|
||||
elif k == ast.ASTKind.Assign:
|
||||
return trans.AssignH.Handle(node)
|
||||
elif k == ast.ASTKind.AnnAssign:
|
||||
return trans.AnnAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.FunctionDef:
|
||||
# 嵌套函数定义:提升为顶层函数 + 创建闭包
|
||||
return HandlesFunctions.translate_nested_function_def(trans, node)
|
||||
elif k == ast.ASTKind.Return:
|
||||
return trans.ReturnH.Handle(node)
|
||||
elif k == ast.ASTKind.If:
|
||||
return trans.IfH.Handle(node)
|
||||
elif k == ast.ASTKind.While:
|
||||
return trans.WhileH.Handle(node)
|
||||
elif k == ast.ASTKind.AugAssign:
|
||||
return trans.AugAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.For:
|
||||
return trans.ForH.Handle(node)
|
||||
elif k == ast.ASTKind.ClassDef:
|
||||
return HandlesClassDef.translate_class_def(trans, node)
|
||||
elif k == ast.ASTKind.Import:
|
||||
return trans.ImportsH.HandleImport(node)
|
||||
elif k == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(node)
|
||||
return trans.ImportsH.HandleImportFromNames(node)
|
||||
elif k == ast.ASTKind.Global:
|
||||
return translate_global(trans, node)
|
||||
elif k == ast.ASTKind.Nonlocal:
|
||||
return translate_nonlocal(trans, node)
|
||||
elif k == ast.ASTKind.Pass:
|
||||
return 0
|
||||
elif k == ast.ASTKind.Break:
|
||||
return translate_break(trans)
|
||||
elif k == ast.ASTKind.Continue:
|
||||
return translate_continue(trans)
|
||||
elif k == ast.ASTKind.Match:
|
||||
return trans.MatchH.Handle(node)
|
||||
elif k == ast.ASTKind.Delete:
|
||||
return translate_delete(trans, node)
|
||||
"""翻译单条语句,返回新增的变量数(委托到 gen.translate_stmt)"""
|
||||
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.translate_stmt(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -83,28 +64,11 @@ def translate_stmt(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def translate_delete(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 del 语句,返回 0"""
|
||||
if trans is None or node is None:
|
||||
return 0
|
||||
dnode: ast.Delete | t.CPtr = (ast.Delete | t.CPtr)(node)
|
||||
if dnode is None or dnode.targets is None:
|
||||
return 0
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
if pool is None or mod is None or builder is None:
|
||||
return 0
|
||||
tn: t.CSizeT = dnode.targets.__len__()
|
||||
for ti in range(tn):
|
||||
tgt: ast.AST | t.CPtr = dnode.targets.get(ti)
|
||||
if tgt is None:
|
||||
continue
|
||||
# del obj.attr → property deleter
|
||||
if tgt.kind() == ast.ASTKind.Attribute:
|
||||
del_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(tgt)
|
||||
if del_at is not None:
|
||||
HandlesExprCall._try_property_deleter(
|
||||
pool, builder, mod, del_at, trans)
|
||||
"""翻译 del 语句,返回 0(委托到 gen.translate_delete)"""
|
||||
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.translate_delete(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -115,20 +79,11 @@ def translate_delete(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def translate_global(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 global 语句:记录 global 变量名"""
|
||||
gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node)
|
||||
if gn is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = gn.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
HT.add_global_name(trans, nm.id)
|
||||
"""翻译 global 语句:记录 global 变量名(委托到 gen.translate_global)"""
|
||||
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.translate_global(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -139,38 +94,14 @@ def translate_global(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def translate_nonlocal(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 nonlocal 语句:记录 nonlocal 变量名及其类型
|
||||
"""翻译 nonlocal 语句:记录 nonlocal 变量名及其类型(委托到 gen.translate_nonlocal)
|
||||
|
||||
类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。
|
||||
"""
|
||||
nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node)
|
||||
if nl is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = nl.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
# 查找父作用域中的变量 alloca,获取类型信息
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, nm.id)
|
||||
if var_alloca is not None and var_alloca.Ty is not None:
|
||||
var_ty = var_alloca.Ty.Pointee
|
||||
# Void 类型视为无效(Pointee 访问异常时可能返回 Void),
|
||||
# 设为 None 让 add_nonlocal_name 回退为 i32,避免生成
|
||||
# "bitcast ... to void*" / "load void, void*" 非法 IR
|
||||
if var_ty is not None:
|
||||
match var_ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
var_ty = None
|
||||
case _:
|
||||
pass
|
||||
HT.add_nonlocal_name(trans, nm.id, var_ty)
|
||||
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.translate_nonlocal(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -179,34 +110,11 @@ def translate_nonlocal(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译表达式语句(printf 调用等)"""
|
||||
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
|
||||
if ex is None:
|
||||
return 0
|
||||
call_node: ast.AST | t.CPtr = ex.value
|
||||
if call_node is None:
|
||||
return 0
|
||||
ck: int = call_node.kind()
|
||||
if ck != ast.ASTKind.Call:
|
||||
return 0
|
||||
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node)
|
||||
func_node: ast.AST | t.CPtr = cl.func
|
||||
if func_node is None:
|
||||
return 0
|
||||
|
||||
func_name: str = HandlesExpr.get_func_name(func_node)
|
||||
if func_name is None:
|
||||
return 0
|
||||
|
||||
# printf / print 走特殊路径(print 是类型感知格式化,不映射到 printf)
|
||||
if string.strcmp(func_name, "printf") == 0:
|
||||
trans.ExprCallH.HandlePrintfCall(cl)
|
||||
elif string.strcmp(func_name, "print") == 0:
|
||||
trans.ExprCallH.HandlePrintCall(cl)
|
||||
else:
|
||||
# 通用函数调用(返回值丢弃)
|
||||
trans.ExprCallH.HandleCall(call_node)
|
||||
"""翻译表达式语句(printf 调用等)(委托到 gen.translate_expr_stmt)"""
|
||||
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.translate_expr_stmt(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -215,13 +123,15 @@ def translate_expr_stmt(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描语句中的 AnnAssign,提前创建 alloca
|
||||
"""预扫描语句中的 AnnAssign,提前创建 alloca(委托到 gen.pre_scan_allocas)
|
||||
|
||||
返回新增的变量数
|
||||
"""
|
||||
if node is None:
|
||||
return 0
|
||||
return trans.AnnAssignH.PreScan(node)
|
||||
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.pre_scan_allocas(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -233,14 +143,11 @@ def pre_scan_allocas(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def pre_scan_scope_decls(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描 Global/Nonlocal 声明,提前注册作用域名称"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Global:
|
||||
return translate_global(trans, node)
|
||||
if k == ast.ASTKind.Nonlocal:
|
||||
return translate_nonlocal(trans, node)
|
||||
"""预扫描 Global/Nonlocal 声明,提前注册作用域名称(委托到 gen.pre_scan_scope_decls)"""
|
||||
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.pre_scan_scope_decls(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -248,26 +155,11 @@ def pre_scan_scope_decls(trans: HT.Translator | t.CPtr,
|
||||
# 翻译 break 语句
|
||||
# ============================================================
|
||||
def translate_break(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 break 语句:跳转到循环 end 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 break 目标
|
||||
if trans._break_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._break_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句(break 后面的代码不可达)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
"""翻译 break 语句:跳转到循环 end 块(委托到 gen.translate_break)"""
|
||||
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.translate_break(trans)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -275,26 +167,11 @@ def translate_break(trans: HT.Translator | t.CPtr) -> int:
|
||||
# 翻译 continue 语句
|
||||
# ============================================================
|
||||
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 continue 目标
|
||||
if trans._continue_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._continue_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
"""翻译 continue 语句:跳转到循环 cond/incr 块(委托到 gen.translate_continue)"""
|
||||
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.translate_continue(trans)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -302,7 +179,9 @@ def translate_continue(trans: HT.Translator | t.CPtr) -> int:
|
||||
# 获取语句类型名(调试用)
|
||||
# ============================================================
|
||||
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
|
||||
"""获取语句类型名"""
|
||||
if node is None:
|
||||
return None
|
||||
return node.type_name()
|
||||
"""获取语句类型名(委托到 gen.get_stmt_kind_name)"""
|
||||
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.get_stmt_kind_name(node)
|
||||
return None
|
||||
@@ -9,8 +9,16 @@ import lib.core.VLogger as VLogger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesEnum - 枚举类型注册和成员查找
|
||||
# HandlesEnum - 枚举类型注册和成员查找(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (模块级全局 _enum_table/_enum_count → gen 实例字段
|
||||
# EnumTable/EnumCount),本模块保留同名模块级函数作为"一行委托":
|
||||
# 延迟 import Gen 取全局单例(BuildPipeline/main 创建后
|
||||
# set_global_gen 注册),再调用 gen 的对应方法。签名与旧函数
|
||||
# 完全一致,调用方零改动。
|
||||
#
|
||||
# EnumEntry/EnumMember 类型保留在本模块(gen 字段类型引用)。
|
||||
# 管理 t.CEnum 派生类的成员信息:
|
||||
# - 枚举名 → EnumEntry(基准类型 + 成员表)
|
||||
# - 成员名 → EnumMember(值、类型)
|
||||
@@ -44,53 +52,55 @@ class EnumEntry:
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局注册表(静态分配)
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_enum_table: EnumEntry | t.CPtr = None
|
||||
_enum_count: int = 0
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_enum_table — 初始化枚举注册表
|
||||
# ============================================================
|
||||
def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化枚举注册表,返回 1 成功"""
|
||||
global _enum_table, _enum_count
|
||||
|
||||
if _enum_table is not None:
|
||||
return 1
|
||||
|
||||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||||
_enum_table = pool.alloc(entry_size * ENUM_MAX)
|
||||
if _enum_table is None:
|
||||
return 0
|
||||
string.memset(_enum_table, 0, entry_size * ENUM_MAX)
|
||||
_enum_count = 0
|
||||
return 1
|
||||
"""初始化枚举注册表,返回 1 成功(委托到 gen.init_enum_table)"""
|
||||
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.init_enum_table(pool)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_entry — 获取第 i 个 EnumEntry 槽位
|
||||
# ============================================================
|
||||
def _get_enum_entry(i: int) -> EnumEntry | t.CPtr:
|
||||
"""获取第 i 个枚举条目"""
|
||||
if _enum_table is None or i < 0 or i >= ENUM_MAX:
|
||||
return None
|
||||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(_enum_table) + i * entry_size
|
||||
return (EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
"""获取第 i 个枚举条目(委托到 gen._get_enum_entry)"""
|
||||
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._get_enum_entry(i)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_member — 获取枚举中第 i 个 EnumMember 槽位
|
||||
# ============================================================
|
||||
def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.CPtr:
|
||||
"""获取枚举中第 i 个成员条目"""
|
||||
if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX:
|
||||
return None
|
||||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size
|
||||
return (EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
"""获取枚举中第 i 个成员条目(委托到 gen._get_enum_member)"""
|
||||
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._get_enum_member(enum_entry, i)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -101,46 +111,12 @@ def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.C
|
||||
def register_enum(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr:
|
||||
global _enum_count
|
||||
"""注册枚举类型,返回 EnumEntry 指针"""
|
||||
if init_enum_table(pool) == 0:
|
||||
return None
|
||||
|
||||
# 检查是否已注册
|
||||
existing: EnumEntry | t.CPtr = find_enum(name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
|
||||
if _enum_count >= ENUM_MAX:
|
||||
fb_et: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_et is not None:
|
||||
viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name)
|
||||
VLogger.error(fb_et, "ENUM")
|
||||
return None
|
||||
|
||||
entry: EnumEntry | t.CPtr = _get_enum_entry(_enum_count)
|
||||
if entry is None:
|
||||
return None
|
||||
|
||||
# 分配成员数组
|
||||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||||
entry.Members = pool.alloc(member_size * ENUM_MEMBER_MAX)
|
||||
if entry.Members is None:
|
||||
return None
|
||||
string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX)
|
||||
|
||||
# 复制类名
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, name)
|
||||
entry.Name = name_buf
|
||||
|
||||
entry.BaseTy = base_ty
|
||||
entry.MemberCount = 0
|
||||
|
||||
_enum_count += 1
|
||||
return entry
|
||||
"""注册枚举类型,返回 EnumEntry 指针(委托到 gen.register_enum)"""
|
||||
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.register_enum(pool, name, base_ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -151,48 +127,23 @@ def add_enum_member(pool: memhub.MemBuddy | t.CPtr,
|
||||
member_name: str,
|
||||
member_val: t.CInt64T,
|
||||
member_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""向枚举添加成员,返回成员索引(-1 失败)"""
|
||||
if enum_entry is None or member_name is None or member_ty is None:
|
||||
return -1
|
||||
|
||||
if enum_entry.MemberCount >= ENUM_MEMBER_MAX:
|
||||
fb_em: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_em is not None:
|
||||
viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name)
|
||||
VLogger.error(fb_em, "ENUM")
|
||||
return -1
|
||||
|
||||
idx: int = enum_entry.MemberCount
|
||||
me: EnumMember | t.CPtr = _get_enum_member(enum_entry, idx)
|
||||
if me is None:
|
||||
return -1
|
||||
|
||||
# 复制成员名
|
||||
name_len: t.CSizeT = string.strlen(member_name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, member_name)
|
||||
me.Name = name_buf
|
||||
|
||||
me.Value = member_val
|
||||
me.Ty = member_ty
|
||||
|
||||
enum_entry.MemberCount = idx + 1
|
||||
return idx
|
||||
"""向枚举添加成员,返回成员索引(-1 失败,委托到 gen.add_enum_member)"""
|
||||
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.add_enum_member(pool, enum_entry, member_name, member_val, member_ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_enum — 按枚举类名查找
|
||||
# ============================================================
|
||||
def find_enum(name: str) -> EnumEntry | t.CPtr:
|
||||
"""按枚举类名查找,返回 EnumEntry 或 None"""
|
||||
if name is None or _enum_table is None:
|
||||
return None
|
||||
for i in range(_enum_count):
|
||||
entry: EnumEntry | t.CPtr = _get_enum_entry(i)
|
||||
if entry is not None and entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
"""按枚举类名查找,返回 EnumEntry 或 None(委托到 gen.find_enum)"""
|
||||
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.find_enum(name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -201,17 +152,11 @@ def find_enum(name: str) -> EnumEntry | t.CPtr:
|
||||
# ============================================================
|
||||
def lookup_enum_member(enum_name: str,
|
||||
member_name: str) -> EnumMember | t.CPtr:
|
||||
"""按枚举类名和成员名查找,返回 EnumMember 或 None"""
|
||||
if enum_name is None or member_name is None:
|
||||
return None
|
||||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||||
if entry is None:
|
||||
return None
|
||||
for mi in range(entry.MemberCount):
|
||||
me: EnumMember | t.CPtr = _get_enum_member(entry, mi)
|
||||
if me is not None and me.Name is not None:
|
||||
if string.strcmp(me.Name, member_name) == 0:
|
||||
return me
|
||||
"""按枚举类名和成员名查找,返回 EnumMember 或 None(委托到 gen.lookup_enum_member)"""
|
||||
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.lookup_enum_member(enum_name, member_name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -219,11 +164,11 @@ def lookup_enum_member(enum_name: str,
|
||||
# is_enum_class — 检查类名是否为已注册枚举
|
||||
# ============================================================
|
||||
def is_enum_class(name: str) -> int:
|
||||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否"""
|
||||
if name is None:
|
||||
return 0
|
||||
if find_enum(name) is not None:
|
||||
return 1
|
||||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否(委托到 gen.is_enum_class)"""
|
||||
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.is_enum_class(name)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -231,8 +176,9 @@ def is_enum_class(name: str) -> int:
|
||||
# get_enum_base_type — 按枚举类名获取基准类型
|
||||
# ============================================================
|
||||
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""按枚举类名获取基准类型"""
|
||||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||||
if entry is not None:
|
||||
return entry.BaseTy
|
||||
"""按枚举类名获取基准类型(委托到 gen.get_enum_base_type)"""
|
||||
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.get_enum_base_type(enum_name)
|
||||
return None
|
||||
@@ -15,7 +15,11 @@ import lib.core.Handles.HandlesType as HandlesType
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesFor - for 循环语句处理(Mixin 继承模式)
|
||||
# HandlesFor - for 循环语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# NewForHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (ForHandle 类保留:trans.ForH 的类型,由 HandlesTranslator.
|
||||
# _init_state 经 NewForHandle 委托创建)。
|
||||
#
|
||||
# 支持 for i in range(start, stop, step) 模式:
|
||||
# %i = alloca i32
|
||||
@@ -37,6 +41,22 @@ import lib.core.Handles.HandlesType as HandlesType
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class ForHandle(HandlesBase.Mixin):
|
||||
"""for 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
@@ -599,13 +619,13 @@ class ForHandle(HandlesBase.Mixin):
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewForHandle - 工厂函数
|
||||
# NewForHandle - 工厂函数(委托到 gen.NewForHandle)
|
||||
# ============================================================
|
||||
def NewForHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ForHandle | t.CPtr:
|
||||
h: ForHandle | t.CPtr = pool.alloc(ForHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ForHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
"""创建 ForHandle 实例(委托到 gen.NewForHandle)"""
|
||||
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.NewForHandle(pool, trans)
|
||||
return None
|
||||
@@ -16,6 +16,20 @@ import lib.Projectrans.Config as Config
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesIf - if/elif/else 语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# 编译期 CIf 求值的模块级函数(_is_cif_attr/_is_cif_call/
|
||||
# _get_platform_macro_value/_cif_name_value/_cif_attr_value/
|
||||
# _cif_eval_node/_evaluate_cif_test)已迁移为 lib.core.Gen.
|
||||
# StmtGenMixin 的方法(_g_cif_eval_ok → gen 实例字段 CifEvalOk),
|
||||
# 本模块保留同名模块级函数作为"一行委托";模块级 _g_cif_eval_ok
|
||||
# 保留为镜像,委托后同步 gen.CifEvalOk(IfHandle.Handle 直接读它)。
|
||||
#
|
||||
# IfHandle 类(trans.IfH 的类型)保留:由 HandlesTranslator.
|
||||
# _init_state 通过 NewIfHandle 工厂创建,Handle 方法内部经模块级
|
||||
# 委托函数访问 gen。
|
||||
# ============================================================
|
||||
|
||||
# 编译期宏条件: if c.CIf(...) / c.CIfdef(...) / c.CIfndef(...)
|
||||
#
|
||||
# 对齐 TPC HandlesIf.py:编译期求值命中分支并剪枝(不发射运行时 IR)。
|
||||
@@ -26,81 +40,55 @@ import lib.Projectrans.Config as Config
|
||||
# 求值失败(如运行时变量 val == 1)→ 回退运行时翻译
|
||||
# (c.CIf 由 HandlesExprCall.translate_call 特判翻译成运行时真值,
|
||||
# c.CIfdef/c.CIfndef 运行时恒真,对齐 TPC HandlesExprCall.py L2434-2446)。
|
||||
# ============================================================
|
||||
|
||||
_g_cif_eval_ok: int = 0
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
def _is_cif_attr(attr: str) -> int:
|
||||
"""检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)"""
|
||||
if attr is None:
|
||||
return 0
|
||||
if string.strcmp(attr, "CIf") == 0: return 1
|
||||
if string.strcmp(attr, "CIfdef") == 0: return 1
|
||||
if string.strcmp(attr, "CIfndef") == 0: return 1
|
||||
"""检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)(委托到 gen._is_cif_attr)"""
|
||||
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._is_cif_attr(attr)
|
||||
return 0
|
||||
|
||||
|
||||
def _is_cif_call(node: ast.AST | t.CPtr) -> int:
|
||||
"""检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用"""
|
||||
if node is None or node.kind() != ast.ASTKind.Call:
|
||||
return 0
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if cl.func is None:
|
||||
return 0
|
||||
fk: int = cl.func.kind()
|
||||
if fk == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
if at.attr is None:
|
||||
return 0
|
||||
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
|
||||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if vn.id is not None and string.strcmp(vn.id, "c") == 0:
|
||||
return _is_cif_attr(at.attr)
|
||||
return 0
|
||||
if fk == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func)
|
||||
if nm.id is not None and _is_cif_attr(nm.id) != 0:
|
||||
return 1
|
||||
"""检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用(委托到 gen._is_cif_call)"""
|
||||
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._is_cif_call(node)
|
||||
return 0
|
||||
|
||||
|
||||
def _get_platform_macro_value(name: str) -> int:
|
||||
"""平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。
|
||||
|
||||
命中置 _g_cif_eval_ok=1;未命中置 0 返回 0。
|
||||
命中置 _g_cif_eval_ok=1;未命中置 0 返回 0(委托到 gen._get_platform_macro_value)。
|
||||
"""
|
||||
global _g_cif_eval_ok
|
||||
_g_cif_eval_ok = 0
|
||||
if name is None:
|
||||
return 0
|
||||
triple: str = Config.TargetTriple
|
||||
if triple is None:
|
||||
triple = "x86_64-pc-windows-gnu"
|
||||
is_win: int = 0
|
||||
is_linux: int = 0
|
||||
is_x64: int = 0
|
||||
if string.strstr(triple, "windows") is not None \
|
||||
or string.strstr(triple, "win32") is not None \
|
||||
or string.strstr(triple, "mingw") is not None \
|
||||
or string.strstr(triple, "msvc") is not None:
|
||||
is_win = 1
|
||||
if string.strstr(triple, "linux") is not None:
|
||||
is_linux = 1
|
||||
if string.strstr(triple, "x86_64") is not None:
|
||||
is_x64 = 1
|
||||
# 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致)
|
||||
if string.strcmp(name, "_WIN32") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "WIN32") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "_WIN64") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "WIN64") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0
|
||||
if string.strcmp(name, "__linux__") == 0: _g_cif_eval_ok = is_linux; return 1 if is_linux else 0
|
||||
if string.strcmp(name, "__x86_64__") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "__x86_64") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "_M_X64") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0
|
||||
if string.strcmp(name, "SIZEOF_VOID_P") == 0: _g_cif_eval_ok = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "__SIZEOF_POINTER__") == 0: _g_cif_eval_ok = 1; return 8 if is_x64 else 4
|
||||
if string.strcmp(name, "NDEBUG") == 0: _g_cif_eval_ok = 1; return 0
|
||||
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:
|
||||
v: int = g._get_platform_macro_value(name)
|
||||
_g_cif_eval_ok = g.CifEvalOk
|
||||
return v
|
||||
return 0
|
||||
|
||||
|
||||
@@ -109,24 +97,15 @@ def _cif_name_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。
|
||||
|
||||
命中置 _g_cif_eval_ok=1(值 0 也算命中,如 DISABLED=0);未命中置 0。
|
||||
命中置 _g_cif_eval_ok=1(值 0 也算命中,如 DISABLED=0);未命中置 0(委托到 gen._cif_name_value)。
|
||||
"""
|
||||
global _g_cif_eval_ok
|
||||
_g_cif_eval_ok = 0
|
||||
if name is None or trans is None:
|
||||
return 0
|
||||
v: int = HandlesType.lookup_cdefine_constant(name)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
_g_cif_eval_ok = 1
|
||||
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:
|
||||
v: int = g._cif_name_value(pool, trans, name)
|
||||
_g_cif_eval_ok = g.CifEvalOk
|
||||
return v
|
||||
v2: int = HandlesExpr._lookup_cross_module_cdefine(
|
||||
pool, name, trans._from_imports, trans._imported_modules)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
_g_cif_eval_ok = 1
|
||||
return v2
|
||||
pv: int = _get_platform_macro_value(name)
|
||||
if _g_cif_eval_ok != 0:
|
||||
return pv
|
||||
return 0
|
||||
|
||||
|
||||
@@ -135,45 +114,15 @@ def _cif_attr_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
at: ast.Attribute | t.CPtr) -> int:
|
||||
"""Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。
|
||||
|
||||
命中置 _g_cif_eval_ok=1;未命中置 0。
|
||||
命中置 _g_cif_eval_ok=1;未命中置 0(委托到 gen._cif_attr_value)。
|
||||
"""
|
||||
global _g_cif_eval_ok
|
||||
_g_cif_eval_ok = 0
|
||||
if at is None or at.attr is None or at.value is None or trans is None:
|
||||
return 0
|
||||
if at.value.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
|
||||
if vn.id is None:
|
||||
return 0
|
||||
v: int = HandlesType.lookup_cdefine_constant(at.attr)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
_g_cif_eval_ok = 1
|
||||
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:
|
||||
v: int = g._cif_attr_value(pool, trans, at)
|
||||
_g_cif_eval_ok = g.CifEvalOk
|
||||
return v
|
||||
# 跨模块: 确定真实模块名(解析 from_imports 别名)
|
||||
real_mod: str = vn.id
|
||||
if trans._from_imports is not None:
|
||||
resolved: str = HandlesImports.lookup_from_import(
|
||||
trans._from_imports, vn.id, 0)
|
||||
if resolved is not None:
|
||||
rm_len: t.CSizeT = 0
|
||||
while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':':
|
||||
rm_len += 1
|
||||
rm_buf: str = pool.alloc(rm_len + 1)
|
||||
if rm_buf is not None:
|
||||
for rm_i in range(rm_len):
|
||||
rm_buf[rm_i] = resolved[rm_i]
|
||||
rm_buf[rm_len] = '\0'
|
||||
real_mod = rm_buf
|
||||
fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod) + 2
|
||||
fi: str = pool.alloc(fi_len)
|
||||
if fi is None:
|
||||
return 0
|
||||
viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod)
|
||||
v2: int = HandlesExpr._lookup_cross_module_cdefine(pool, at.attr, fi)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
_g_cif_eval_ok = 1
|
||||
return v2
|
||||
return 0
|
||||
|
||||
|
||||
@@ -185,128 +134,15 @@ def _cif_eval_node(pool: memhub.MemBuddy | t.CPtr,
|
||||
支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine)
|
||||
/ BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=)
|
||||
/ BoolOp(and/or) / UnaryOp(not - + ~)。
|
||||
成功置 _g_cif_eval_ok=1;失败(含运行时变量)置 0 返回 0。
|
||||
成功置 _g_cif_eval_ok=1;失败(含运行时变量)置 0 返回 0(委托到 gen._cif_eval_node)。
|
||||
"""
|
||||
global _g_cif_eval_ok
|
||||
if node is None:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
_g_cif_eval_ok = 1
|
||||
return cn.int_val
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
|
||||
if nm.id is None:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
return _cif_name_value(pool, trans, nm.id)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
return _cif_attr_value(pool, trans, at)
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
|
||||
if uop.operand is None:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
ov: int = _cif_eval_node(pool, trans, uop.operand)
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0
|
||||
if uop.op == ast.OpKind.USub: return -ov
|
||||
if uop.op == ast.OpKind.UAdd: return ov
|
||||
if uop.op == ast.OpKind.Invert: return ~ov
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node)
|
||||
vals: list[ast.AST | t.CPtr] | t.CPtr = bo.values
|
||||
if vals is None:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
bn: t.CSizeT = vals.__len__()
|
||||
if bo.op == ast.OpKind.And:
|
||||
for bi in range(bn):
|
||||
rv: int = _cif_eval_node(pool, trans, vals.get(bi))
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
if rv == 0:
|
||||
return 0
|
||||
return 1
|
||||
if bo.op == ast.OpKind.Or:
|
||||
for bi in range(bn):
|
||||
rv: int = _cif_eval_node(pool, trans, vals.get(bi))
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
if rv != 0:
|
||||
return 1
|
||||
return 0
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node)
|
||||
lv: int = _cif_eval_node(pool, trans, cmp.left)
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops)
|
||||
comps: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators
|
||||
if ops_list is None or comps is None:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
cc: t.CSizeT = comps.__len__()
|
||||
ci: t.CSizeT
|
||||
for ci in range(cc):
|
||||
rv: int = _cif_eval_node(pool, trans, comps.get(ci))
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
op_id: int = ops_list.get(ci)
|
||||
ok_cmp: int = 0
|
||||
if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0
|
||||
elif op_id == ast.OpKind.Ne: ok_cmp = 1 if lv != rv else 0
|
||||
elif op_id == ast.OpKind.Lt: ok_cmp = 1 if lv < rv else 0
|
||||
elif op_id == ast.OpKind.Le: ok_cmp = 1 if lv <= rv else 0
|
||||
elif op_id == ast.OpKind.Gt: ok_cmp = 1 if lv > rv else 0
|
||||
elif op_id == ast.OpKind.Ge: ok_cmp = 1 if lv >= rv else 0
|
||||
else:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
if ok_cmp == 0:
|
||||
return 0
|
||||
lv = rv
|
||||
return 1
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
lv: int = _cif_eval_node(pool, trans, bop.left)
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
rv: int = _cif_eval_node(pool, trans, bop.right)
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
if bop.op == ast.OpKind.Add: return lv + rv
|
||||
if bop.op == ast.OpKind.Sub: return lv - rv
|
||||
if bop.op == ast.OpKind.Mult: return lv * rv
|
||||
if bop.op == ast.OpKind.FloorDiv:
|
||||
if rv == 0:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
return lv // rv
|
||||
if bop.op == ast.OpKind.Mod:
|
||||
if rv == 0:
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
return lv % rv
|
||||
if bop.op == ast.OpKind.BitAnd: return lv & rv
|
||||
if bop.op == ast.OpKind.BitOr: return lv | rv
|
||||
if bop.op == ast.OpKind.BitXor: return lv ^ rv
|
||||
if bop.op == ast.OpKind.LShift: return lv << rv
|
||||
if bop.op == ast.OpKind.RShift: return lv >> rv
|
||||
_g_cif_eval_ok = 0
|
||||
return 0
|
||||
_g_cif_eval_ok = 0
|
||||
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:
|
||||
v: int = g._cif_eval_node(pool, trans, node)
|
||||
_g_cif_eval_ok = g.CifEvalOk
|
||||
return v
|
||||
return 0
|
||||
|
||||
|
||||
@@ -316,59 +152,16 @@ def _evaluate_cif_test(pool: memhub.MemBuddy | t.CPtr,
|
||||
"""求值 CIf 调用(test 必须是 c.CIf 系调用)。
|
||||
|
||||
成功: 置 _g_cif_eval_ok=1,返回条件值(0/1)
|
||||
失败(运行时变量/未知结构): 置 _g_cif_eval_ok=0,返回 0
|
||||
失败(运行时变量/未知结构): 置 _g_cif_eval_ok=0,返回 0(委托到 gen._evaluate_cif_test)。
|
||||
"""
|
||||
global _g_cif_eval_ok
|
||||
_g_cif_eval_ok = 0
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(test)
|
||||
if cl is None or cl.func is None:
|
||||
return 0
|
||||
kind: str = None
|
||||
fk: int = cl.func.kind()
|
||||
if fk == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
|
||||
kind = at.attr
|
||||
elif fk == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func)
|
||||
kind = nm.id
|
||||
if kind is None:
|
||||
return 0
|
||||
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
|
||||
if cargs is None or cargs.__len__() < 1:
|
||||
return 0
|
||||
arg0: ast.AST | t.CPtr = cargs.get(0)
|
||||
if string.strcmp(kind, "CIf") == 0:
|
||||
v: int = _cif_eval_node(pool, trans, arg0)
|
||||
if _g_cif_eval_ok == 0:
|
||||
return 0
|
||||
return 1 if v != 0 else 0
|
||||
# CIfdef / CIfndef: 判定宏名是否已定义
|
||||
defined: int = 0
|
||||
if arg0 is not None and arg0.kind() == ast.ASTKind.Name:
|
||||
nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0)
|
||||
if nm0.id is None:
|
||||
return 0
|
||||
_cif_name_value(pool, trans, nm0.id)
|
||||
defined = _g_cif_eval_ok
|
||||
elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant:
|
||||
cn0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0)
|
||||
if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None:
|
||||
_cif_name_value(pool, trans, cn0.str_val)
|
||||
defined = _g_cif_eval_ok
|
||||
else:
|
||||
return 0
|
||||
elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute:
|
||||
at0: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg0)
|
||||
_cif_attr_value(pool, trans, at0)
|
||||
defined = _g_cif_eval_ok
|
||||
else:
|
||||
return 0
|
||||
# 定义判定本身成功(未定义名特判:不报错,defined=0 走 else)
|
||||
_g_cif_eval_ok = 1
|
||||
if string.strcmp(kind, "CIfdef") == 0:
|
||||
return 1 if defined != 0 else 0
|
||||
# CIfndef
|
||||
return 0 if defined != 0 else 1
|
||||
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:
|
||||
v: int = g._evaluate_cif_test(pool, trans, test)
|
||||
_g_cif_eval_ok = g.CifEvalOk
|
||||
return v
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -526,13 +319,13 @@ class IfHandle(HandlesBase.Mixin):
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewIfHandle - 工厂函数
|
||||
# NewIfHandle - 工厂函数(委托到 gen.NewIfHandle)
|
||||
# ============================================================
|
||||
def NewIfHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr:
|
||||
h: IfHandle | t.CPtr = pool.alloc(IfHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, IfHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
"""创建 IfHandle 实例(委托到 gen.NewIfHandle)"""
|
||||
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.NewIfHandle(pool, trans)
|
||||
return None
|
||||
@@ -16,16 +16,46 @@ import lib.core.StubMerger as StubMerger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesImports - 导入语句处理(Mixin 继承模式)
|
||||
# HandlesImports - 导入语句处理(P6-D 对象化后的委托层)
|
||||
#
|
||||
# 管理 _imported_modules 和 _from_imports 字符串
|
||||
# 注意:str = bytes = t.CChar | t.CPtr = i8*
|
||||
#
|
||||
# P6-D 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.ImportsGenMixin 的方法
|
||||
# (全局状态 _g_reexport_* 与 _g_current_file 迁入 gen 字段),本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
# ImportsHandle 类与 NewImportsHandle 工厂保留在本模块(对象工厂,
|
||||
# 不依赖 gen 状态,与 HandlesExpr.NewExprHandle 模式一致)。
|
||||
# ============================================================
|
||||
|
||||
MAX_REEXPORT: t.CDefine = 512
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模块级工具函数(保留供外部调用)
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6-D 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# ImportsGenMixin 方法,避免函数体 import 包模块与 Generator
|
||||
# 类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 添加已导入模块名
|
||||
@@ -33,57 +63,23 @@ import lib.core.StubMerger as StubMerger
|
||||
def add_imported_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
imported_modules: str,
|
||||
name: str) -> str:
|
||||
"""记录已导入的模块名,返回新的 imported_modules 字符串指针"""
|
||||
if name is None:
|
||||
return imported_modules
|
||||
if imported_modules is None:
|
||||
nlen: t.CSizeT = string.strlen(name)
|
||||
buf: t.CChar | t.CPtr = pool.alloc(nlen + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, name)
|
||||
return buf
|
||||
return None
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(imported_modules)
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
new_len: t.CSizeT = old_len + 1 + name_len
|
||||
buf2: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf2 is not None:
|
||||
string.strcpy(buf2, imported_modules)
|
||||
buf2[old_len] = ' '
|
||||
string.strcpy(buf2 + old_len + 1, name)
|
||||
return buf2
|
||||
return imported_modules
|
||||
"""记录已导入的模块名,返回新的 imported_modules 字符串指针(委托到 gen.add_imported_module)"""
|
||||
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.add_imported_module(pool, imported_modules, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 检查模块是否已导入
|
||||
# ============================================================
|
||||
def is_module_imported(imported_modules: str, name: str) -> int:
|
||||
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配)"""
|
||||
if name is None or imported_modules is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = imported_modules
|
||||
total_len: t.CSizeT = string.strlen(imported_modules)
|
||||
ci: t.CSizeT = 0
|
||||
while ci < total_len:
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
word_start: t.CSizeT = ci
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
word_len: t.CSizeT = ci - word_start
|
||||
if word_len == name_len:
|
||||
match: int = 1
|
||||
for ei in range(name_len):
|
||||
if cur[word_start + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
if match == 1:
|
||||
return 1
|
||||
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配,委托到 gen.is_module_imported)"""
|
||||
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.is_module_imported(imported_modules, name)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -95,35 +91,18 @@ def add_from_import(pool: memhub.MemBuddy | t.CPtr,
|
||||
local_name: str,
|
||||
module_name: str,
|
||||
original_name: str = None) -> str:
|
||||
"""添加 from-import 映射,返回新的 from_imports 字符串
|
||||
"""添加 from-import 映射,返回新的 from_imports 字符串(委托到 gen.add_from_import)
|
||||
|
||||
格式:
|
||||
无别名: "local_name:module_name"
|
||||
有别名: "local_name:module_name:original_name"
|
||||
(original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰)
|
||||
"""
|
||||
if local_name is None or module_name is None:
|
||||
return from_imports
|
||||
entry: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if entry is None:
|
||||
return from_imports
|
||||
if original_name is not None and string.strcmp(original_name, local_name) != 0:
|
||||
viperlib.snprintf(entry, 256, "%s:%s:%s", local_name, module_name, original_name)
|
||||
else:
|
||||
viperlib.snprintf(entry, 256, "%s:%s", local_name, module_name)
|
||||
if from_imports is None:
|
||||
return entry
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(from_imports)
|
||||
entry_len: t.CSizeT = string.strlen(entry)
|
||||
new_len: t.CSizeT = old_len + 1 + entry_len
|
||||
buf: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, from_imports)
|
||||
buf[old_len] = ' '
|
||||
string.strcpy(buf + old_len + 1, entry)
|
||||
return buf
|
||||
return from_imports
|
||||
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.add_from_import(pool, from_imports, local_name, module_name, original_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -134,64 +113,11 @@ def add_from_import(pool: memhub.MemBuddy | t.CPtr,
|
||||
# ============================================================
|
||||
def lookup_from_import_original(from_imports: str,
|
||||
local_name: str) -> str:
|
||||
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到"""
|
||||
if local_name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(local_name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到第一个 ':' 的位置
|
||||
colon1: t.CSizeT = ci
|
||||
while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ':
|
||||
colon1 += 1
|
||||
if colon1 >= total_len or cur[colon1] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon1 - ci
|
||||
# 跳过 star import
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
continue
|
||||
# 比较名称
|
||||
if entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != local_name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
# 找到匹配,检查是否有第三个字段(原始名)
|
||||
pos: t.CSizeT = colon1 + 1
|
||||
# 跳过模块名
|
||||
while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0':
|
||||
pos += 1
|
||||
if pos < total_len and cur[pos] == ':':
|
||||
# 有第三个字段: original_name
|
||||
orig_start: t.CSizeT = pos + 1
|
||||
orig_end: t.CSizeT = orig_start
|
||||
while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0':
|
||||
orig_end += 1
|
||||
orig_len: t.CSizeT = orig_end - orig_start
|
||||
if orig_len > 0:
|
||||
orig_buf: str = cur + orig_start
|
||||
# 返回指向内部的指针(调用方需在使用期内保持 from_imports 有效)
|
||||
return orig_buf
|
||||
return None
|
||||
return None
|
||||
# 跳到下一个条目
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到(委托到 gen.lookup_from_import_original)"""
|
||||
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.lookup_from_import_original(from_imports, local_name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -205,83 +131,16 @@ def lookup_from_import_original(from_imports: str,
|
||||
# ============================================================
|
||||
def lookup_from_import(from_imports: str, name: str,
|
||||
allow_star_fallback: int = 1) -> str:
|
||||
"""查找 from-import 名称,返回模块名或 None
|
||||
"""查找 from-import 名称,返回模块名或 None(委托到 gen.lookup_from_import)
|
||||
|
||||
支持 star import: 如果 from_imports 中有 "*:module" 条目,
|
||||
且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。
|
||||
"""
|
||||
if name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
star_mod: str = None
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到 ':' 的位置
|
||||
colon_pos: t.CSizeT = ci
|
||||
while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ':
|
||||
colon_pos += 1
|
||||
if colon_pos >= total_len or cur[colon_pos] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon_pos - ci
|
||||
# 检测 star import ("*:module")
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
mod_start: t.CSizeT = colon_pos + 1
|
||||
mod_end: t.CSizeT = mod_start
|
||||
while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':':
|
||||
mod_end += 1
|
||||
star_mod = cur + mod_start
|
||||
# 比较名称
|
||||
elif entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
mod_start2: t.CSizeT = colon_pos + 1
|
||||
mod_end2: t.CSizeT = mod_start2
|
||||
# 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符)
|
||||
while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':':
|
||||
mod_end2 += 1
|
||||
return cur + mod_start2
|
||||
# 跳到下一个条目
|
||||
ci = colon_pos
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
# 未找到精确匹配,仅在允许时回退到 star import
|
||||
if allow_star_fallback == 0:
|
||||
return None
|
||||
return star_mod
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 re-export 映射表(module_sha1 + func_name → source_module)
|
||||
#
|
||||
# 当 ast/__init__.vp 中有 from .lexer import _lexer_init 时,
|
||||
# _lexer_init 被 re-export 为 ast._lexer_init。
|
||||
# 跨模块调用 ast._lexer_init(...) 需使用 ast.lexer 的 SHA1 混淆,
|
||||
# 而非 ast 的 SHA1。
|
||||
#
|
||||
# 数据布局:
|
||||
# _g_reexport_sha1s: 每条 17 字节(SHA1 16字符 + null)
|
||||
# _g_reexport_funcs: 每条 64 字节(函数名 + null)
|
||||
# _g_reexport_srcs: 每条 64 字节(源模块名 + null)
|
||||
# ============================================================
|
||||
MAX_REEXPORT: t.CDefine = 512
|
||||
|
||||
_g_reexport_sha1s: bytes = None
|
||||
_g_reexport_funcs: bytes = None
|
||||
_g_reexport_srcs: bytes = None
|
||||
_g_reexport_count: int = 0
|
||||
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.lookup_from_import(from_imports, name, allow_star_fallback)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -294,42 +153,11 @@ _g_reexport_count: int = 0
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。
|
||||
# ============================================================
|
||||
def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int:
|
||||
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败"""
|
||||
global _g_reexport_sha1s, _g_reexport_funcs, _g_reexport_srcs, _g_reexport_count
|
||||
if mod_sha1 is None or func_name is None or source_module is None:
|
||||
return -1
|
||||
# 懒初始化
|
||||
if _g_reexport_sha1s is None:
|
||||
_g_reexport_sha1s = stdlib.malloc(MAX_REEXPORT * 17)
|
||||
_g_reexport_funcs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
_g_reexport_srcs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
if _g_reexport_sha1s is None or _g_reexport_funcs is None or _g_reexport_srcs is None:
|
||||
return -1
|
||||
string.memset(_g_reexport_sha1s, 0, MAX_REEXPORT * 17)
|
||||
string.memset(_g_reexport_funcs, 0, MAX_REEXPORT * 64)
|
||||
string.memset(_g_reexport_srcs, 0, MAX_REEXPORT * 64)
|
||||
if _g_reexport_count >= MAX_REEXPORT:
|
||||
return -1
|
||||
# 幂等检查:查找是否已存在相同映射
|
||||
for i in range(_g_reexport_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0:
|
||||
# 已存在,更新 source_module(以防变化;64 字节槽,strncpy 钳制)
|
||||
string.strncpy(_g_reexport_srcs + fidx, source_module, 63)
|
||||
_g_reexport_srcs[fidx + 63] = '\0'
|
||||
return 0
|
||||
# 添加新条目(槽位定长 17/64 字节,strcpy 无界会越界写相邻槽,全部 strncpy 钳制)
|
||||
idx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 17
|
||||
fidx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 64
|
||||
string.strncpy(_g_reexport_sha1s + idx2, mod_sha1, 16)
|
||||
_g_reexport_sha1s[idx2 + 16] = '\0'
|
||||
string.strncpy(_g_reexport_funcs + fidx2, func_name, 63)
|
||||
_g_reexport_funcs[fidx2 + 63] = '\0'
|
||||
string.strncpy(_g_reexport_srcs + fidx2, source_module, 63)
|
||||
_g_reexport_srcs[fidx2 + 63] = '\0'
|
||||
_g_reexport_count += 1
|
||||
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败(委托到 gen.register_reexport)"""
|
||||
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.register_reexport(mod_sha1, func_name, source_module)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -340,17 +168,11 @@ def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int:
|
||||
# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。
|
||||
# ============================================================
|
||||
def lookup_reexport(mod_sha1: str, func_name: str) -> str:
|
||||
"""查找 re-export 映射,返回源模块名或 None"""
|
||||
if mod_sha1 is None or func_name is None:
|
||||
return None
|
||||
if _g_reexport_sha1s is None or _g_reexport_count <= 0:
|
||||
return None
|
||||
for i in range(_g_reexport_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0:
|
||||
return _g_reexport_srcs + fidx
|
||||
"""查找 re-export 映射,返回源模块名或 None(委托到 gen.lookup_reexport)"""
|
||||
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.lookup_reexport(mod_sha1, func_name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -375,57 +197,15 @@ def lookup_reexport(mod_sha1: str, func_name: str) -> str:
|
||||
# 无法解析时返回 module(回退到原始值)
|
||||
# ============================================================
|
||||
def _resolve_relative_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
current_package: str,
|
||||
level: t.CInt,
|
||||
module: str) -> str:
|
||||
"""解析相对导入为完整模块名"""
|
||||
if level <= 0:
|
||||
return module
|
||||
if current_package is None:
|
||||
return module
|
||||
|
||||
# 从 current_package 开始,上溯 (level-1) 级
|
||||
pkg: str = current_package
|
||||
up: t.CInt = level - 1
|
||||
while up > 0:
|
||||
pkg_len: t.CSizeT = string.strlen(pkg)
|
||||
last_dot: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < pkg_len:
|
||||
if pkg[i] == '.':
|
||||
last_dot = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无更多父级,包变为空
|
||||
pkg = None
|
||||
break
|
||||
# 截断到最后一个 '.' 处
|
||||
new_pkg: str = pool.alloc(last_dot + 1)
|
||||
if new_pkg is None:
|
||||
return module
|
||||
string.strncpy(new_pkg, pkg, last_dot)
|
||||
new_pkg[last_dot] = '\0'
|
||||
pkg = new_pkg
|
||||
up -= 1
|
||||
|
||||
if module is None:
|
||||
# from . import Y → 模块就是包本身
|
||||
return pkg
|
||||
if pkg is None:
|
||||
# 包已上溯到空,直接用 module
|
||||
return module
|
||||
# 拼接 pkg + "." + module
|
||||
pkg_len2: t.CSizeT = string.strlen(pkg)
|
||||
mod_len: t.CSizeT = string.strlen(module)
|
||||
buf: str = pool.alloc(pkg_len2 + 1 + mod_len + 1)
|
||||
if buf is None:
|
||||
return module
|
||||
string.strcpy(buf, pkg)
|
||||
buf[pkg_len2] = '.'
|
||||
string.strcpy(buf + pkg_len2 + 1, module)
|
||||
return buf
|
||||
current_package: str,
|
||||
level: t.CInt,
|
||||
module: str) -> str:
|
||||
"""解析相对导入为完整模块名(委托到 gen._resolve_relative_module)"""
|
||||
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._resolve_relative_module(pool, current_package, level, module)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -441,56 +221,27 @@ def _resolve_relative_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
# "ast.vp" → None(顶级文件)
|
||||
# ============================================================
|
||||
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr,
|
||||
rel_path: str) -> str:
|
||||
"""从相对路径计算包名(目录部分,分隔符替换为 .)"""
|
||||
if rel_path is None:
|
||||
return None
|
||||
rlen: t.CSizeT = string.strlen(rel_path)
|
||||
# 找最后一个 / 或 \
|
||||
last_sep: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < rlen:
|
||||
ch: t.CChar = rel_path[i]
|
||||
if ch == '/' or ch == '\\':
|
||||
last_sep = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无目录分隔符 → 顶级文件,无包
|
||||
return None
|
||||
# 复制目录部分,将 / 和 \ 替换为 .
|
||||
dir_len: t.CSizeT = last_sep
|
||||
buf: str = pool.alloc(dir_len + 1)
|
||||
if buf is None:
|
||||
return None
|
||||
j: t.CSizeT = 0
|
||||
while j < dir_len:
|
||||
ch2: t.CChar = rel_path[j]
|
||||
if ch2 == '/' or ch2 == '\\':
|
||||
buf[j] = '.'
|
||||
else:
|
||||
buf[j] = ch2
|
||||
j += 1
|
||||
buf[dir_len] = '\0'
|
||||
return buf
|
||||
rel_path: str) -> str:
|
||||
"""从相对路径计算包名(目录部分,分隔符替换为 .,委托到 gen.compute_package_from_relpath)"""
|
||||
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.compute_package_from_relpath(pool, rel_path)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局当前文件名(镜像 HandlesType._g_current_file)
|
||||
# set_current_file - 设置当前编译的文件名
|
||||
#
|
||||
# HandlesImports 因循环依赖(HandlesType import 了本模块)不能
|
||||
# import HandlesType,无法读取其 _g_current_file。因此由
|
||||
# BuildPipeline/Phase1 在调用 HandlesType.set_current_file 时
|
||||
# 同步调用本模块的 set_current_file,供导入时 SHA1 检查报错使用。
|
||||
# 与 HandlesType.set_current_file 同步调用,写入 gen.CurrentFile
|
||||
# (委托到 gen.set_current_file)。
|
||||
# ============================================================
|
||||
_g_current_file: str = None
|
||||
|
||||
|
||||
def set_current_file(file_path: str) -> None:
|
||||
"""设置当前正在编译的文件名(与 HandlesType.set_current_file 同步调用)"""
|
||||
global _g_current_file
|
||||
_g_current_file = file_path
|
||||
"""设置当前正在编译的文件名(与 HandlesType.set_current_file 同步调用,委托到 gen.set_current_file)"""
|
||||
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:
|
||||
g.set_current_file(file_path)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -503,38 +254,26 @@ def set_current_file(file_path: str) -> None:
|
||||
# ImportError: <msg>
|
||||
# ============================================================
|
||||
def _report_import_error(node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
"""以 Python 风格报错并退出(本地实现,避免循环依赖)"""
|
||||
stdio.printf("Traceback (most recent call last):\n")
|
||||
lineno: int = 0
|
||||
if node is not None:
|
||||
lineno = node.lineno
|
||||
file_name: str = _g_current_file
|
||||
if file_name is None:
|
||||
file_name = "<unknown>"
|
||||
stdio.printf(' File "%s", line %d\n', file_name, lineno)
|
||||
# 显示行内内容(读源文件第 lineno 行的实际代码,便于快速定位)
|
||||
if lineno > 0 and file_name is not None:
|
||||
f_err: fileio.File | t.CPtr = fileio.File(file_name, fileio.MODE.R)
|
||||
if not f_err.closed:
|
||||
line_buf_err: bytes = stdlib.malloc(512)
|
||||
if line_buf_err is not None:
|
||||
cur_ln: int = 0
|
||||
while cur_ln < lineno:
|
||||
r_err: LONG = f_err.readline(line_buf_err, 511)
|
||||
if r_err <= 0:
|
||||
break
|
||||
cur_ln += 1
|
||||
if cur_ln == lineno:
|
||||
ll_err: t.CSizeT = string.strlen(line_buf_err)
|
||||
while ll_err > 0 and (line_buf_err[ll_err - 1] == '\n' or line_buf_err[ll_err - 1] == '\r'):
|
||||
ll_err -= 1
|
||||
line_buf_err[ll_err] = '\0'
|
||||
stdio.printf(" %s\n", line_buf_err)
|
||||
break
|
||||
stdlib.free(line_buf_err)
|
||||
f_err.close()
|
||||
stdio.printf("ImportError: %s\n", msg)
|
||||
sys.exit(1)
|
||||
"""以 Python 风格报错并退出(本地实现,避免循环依赖,委托到 gen._report_import_error)"""
|
||||
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:
|
||||
g._report_import_error(node, msg)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_local_module_file - 当前文件同目录存在 {mod_name}.vp/.py
|
||||
#
|
||||
# 多文件项目(如 Test/G4/App 的 caller1.vp import g4node)的兄弟模块
|
||||
# 不在 includes 扫描存储器中(SHA1 在项目源文件列表),检查应豁免。
|
||||
# ============================================================
|
||||
def _is_local_module_file(mod_name: str) -> int:
|
||||
"""当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块(委托到 gen._is_local_module_file)"""
|
||||
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._is_local_module_file(mod_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -548,56 +287,8 @@ def _report_import_error(node: ast.AST | t.CPtr, msg: str) -> None:
|
||||
#
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查。
|
||||
# ============================================================
|
||||
def _is_local_module_file(mod_name: str) -> int:
|
||||
"""当前文件同目录存在 {mod_name}.vp/.py → 项目内兄弟模块
|
||||
|
||||
多文件项目(如 Test/G4/App 的 caller1.vp import g4node)的兄弟模块
|
||||
不在 includes 扫描存储器中(SHA1 在项目源文件列表),检查应豁免。
|
||||
"""
|
||||
cur: str = _g_current_file
|
||||
if cur is None or mod_name is None:
|
||||
return 0
|
||||
cur_len: t.CSizeT = string.strlen(cur)
|
||||
if cur_len == 0:
|
||||
return 0
|
||||
sep_pos: t.CSizeT = cur_len
|
||||
while sep_pos > 0:
|
||||
sep_pos -= 1
|
||||
ch: t.CChar = cur[sep_pos]
|
||||
if ch == '/' or ch == '\\':
|
||||
sep_pos += 1
|
||||
break
|
||||
mod_len: t.CSizeT = string.strlen(mod_name)
|
||||
path_len: t.CSizeT = sep_pos + mod_len + 5
|
||||
path_buf: bytes = stdlib.malloc(path_len + 1)
|
||||
if path_buf is None:
|
||||
return 0
|
||||
# .vp 文件
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".vp")
|
||||
fex: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex.closed:
|
||||
fex.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
# .py 文件(Python 模块可能无 .vp)
|
||||
string.strncpy(path_buf, cur, sep_pos)
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".py")
|
||||
fex2: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex2.closed:
|
||||
fex2.close()
|
||||
stdlib.free(path_buf)
|
||||
return 1
|
||||
stdlib.free(path_buf)
|
||||
return 0
|
||||
|
||||
|
||||
def _check_import_sha1(node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出
|
||||
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出(委托到 gen._check_import_sha1)
|
||||
|
||||
Args:
|
||||
node: Import/ImportFrom AST 节点(提供行号)
|
||||
@@ -606,33 +297,18 @@ def _check_import_sha1(node: ast.AST | t.CPtr, mod_name: str) -> int:
|
||||
Returns:
|
||||
1=检查通过;模块未注册时直接报错退出(不会返回 0)
|
||||
"""
|
||||
if mod_name is None:
|
||||
return 1
|
||||
# t/c 是内部库,不参与 includes 扫描,豁免检查
|
||||
if string.strcmp(mod_name, "t") == 0 or string.strcmp(mod_name, "c") == 0:
|
||||
return 1
|
||||
mod_sha1: str = StubMerger.LookupSha1ByModName(mod_name)
|
||||
if mod_sha1 is None:
|
||||
# App 兄弟模块豁免:当前文件同目录存在 {mod_name}.vp/.py
|
||||
# (如 Test/G4/App/caller1.vp import g4node——同项目源文件,
|
||||
# SHA1 在项目文件列表而非 includes 扫描存储器,不应报错)
|
||||
if _is_local_module_file(mod_name) != 0:
|
||||
return 1
|
||||
err_buf: t.CChar | t.CPtr = stdlib.malloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256,
|
||||
"模块 '%s' 未注册 SHA1(includes 扫描未找到该模块,请检查 project.json 的 includes 路径配置)",
|
||||
mod_name)
|
||||
_report_import_error(node, err_buf)
|
||||
else:
|
||||
_report_import_error(node, "导入模块 SHA1 未注册(includes 扫描未找到该模块)")
|
||||
return 1
|
||||
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._check_import_sha1(node, mod_name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ImportsHandle - 导入语句处理器(Mixin 继承模式)
|
||||
#
|
||||
# 方法版本:直接更新 trans._imported_modules / trans._from_imports
|
||||
# (内部调用的模块级工具函数经上方委托函数路由到 gen 方法)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ImportsHandle(HandlesBase.Mixin):
|
||||
|
||||
@@ -27,9 +27,29 @@ import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
#
|
||||
# trans 单参模式:所有共享状态从 trans 获取,无需 11 个参数
|
||||
# 注意: str = bytes = t.CChar | t.CPtr = i8*
|
||||
#
|
||||
# P6-E 对象化重构:全部函数已迁移为 lib.core.Gen.TranslatorGenMixin
|
||||
# 的方法,本模块保留同名模块级函数作为"一行委托"(同 P2-P5 模式):
|
||||
# 延迟 import Gen 取全局单例,再调用 gen 的对应方法。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6-E 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# TranslatorGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数
|
||||
#
|
||||
@@ -39,23 +59,11 @@ import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
# ============================================================
|
||||
def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)"""
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
if trans is None or trans.ModuleSha1 is None:
|
||||
return 0
|
||||
|
||||
# 检查返回类型是否有 CExport 或 State 标记
|
||||
has_export: int = 0
|
||||
has_state: int = 0
|
||||
if fd.returns is not None:
|
||||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||||
|
||||
if has_export != 0 or has_state != 0:
|
||||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||||
|
||||
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)(委托到 gen._register_cexport_from_funcdef)"""
|
||||
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._register_cexport_from_funcdef(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -67,7 +75,7 @@ def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def translate_children(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""遍历 tree.children 并翻译每个子节点
|
||||
"""遍历 tree.children 并翻译每个子节点(委托到 gen.translate_children)
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
@@ -76,64 +84,11 @@ def translate_children(trans: HT.Translator | t.CPtr,
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
added_total: int = 0
|
||||
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None: continue
|
||||
kd: int = child.kind()
|
||||
|
||||
# _declare_only == 0 时,_translate_module_level 已预处理导入语句,
|
||||
# 此处跳过避免重复处理(from_imports 条目重复)
|
||||
if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom):
|
||||
continue
|
||||
if kd == ast.ASTKind.Import:
|
||||
trans.ImportsH.HandleImport(child)
|
||||
elif kd == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(child)
|
||||
trans.ImportsH.HandleImportFromNames(child)
|
||||
elif kd == ast.ASTKind.FunctionDef:
|
||||
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
|
||||
# Phase 1b 全量翻译:正常翻译函数体
|
||||
if trans._declare_only == 0:
|
||||
added: int = HandlesFunctions.translate_function_def(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 1:
|
||||
_register_cexport_from_funcdef(trans, child)
|
||||
# 预解析函数签名类型,触发泛型类特化(如 numpy 的 _empty_like
|
||||
# 签名 ndarray[t.CDouble] → 特化结构体注册)。
|
||||
# 1a 阶段在 mark1 之前,特化结构体的 Ty/Fields 分配在 mark1 前,
|
||||
# 不被 1b 的 mark/reset 回收 → 避免 Phase2 翻译 App 文件时 UAF
|
||||
# (Phase1 1b 才触发特化时,结构体 Ty/Fields 在 pool 被 reset 覆写)。
|
||||
# 仅触发特化,不验证结果(1b 全量翻译时仍会重新解析)。
|
||||
_prescan_funcdef_signatures(trans, child)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
# ClassDef 在模块级直接处理(不需要 builder)
|
||||
# _declare_only=2(import扫描模式)时跳过,只处理 import 依赖
|
||||
if trans._declare_only != 2:
|
||||
HandlesClassDef.translate_class_def(trans, child)
|
||||
elif trans._declare_only == 0 and trans._cur_builder is not None:
|
||||
# 有 builder → 委托 HandlesBody 分派
|
||||
added = HandlesBody.translate_stmt(trans, child)
|
||||
added_total += added
|
||||
elif kd == ast.ASTKind.AnnAssign and trans._declare_only != 2:
|
||||
# 模块级 AnnAssign
|
||||
# _declare_only=2(import扫描模式)时跳过
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine(在 handle_module_level_var 内部判断)
|
||||
# _declare_only=0(全量翻译)时处理所有模块级 AnnAssign
|
||||
added = handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 0 and kd == ast.ASTKind.Assign:
|
||||
# 无 builder 的模块级 Assign → 创建全局变量(仅全量翻译模式)
|
||||
added = handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
|
||||
return added_total
|
||||
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.translate_children(trans, tree)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -146,26 +101,11 @@ def translate_children(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def _prescan_funcdef_signatures(trans: HT.Translator | t.CPtr,
|
||||
fd: ast.FunctionDef | t.CPtr) -> None:
|
||||
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化"""
|
||||
if trans is None or fd is None:
|
||||
return
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is None:
|
||||
return
|
||||
imp: str = trans._imported_modules
|
||||
fi: str = trans._from_imports
|
||||
if fd.returns is not None:
|
||||
HandlesType.resolve_annotation_type(pool, fd.returns, imp, fi, trans)
|
||||
if fd.args is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd.args)
|
||||
if ags.args is not None:
|
||||
al: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = al.__len__()
|
||||
ai: t.CSizeT
|
||||
for ai in range(an):
|
||||
ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(al.get(ai))
|
||||
if ag is not None and ag.annotation is not None:
|
||||
HandlesType.resolve_annotation_type(pool, ag.annotation, imp, fi, trans)
|
||||
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化(委托到 gen._prescan_funcdef_signatures)"""
|
||||
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:
|
||||
g._prescan_funcdef_signatures(trans, fd)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -177,81 +117,12 @@ def _prescan_funcdef_signatures(trans: HT.Translator | t.CPtr,
|
||||
def _build_array_initializer_text(pool: memhub.MemBuddy | t.CPtr,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr,
|
||||
list_node: ast.List | t.CPtr) -> str:
|
||||
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败"""
|
||||
if var_ty is None or list_node is None:
|
||||
return None
|
||||
|
||||
# 重新进行类型转换,确保 TPV 编译器正确识别 ast.List 类型
|
||||
# (避免 init_list_node 初始值为 None 时类型推断退化为 t.CPtr)
|
||||
ln: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if ln is None:
|
||||
return None
|
||||
|
||||
# 从 var_ty 提取数组元素类型和数量
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
arr_count: t.CInt = 0
|
||||
match var_ty:
|
||||
case llvmlite.LLVMType.Array(et, cnt):
|
||||
elem_ty = et
|
||||
arr_count = cnt
|
||||
|
||||
if elem_ty is None or arr_count <= 0:
|
||||
return None
|
||||
|
||||
# 确定元素类型的 IR 表示
|
||||
elem_ir_ty: str = "i8"
|
||||
match elem_ty:
|
||||
case llvmlite.LLVMType.Int(bits):
|
||||
if bits == 8:
|
||||
elem_ir_ty = "i8"
|
||||
elif bits == 16:
|
||||
elem_ir_ty = "i16"
|
||||
elif bits == 32:
|
||||
elem_ir_ty = "i32"
|
||||
elif bits == 64:
|
||||
elem_ir_ty = "i64"
|
||||
|
||||
# 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别)
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = ln.elts
|
||||
if elts is None:
|
||||
return None
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符
|
||||
buf_size: t.CSizeT = 64 + elts_count * 32
|
||||
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
|
||||
if buf is None:
|
||||
return None
|
||||
|
||||
# 写入前缀: "["(类型前缀由 _print_global 输出,初始化器只需元素列表)
|
||||
written: t.CInt = viperlib.snprintf(buf, buf_size, "[")
|
||||
pos: t.CSizeT = t.CSizeT(written)
|
||||
|
||||
# 逐个元素写入
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
# 直接从 Constant 节点提取 int_val(避免 extract_cdefine_int_value 的 t.CInt 截断)
|
||||
elem_val: t.CInt64T = 0
|
||||
if elem_node is not None:
|
||||
ek: int = elem_node.kind()
|
||||
if ek == ast.ASTKind.Constant:
|
||||
ec: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(elem_node)
|
||||
if ec is not None and ec.const_kind == ast.CONST_INT:
|
||||
elem_val = ec.int_val
|
||||
elif ek == ast.ASTKind.UnaryOp:
|
||||
# 负数: UnaryOp(USub, Constant)
|
||||
elem_val = HandlesAnnAssign.extract_cdefine_int_value(elem_node)
|
||||
if i > 0:
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
|
||||
pos += t.CSizeT(written)
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, "%s %lld", elem_ir_ty, elem_val)
|
||||
pos += t.CSizeT(written)
|
||||
i += 1
|
||||
|
||||
# 写入后缀 "]"
|
||||
viperlib.snprintf(buf + pos, buf_size - pos, "]")
|
||||
return buf
|
||||
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败(委托到 gen._build_array_initializer_text)"""
|
||||
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._build_array_initializer_text(pool, var_ty, list_node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -265,31 +136,12 @@ def _build_string_ptr_initializer(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
var_name: str,
|
||||
str_val: str) -> str:
|
||||
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败"""
|
||||
if str_val is None or var_name is None:
|
||||
return None
|
||||
|
||||
# 构造内部字符串常量名称: .str.{var_name}
|
||||
str_name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if str_name_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name)
|
||||
|
||||
# 调用 llvmlite.create_global_string 创建字符串常量全局
|
||||
str_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_string(
|
||||
pool, mod, str_name_buf, str_val)
|
||||
if str_gv is None:
|
||||
return None
|
||||
|
||||
# 生成 GEP 初始化器文本
|
||||
str_len: t.CSizeT = string.strlen(str_val)
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if init_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(init_buf, 128,
|
||||
"getelementptr inbounds ([%d x i8], [%d x i8]* @%s, i32 0, i32 0)",
|
||||
str_len + 1, str_len + 1, str_name_buf)
|
||||
return init_buf
|
||||
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败(委托到 gen._build_string_ptr_initializer)"""
|
||||
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._build_string_ptr_initializer(pool, mod, var_name, str_val)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -301,158 +153,11 @@ def _build_string_ptr_initializer(pool: memhub.MemBuddy | t.CPtr,
|
||||
# ============================================================
|
||||
def handle_module_level_var(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理模块级变量声明,创建全局变量"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
# CDefine 注解: 编译期常量,不创建全局变量
|
||||
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_cd: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_cd is not None and aa_cd.target is not None:
|
||||
if aa_cd.target.kind() == ast.ASTKind.Name:
|
||||
nm_cd: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa_cd.target)
|
||||
if nm_cd.id is not None:
|
||||
if HandlesAnnAssign.is_cdefine_annotation(aa_cd.annotation) != 0:
|
||||
# 浮点/整数自动识别注册(浮点 CDefine 如 vipermath U_M_PI)
|
||||
HandlesAnnAssign._register_cdefine_from_value(
|
||||
pool, nm_cd.id, aa_cd.value)
|
||||
return 0
|
||||
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量
|
||||
# CDefine 已在上面处理并返回,到这里说明不是 CDefine,直接跳过
|
||||
if trans._declare_only == 1:
|
||||
return 0
|
||||
|
||||
var_name: str = None
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
init_val: t.CInt64T = 0
|
||||
init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str
|
||||
init_str_val: str = None
|
||||
init_list_node: ast.List | t.CPtr = None
|
||||
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None or aa.target is None:
|
||||
return 0
|
||||
if aa.target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
var_name = nm.id
|
||||
# 解析类型
|
||||
if aa.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||||
if resolved is not None:
|
||||
var_ty = resolved
|
||||
# 解析初始值(支持整数、列表字面量、字符串字面量)
|
||||
if aa.value is not None:
|
||||
val_kind: int = aa.value.kind()
|
||||
if val_kind == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(aa.value)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
init_val = cn.int_val
|
||||
init_kind = 1
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn.str_val
|
||||
init_kind = 3
|
||||
elif val_kind == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(aa.value)
|
||||
init_kind = 2
|
||||
elif k == ast.ASTKind.Assign:
|
||||
asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
|
||||
if asgn is None or asgn.targets is None:
|
||||
return 0
|
||||
targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets
|
||||
if targets.__len__() < 1:
|
||||
return 0
|
||||
t0: ast.AST | t.CPtr = targets.get(0)
|
||||
if t0 is None or t0.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0)
|
||||
var_name = nm2.id
|
||||
if asgn.value is not None:
|
||||
val_kind2: int = asgn.value.kind()
|
||||
if val_kind2 == ast.ASTKind.Constant:
|
||||
cn2: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(asgn.value)
|
||||
if cn2.const_kind == ast.CONST_INT:
|
||||
init_val = cn2.int_val
|
||||
init_kind = 1
|
||||
elif cn2.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn2.str_val
|
||||
init_kind = 3
|
||||
elif val_kind2 == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(asgn.value)
|
||||
init_kind = 2
|
||||
|
||||
if var_name is None:
|
||||
return 0
|
||||
|
||||
# 检查是否已注册
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
trans.SymTab, var_name)
|
||||
if existing is not None:
|
||||
return 0
|
||||
|
||||
# 创建全局变量 @var_name
|
||||
# 先确保 var_ty 中的跨模块结构体类型在模块中有 opaque 声明
|
||||
# 否则 @var_name = global %"sha1.ClassName"* zeroinitializer 会报
|
||||
# "use of undefined type named 'sha1.ClassName'" 错误
|
||||
# (如 _mbuddy: memhub.MemManager | t.CPtr → Ptr(Struct("aeb3...MemManager")))
|
||||
llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, var_name, var_ty)
|
||||
if gv is None:
|
||||
return 0
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
# 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值)
|
||||
gv.Linkage = None
|
||||
if init_kind == 1:
|
||||
# 整数初始值
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(48)
|
||||
if init_buf is not None:
|
||||
viperlib.snprintf(init_buf, 48, "%lld", init_val)
|
||||
gv.Initializer = init_buf
|
||||
elif init_kind == 2:
|
||||
# 列表字面量 → 数组初始化器 [N x elem_ty] [elem_ty val0, ...]
|
||||
arr_init: str = _build_array_initializer_text(pool, var_ty, init_list_node)
|
||||
if arr_init is not None:
|
||||
gv.Initializer = arr_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
elif init_kind == 3:
|
||||
# 字符串字面量 → 创建字符串常量全局 + GEP 引用
|
||||
str_init: str = _build_string_ptr_initializer(pool, mod, var_name, init_str_val)
|
||||
if str_init is not None:
|
||||
gv.Initializer = str_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
else:
|
||||
# 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer,
|
||||
# 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type"
|
||||
gv.Initializer = "zeroinitializer"
|
||||
|
||||
# 创建 Value 引用(@var_name, 类型为 var_ty*)
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
ref_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if ref_name is not None:
|
||||
viperlib.snprintf(ref_name, 64, "@%s", var_name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, var_ptr_ty, ref_name)
|
||||
|
||||
# 注册到模块作用域
|
||||
if HandlesVar.define_module_var(trans.SymTab, var_name, gv_ref) == 0:
|
||||
# 设置 AnnotClassName(联合类型如 Logger|t.CPtr 简化为 Ptr(i8) 时,
|
||||
# 属性访问需要通过 AnnotClassName 回退到类名查找结构体)
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_ml: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_ml is not None and aa_ml.annotation is not None:
|
||||
cls_nm_ml: str = HandlesType.extract_class_name_from_annotation(
|
||||
aa_ml.annotation, trans._imported_modules)
|
||||
if cls_nm_ml is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
trans.SymTab, var_name, cls_nm_ml)
|
||||
return 1
|
||||
"""处理模块级变量声明,创建全局变量(委托到 gen.handle_module_level_var)"""
|
||||
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.handle_module_level_var(trans, node)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -466,7 +171,7 @@ def handle_module_level_var(trans: HT.Translator | t.CPtr,
|
||||
def create_wrapper_main(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr,
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""创建包装 main 函数并翻译所有顶层语句
|
||||
"""创建包装 main 函数并翻译所有顶层语句(委托到 gen.create_wrapper_main)
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
@@ -476,57 +181,8 @@ def create_wrapper_main(trans: HT.Translator | t.CPtr,
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
main_func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||||
pool, mod, "main", i32_ty)
|
||||
if main_func is None:
|
||||
VLogger.error("CreateFunction main returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, main_func, "entry")
|
||||
if entry_blk is None:
|
||||
VLogger.error("CreateBlock returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, main_func)
|
||||
if builder is None:
|
||||
VLogger.error("NewBuilder returned NULL", "TR")
|
||||
return 0
|
||||
llvmlite.position_at_end(builder, entry_blk)
|
||||
|
||||
# 设置当前翻译上下文(供 Handle 通过 self.Trans._cur_builder 访问)
|
||||
trans._cur_func = main_func
|
||||
trans._cur_builder = builder
|
||||
|
||||
# 预处理模块级变量:为 AnnAssign/Assign 创建 LLVM 全局变量
|
||||
# 必须在 pre_scan_allocas 之前执行,否则 PreScan 会创建局部 alloca,
|
||||
# 导致其他函数通过 SSA 编号引用 wrapper main 的局部变量(无效 IR)
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is not None:
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign:
|
||||
handle_module_level_var(trans, child)
|
||||
|
||||
# 预扫描顶层语句:为函数内 AnnAssign 提前创建 alloca
|
||||
# (模块级变量已在上面注册到模块作用域,PreScan 的 lookup_current 会跳过它们)
|
||||
if ch is not None:
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
HandlesBody.pre_scan_allocas(trans, child)
|
||||
|
||||
# 翻译子节点
|
||||
added_total: int = translate_children(trans, tree)
|
||||
|
||||
# 返回 0
|
||||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
llvmlite.build_ret(builder, zero_val)
|
||||
|
||||
return added_total
|
||||
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.create_wrapper_main(trans, tree, i32_ty)
|
||||
return 0
|
||||
@@ -15,7 +15,11 @@ import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesMatch - match 语句处理(Mixin 继承模式)
|
||||
# HandlesMatch - match 语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# NewMatchHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (MatchHandle 类保留:trans.MatchH 的类型,由 HandlesTranslator.
|
||||
# _init_state 经 NewMatchHandle 委托创建)。
|
||||
#
|
||||
# 逻辑移植自 TPC 的 HandlesMatch.py,用 Viper 语法重写。
|
||||
# 两条路径:
|
||||
@@ -39,6 +43,22 @@ MAX_MATCH_CASES: t.CDefine = 32
|
||||
SCOPE_MATCH: t.CDefine = 6
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class MatchHandle(HandlesBase.Mixin):
|
||||
"""match 语句处理器:REnum + 非 REnum 两条路径"""
|
||||
@@ -799,13 +819,13 @@ class MatchHandle(HandlesBase.Mixin):
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewMatchHandle - 工厂函数
|
||||
# NewMatchHandle - 工厂函数(委托到 gen.NewMatchHandle)
|
||||
# ============================================================
|
||||
def NewMatchHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> MatchHandle | t.CPtr:
|
||||
h: MatchHandle | t.CPtr = pool.alloc(MatchHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, MatchHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
"""创建 MatchHandle 实例(委托到 gen.NewMatchHandle)"""
|
||||
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.NewMatchHandle(pool, trans)
|
||||
return None
|
||||
@@ -11,7 +11,12 @@ import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)
|
||||
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)(P6 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
|
||||
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
|
||||
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
|
||||
# 对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针)
|
||||
# 指针指向父函数中变量的 alloca(原始存储位置),父与子共享同一存储,
|
||||
@@ -33,6 +38,22 @@ import lib.core.Handles.HandlesVar as HandlesVar
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_void_type — 判断是否为 Void 类型(非法用作变量类型)
|
||||
#
|
||||
@@ -41,35 +62,24 @@ import lib.core.Handles.HandlesVar as HandlesVar
|
||||
# 回退为 i32,避免生成 "bitcast ... to void*" / "load void, void*" 的非法 IR。
|
||||
# ============================================================
|
||||
def _is_void_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""判断是否为 Void 类型,是则返回 1,否则 0"""
|
||||
if ty is None:
|
||||
return 0
|
||||
match ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
return 1
|
||||
case _:
|
||||
return 0
|
||||
"""判断是否为 Void 类型,是则返回 1,否则 0(委托到 gen._is_void_type)"""
|
||||
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._is_void_type(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取或创建 _env_ptr 变量(存储 env 参数的 alloca)
|
||||
# ============================================================
|
||||
def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)"""
|
||||
env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, "_env_ptr")
|
||||
if env_var is not None:
|
||||
return env_var
|
||||
# 创建 alloca 存储 env
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca)
|
||||
return alloca
|
||||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)(委托到 gen.get_env_ptr_var)"""
|
||||
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.get_env_ptr_var(trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -79,39 +89,15 @@ def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
# ============================================================
|
||||
def _load_raw_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)
|
||||
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)(委托到 gen._load_raw_var_ptr)
|
||||
|
||||
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
|
||||
"""
|
||||
idx: int = HT.get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
|
||||
|
||||
# 1. 加载 env_ptr
|
||||
env_alloca: llvmlite.Value | t.CPtr = get_env_ptr_var(trans)
|
||||
if env_alloca is None:
|
||||
return None
|
||||
env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca)
|
||||
if env_ptr is None:
|
||||
return None
|
||||
|
||||
# 2. GEP to offset (idx * 8) — env 存储指针数组,每槽 8 字节
|
||||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 8)
|
||||
addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
# 3. Bitcast to i8** and load the raw pointer
|
||||
ptr_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i8_ptr_ptr_ty)
|
||||
if ptr_addr is None:
|
||||
return None
|
||||
return llvmlite.build_load(builder, i8_ptr_ty, ptr_addr)
|
||||
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._load_raw_var_ptr(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -121,29 +107,15 @@ def _load_raw_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def load_nonlocal_var(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量值
|
||||
"""从闭包 env 加载 nonlocal 变量值(委托到 gen.load_nonlocal_var)
|
||||
|
||||
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
|
||||
"""
|
||||
raw_ptr: llvmlite.Value | t.CPtr = _load_raw_var_ptr(trans, name)
|
||||
if raw_ptr is None:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
|
||||
# 获取变量类型(从注册时存储的类型信息)
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name)
|
||||
if var_ty is None or _is_void_type(var_ty) != 0:
|
||||
# Void 类型视为无效(会导致 "load void, void*" 非法 IR),回退为 i32
|
||||
var_ty = llvmlite.Int32(pool)
|
||||
|
||||
# bitcast raw i8* to var_ty*
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
|
||||
if var_ptr is None:
|
||||
return None
|
||||
return llvmlite.build_load(builder, var_ty, var_ptr)
|
||||
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.load_nonlocal_var(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -153,23 +125,12 @@ def load_nonlocal_var(trans: HT.Translator | t.CPtr,
|
||||
# ============================================================
|
||||
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作
|
||||
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作(委托到 gen.get_nonlocal_var_ptr)
|
||||
|
||||
返回的指针指向父函数的 alloca,store 操作对父函数可见。
|
||||
"""
|
||||
raw_ptr: llvmlite.Value | t.CPtr = _load_raw_var_ptr(trans, name)
|
||||
if raw_ptr is None:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
|
||||
# 获取变量类型
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = HT.get_nonlocal_type(trans, name)
|
||||
if var_ty is None or _is_void_type(var_ty) != 0:
|
||||
# Void 类型视为无效(会导致 "bitcast ... to void*" 非法 IR),回退为 i32
|
||||
var_ty = llvmlite.Int32(pool)
|
||||
|
||||
# bitcast raw i8* to var_ty*
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
return llvmlite.build_bitcast(builder, raw_ptr, var_ptr_ty)
|
||||
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.get_nonlocal_var_ptr(trans, name)
|
||||
return None
|
||||
@@ -11,10 +11,30 @@ import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesReturn - Return 语句处理(Mixin 继承模式)
|
||||
# HandlesReturn - Return 语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# NewReturnHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (ReturnHandle 类保留:trans.ReturnH 的类型,由 HandlesTranslator.
|
||||
# _init_state 经 NewReturnHandle 委托创建)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class ReturnHandle(HandlesBase.Mixin):
|
||||
"""Return 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
@@ -139,13 +159,13 @@ class ReturnHandle(HandlesBase.Mixin):
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewReturnHandle - 工厂函数
|
||||
# NewReturnHandle - 工厂函数(委托到 gen.NewReturnHandle)
|
||||
# ============================================================
|
||||
def NewReturnHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ReturnHandle | t.CPtr:
|
||||
h: ReturnHandle | t.CPtr = pool.alloc(ReturnHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ReturnHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
"""创建 ReturnHandle 实例(委托到 gen.NewReturnHandle)"""
|
||||
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.NewReturnHandle(pool, trans)
|
||||
return None
|
||||
@@ -39,6 +39,10 @@ import lib.Projectrans.Config as Config
|
||||
# HandlesExpr - 表达式翻译
|
||||
# HandlesFunctions - 函数定义处理
|
||||
# 注意:str = bytes = t.CChar | t.CPtr = i8*
|
||||
#
|
||||
# P6-E 对象化重构:模块级 global/nonlocal 名称管理函数已迁移为
|
||||
# lib.core.Gen.TranslatorGenMixin 的方法,本模块保留同名模块级
|
||||
# 函数作为"一行委托"(同 P2-P5 模式)。Translator 类保留在本模块。
|
||||
# ============================================================
|
||||
|
||||
# 常量
|
||||
@@ -47,6 +51,22 @@ MAX_FUNCS: t.CDefine = 256
|
||||
MAX_GLOBAL_NAMES: t.CDefine = 32
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6-E 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# TranslatorGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class Translator:
|
||||
"""翻译器:管理编译状态,委托 Handles 模块执行翻译"""
|
||||
@@ -397,154 +417,78 @@ class Translator:
|
||||
|
||||
|
||||
# ============================================================
|
||||
# global/nonlocal 名称管理(模块级辅助函数)
|
||||
# global/nonlocal 名称管理(模块级辅助函数,委托到 gen 方法)
|
||||
# ============================================================
|
||||
def add_global_name(trans: HT.Translator | t.CPtr, name: str):
|
||||
"""添加一个 global 变量名"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._global_names is None:
|
||||
return
|
||||
# 检查是否已存在
|
||||
if is_global_name(trans, name) != 0:
|
||||
return
|
||||
if trans._global_name_count >= MAX_GLOBAL_NAMES:
|
||||
pool_err: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
err_buf: str = None
|
||||
if pool_err is not None:
|
||||
err_buf = pool_err.alloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256, "global 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 global 声明或增大 MAX_GLOBAL_NAMES", MAX_GLOBAL_NAMES)
|
||||
VLogger.error(err_buf, "ScopeDecl")
|
||||
else:
|
||||
VLogger.error("global 变量数量超过上限,请减少 global 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl")
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + trans._global_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
trans._global_name_count += 1
|
||||
"""添加一个 global 变量名(委托到 gen.add_global_name)"""
|
||||
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:
|
||||
g.add_global_name(trans, name)
|
||||
|
||||
|
||||
def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 global 集合中"""
|
||||
if trans is None or name is None or trans._global_names is None:
|
||||
return 0
|
||||
for i in range(trans._global_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
"""检查 name 是否在当前函数的 global 集合中(委托到 gen.is_global_name)"""
|
||||
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.is_global_name(trans, name)
|
||||
return 0
|
||||
|
||||
|
||||
def add_nonlocal_name(trans: HT.Translator | t.CPtr, name: str,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = None):
|
||||
"""添加一个 nonlocal 变量名
|
||||
"""添加一个 nonlocal 变量名(委托到 gen.add_nonlocal_name)
|
||||
|
||||
Args:
|
||||
name: nonlocal 变量名
|
||||
var_ty: 变量的 LLVM 类型(用于 env 指针数组方案的类型恢复,
|
||||
None 时回退为 i32)
|
||||
"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._nonlocal_names is None:
|
||||
return
|
||||
if is_nonlocal_name(trans, name) != 0:
|
||||
# 已存在:更新类型信息(可能在预扫描时类型未知,正式翻译时更新)
|
||||
# _nonlocal_types 每槽 8 字节,存 LLVMType* 指针。
|
||||
# 用 str|t.CPtr (i8**) 二级指针存取(与 _nonlocal_names 模式一致),
|
||||
# [0] 解引用只拷贝 8 字节指针,避免值拷贝 24+ 字节 LLVMType 结构体溢出。
|
||||
if var_ty is not None and trans._nonlocal_types is not None:
|
||||
idx: int = get_nonlocal_index(trans, name)
|
||||
if idx >= 0:
|
||||
ty_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + idx * 8
|
||||
ty_slot: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr)
|
||||
ty_slot[0] = var_ty
|
||||
return
|
||||
if trans._nonlocal_name_count >= MAX_GLOBAL_NAMES:
|
||||
pool_err_nl: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
err_buf_nl: str = None
|
||||
if pool_err_nl is not None:
|
||||
err_buf_nl = pool_err_nl.alloc(256)
|
||||
if err_buf_nl is not None:
|
||||
viperlib.snprintf(err_buf_nl, 256, "nonlocal 变量数量超过上限 MAX_GLOBAL_NAMES=%d,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", MAX_GLOBAL_NAMES)
|
||||
VLogger.error(err_buf_nl, "ScopeDecl")
|
||||
else:
|
||||
VLogger.error("nonlocal 变量数量超过上限,请减少 nonlocal 声明或增大 MAX_GLOBAL_NAMES", "ScopeDecl")
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + trans._nonlocal_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
# 存储类型信息(用 str|t.CPtr = i8** 二级指针,与 _nonlocal_names 一致)
|
||||
if trans._nonlocal_types is not None:
|
||||
ty_addr2: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + trans._nonlocal_name_count * 8
|
||||
ty_slot2: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr2)
|
||||
# var_ty 为 None 时存入 i32 作为默认类型
|
||||
stored_ty: llvmlite.LLVMType | t.CPtr = var_ty
|
||||
if stored_ty is None:
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
if pool is not None:
|
||||
stored_ty = llvmlite.Int32(pool)
|
||||
ty_slot2[0] = stored_ty
|
||||
trans._nonlocal_name_count += 1
|
||||
trans._closure_env_count += 1
|
||||
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:
|
||||
g.add_nonlocal_name(trans, name, var_ty)
|
||||
|
||||
|
||||
def get_nonlocal_type(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""获取 nonlocal 变量的 LLVM 类型
|
||||
"""获取 nonlocal 变量的 LLVM 类型(委托到 gen.get_nonlocal_type)
|
||||
|
||||
Returns: 找到的类型指针,找不到返回 None
|
||||
"""
|
||||
if trans is None or name is None or trans._nonlocal_types is None:
|
||||
return None
|
||||
idx: int = get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
ty_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_types) + idx * 8
|
||||
ty_slot: str | t.CPtr = (t.CVoid | t.CPtr)(ty_addr)
|
||||
return (llvmlite.LLVMType | t.CPtr)(ty_slot[0])
|
||||
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.get_nonlocal_type(trans, name)
|
||||
return None
|
||||
|
||||
|
||||
def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 nonlocal 集合中"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return 0
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
"""检查 name 是否在当前函数的 nonlocal 集合中(委托到 gen.is_nonlocal_name)"""
|
||||
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.is_nonlocal_name(trans, name)
|
||||
return 0
|
||||
|
||||
|
||||
def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return -1
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return i
|
||||
return -1
|
||||
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1(委托到 gen.get_nonlocal_index)"""
|
||||
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.get_nonlocal_index(trans, name)
|
||||
return 0
|
||||
|
||||
|
||||
def clear_scope_names(trans: HT.Translator | t.CPtr):
|
||||
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)"""
|
||||
if trans is None:
|
||||
return
|
||||
trans._global_name_count = 0
|
||||
trans._nonlocal_name_count = 0
|
||||
trans._closure_env_count = 0
|
||||
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)(委托到 gen.clear_scope_names)"""
|
||||
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:
|
||||
g.clear_scope_names(trans)
|
||||
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
+143
-177
@@ -6,7 +6,7 @@ import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesVar - 嵌套作用域符号表 + 变量管理
|
||||
# HandlesVar - 嵌套作用域符号表 + 变量管理(P6 对象化后的委托层)
|
||||
#
|
||||
# 使用 Scope 链(Parent 指针)管理嵌套作用域,
|
||||
# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。
|
||||
@@ -15,6 +15,14 @@ import string
|
||||
# SCOPE_MODULE — 模块级(根作用域)
|
||||
# SCOPE_FUNCTION — 函数级
|
||||
# SCOPE_BLOCK — 块级(if/for/while,当前未使用块作用域)
|
||||
#
|
||||
# P6 对象化重构(wiki/14-oo-refactor.md):
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.VarGenMixin 的方法(方法化迁移,
|
||||
# 无全局状态),本模块保留同名模块级函数作为"一行委托":延迟 import
|
||||
# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),
|
||||
# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# VarEntry/Scope/SymbolTable 类型与常量保留在本模块(gen 方法签名引用)。
|
||||
# ============================================================
|
||||
|
||||
# 作用域类型常量
|
||||
@@ -68,16 +76,39 @@ class SymbolTable:
|
||||
Current: Scope | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# VarGenMixin 方法,避免函数体 import 包模块与 Generator
|
||||
# 类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组"""
|
||||
size: t.CSizeT = MAX_VARS * VarEntry.__sizeof__()
|
||||
vars_ptr: VarEntry | t.CPtr = pool.alloc(size)
|
||||
if vars_ptr is not None:
|
||||
string.memset(vars_ptr, 0, size)
|
||||
return vars_ptr
|
||||
"""分配并清零变量表数组(委托到 gen.init_vars)"""
|
||||
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.init_vars(pool)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -86,16 +117,11 @@ def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
|
||||
def find_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry.Alloca
|
||||
"""在变量表中按名称查找(委托到 gen.find_var)"""
|
||||
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.find_var(vars_ptr, var_count, name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -105,16 +131,11 @@ def find_var(vars_ptr: VarEntry | t.CPtr,
|
||||
def find_var_entry(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None(委托到 gen.find_var_entry)"""
|
||||
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.find_var_entry(vars_ptr, var_count, name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -123,15 +144,11 @@ def find_var_entry(vars_ptr: VarEntry | t.CPtr,
|
||||
# ============================================================
|
||||
def lookup_var_entry(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: VarEntry | t.CPtr = find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None(委托到 gen.lookup_var_entry)"""
|
||||
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.lookup_var_entry(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -145,13 +162,11 @@ def lookup_var_entry(symtab: SymbolTable | t.CPtr,
|
||||
def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.AnnotClassName = class_name
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败(委托到 gen.set_var_annot_class_name)"""
|
||||
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.set_var_annot_class_name(symtab, name, class_name)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -164,13 +179,11 @@ def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
|
||||
# ============================================================
|
||||
def set_var_ptr_element(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.IsPtrElement = 1
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败(委托到 gen.set_var_ptr_element)"""
|
||||
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.set_var_ptr_element(symtab, name)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -181,17 +194,11 @@ def add_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表"""
|
||||
if name is None or alloca is None or vars_ptr is None:
|
||||
return 1
|
||||
if var_count >= MAX_VARS:
|
||||
return 1
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
"""添加变量到变量表(委托到 gen.add_var)"""
|
||||
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.add_var(vars_ptr, var_count, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -206,14 +213,16 @@ def add_var(vars_ptr: VarEntry | t.CPtr,
|
||||
# ============================================================
|
||||
def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值
|
||||
"""在函数入口块生成 alloca,返回 alloca 值(委托到 gen._alloca_at_entry)
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
if builder is None or ty is None:
|
||||
return None
|
||||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||||
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._alloca_at_entry(builder, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -225,16 +234,12 @@ def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca"""
|
||||
existing: llvmlite.Value | t.CPtr = find_var(vars_ptr, var_count, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if add_var(vars_ptr, var_count, name, alloca) != 0:
|
||||
return None
|
||||
return alloca
|
||||
"""查找或创建变量 alloca(委托到 gen.get_or_create_var)"""
|
||||
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.get_or_create_var(pool, builder, vars_ptr, var_count, name, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -243,41 +248,24 @@ def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
|
||||
def _create_scope(pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: Scope | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点"""
|
||||
scope: Scope | t.CPtr = pool.alloc(Scope.__sizeof__())
|
||||
if scope is None:
|
||||
return None
|
||||
string.memset(scope, 0, Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
scope.Vars = init_vars(pool)
|
||||
scope.VarCount = 0
|
||||
scope.Kind = kind
|
||||
if scope.Vars is None:
|
||||
return None
|
||||
return scope
|
||||
"""创建并初始化作用域节点(委托到 gen._create_scope)"""
|
||||
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._create_scope(pool, parent, kind)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域"""
|
||||
if pool is None:
|
||||
return None
|
||||
symtab: SymbolTable | t.CPtr = pool.alloc(SymbolTable.__sizeof__())
|
||||
if symtab is None:
|
||||
return None
|
||||
string.memset(symtab, 0, SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# 创建根作用域(模块级)
|
||||
root: Scope | t.CPtr = _create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None:
|
||||
return None
|
||||
|
||||
symtab.Root = root
|
||||
symtab.Current = root
|
||||
return symtab
|
||||
"""创建并初始化符号表,包含模块级根作用域(委托到 gen.init_symbol_table)"""
|
||||
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.init_symbol_table(pool)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -285,24 +273,23 @@ def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr:
|
||||
# ============================================================
|
||||
def enter_scope(symtab: SymbolTable | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域"""
|
||||
if symtab is None:
|
||||
return None
|
||||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||||
scope: Scope | t.CPtr = _create_scope(pool, symtab.Current, kind)
|
||||
if scope is None:
|
||||
return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
"""进入新作用域,返回新创建的作用域(委托到 gen.enter_scope)"""
|
||||
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.enter_scope(symtab, kind)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(symtab: SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域"""
|
||||
if symtab is not None and symtab.Current is not None:
|
||||
symtab.Current = symtab.Current.Parent
|
||||
"""退出当前作用域,恢复到父作用域(委托到 gen.exit_scope)"""
|
||||
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:
|
||||
g.exit_scope(symtab)
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -311,16 +298,12 @@ def exit_scope(symtab: SymbolTable | t.CPtr):
|
||||
def define_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
"""在当前作用域定义变量,返回 0 成功(委托到 gen.define_var)"""
|
||||
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.define_var(symtab, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -329,16 +312,12 @@ def define_var(symtab: SymbolTable | t.CPtr,
|
||||
def define_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
"""在模块作用域定义变量,返回 0 成功(委托到 gen.define_module_var)"""
|
||||
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.define_module_var(symtab, name, alloca)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -346,16 +325,11 @@ def define_module_var(symtab: SymbolTable | t.CPtr,
|
||||
# ============================================================
|
||||
def lookup_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: llvmlite.Value | t.CPtr = find_var(
|
||||
scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None(委托到 gen.lookup_var)"""
|
||||
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.lookup_var(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
@@ -364,13 +338,12 @@ def lookup_var(symtab: SymbolTable | t.CPtr,
|
||||
# ============================================================
|
||||
def lookup_current(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return None
|
||||
return find_var(scope.Vars, scope.VarCount, name)
|
||||
"""仅在当前作用域查找变量(委托到 gen.lookup_current)"""
|
||||
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.lookup_current(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -378,13 +351,12 @@ def lookup_current(symtab: SymbolTable | t.CPtr,
|
||||
# ============================================================
|
||||
def lookup_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return None
|
||||
return find_var(scope.Vars, scope.VarCount, name)
|
||||
"""在模块作用域查找变量(委托到 gen.lookup_module_var)"""
|
||||
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.lookup_module_var(symtab, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
@@ -395,17 +367,14 @@ def lookup_module_var(symtab: SymbolTable | t.CPtr,
|
||||
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
|
||||
# ============================================================
|
||||
def is_module_scope(symtab: SymbolTable | t.CPtr) -> int:
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root)
|
||||
"""判断当前作用域是否为模块级作用域(Current == Root,委托到 gen.is_module_scope)
|
||||
|
||||
Returns: 1=模块级作用域, 0=函数内作用域
|
||||
"""
|
||||
if symtab is None:
|
||||
return 0
|
||||
if symtab.Root is None or symtab.Current is None:
|
||||
return 0
|
||||
# 比较指针:Current 与 Root 相同则为模块级
|
||||
if t.CUInt64T(symtab.Current) == t.CUInt64T(symtab.Root):
|
||||
return 1
|
||||
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.is_module_scope(symtab)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -417,12 +386,9 @@ def get_or_create_sym(symtab: SymbolTable | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域)"""
|
||||
existing: llvmlite.Value | t.CPtr = lookup_current(symtab, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
define_var(symtab, name, alloca)
|
||||
return alloca
|
||||
"""查找或创建变量 alloca(在当前作用域,委托到 gen.get_or_create_sym)"""
|
||||
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.get_or_create_sym(symtab, pool, builder, name, ty)
|
||||
return None
|
||||
@@ -13,7 +13,11 @@ import lib.core.Handles.HandlesBody as HandlesBody
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesWhile - while 循环语句处理(Mixin 继承模式)
|
||||
# HandlesWhile - while 循环语句处理(P6 对象化后的委托层)
|
||||
#
|
||||
# NewWhileHandle 工厂已迁移为 lib.core.Gen.StmtGenMixin 的方法
|
||||
# (WhileHandle 类保留:trans.WhileH 的类型,由 HandlesTranslator.
|
||||
# _init_state 经 NewWhileHandle 委托创建)。
|
||||
#
|
||||
# 翻译 while 语句为 LLVM IR 控制流:
|
||||
# br label %cond
|
||||
@@ -28,6 +32,22 @@ import lib.core.Handles.HandlesBody as HandlesBody
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class WhileHandle(HandlesBase.Mixin):
|
||||
"""while 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
@@ -123,13 +143,13 @@ class WhileHandle(HandlesBase.Mixin):
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewWhileHandle - 工厂函数
|
||||
# NewWhileHandle - 工厂函数(委托到 gen.NewWhileHandle)
|
||||
# ============================================================
|
||||
def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr:
|
||||
h: WhileHandle | t.CPtr = pool.alloc(WhileHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, WhileHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
"""创建 WhileHandle 实例(委托到 gen.NewWhileHandle)"""
|
||||
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.NewWhileHandle(pool, trans)
|
||||
return None
|
||||
+28
@@ -21,6 +21,19 @@ import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesMatch as HandlesMatch
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesMain as HandlesMain
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
@@ -99,6 +112,21 @@ def main() -> int:
|
||||
HandlesExprCall.set_global_gen(gen)
|
||||
HandlesFunctions.set_global_gen(gen)
|
||||
HandlesClassDef.set_global_gen(gen)
|
||||
# P6: 注入语句/赋值/变量/导入/翻译驱动模块的单例
|
||||
HandlesImports.set_global_gen(gen)
|
||||
HandlesBody.set_global_gen(gen)
|
||||
HandlesIf.set_global_gen(gen)
|
||||
HandlesWhile.set_global_gen(gen)
|
||||
HandlesFor.set_global_gen(gen)
|
||||
HandlesReturn.set_global_gen(gen)
|
||||
HandlesNonlocal.set_global_gen(gen)
|
||||
HandlesMatch.set_global_gen(gen)
|
||||
HandlesEnum.set_global_gen(gen)
|
||||
HandlesAnnAssign.set_global_gen(gen)
|
||||
HandlesAugAssign.set_global_gen(gen)
|
||||
HandlesVar.set_global_gen(gen)
|
||||
HandlesTranslator.set_global_gen(gen)
|
||||
HandlesMain.set_global_gen(gen)
|
||||
|
||||
# 初始化 VLogger 并打印启动日志
|
||||
log: VLogger.Logger | t.CPtr = VLogger.get_logger()
|
||||
|
||||
Reference in new issue
Block a user