基线重置,修复了一些 bug

This commit is contained in:
TermiNexus committed 2026-09-07 14:46:02 +08:00
1 parent b02bedae9a
commit 45e78ad107
2421 files changed
+13195 -19306

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-163
View File
@@ -1,163 +0,0 @@
import t, c
from stdint import *
import ast
import memhub
import string
import llvmlite
import stdlib
import stdio
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.Stub.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
# ============================================================
# docstring 登记表容量(__doc__ 魔法属性支持)
#
# DOC_MAX: 登记条目上限(预注册阶段所有 App/includes 文件的
# 函数/类/方法 docstring,幂等查重)
# DOC_KEY_SZ: key "{module_sha1}.{symbol}" 缓冲宽度
# DOC_VAL_SZ: docstring 内容缓冲宽度
# ============================================================
DOC_MAX: t.CDefine = 512
DOC_KEY_SZ: t.CDefine = 192
DOC_VAL_SZ: t.CDefine = 4096
# ============================================================
# f-string 翻译常量(对齐 TPC HandlesExprFormat)
#
# FSTR_BUF_SIZE: 运行时栈缓冲大小(snprintf 结果缓冲)
# FSTR_SPEC_MAX: 编译期 format_spec 解析缓冲宽度
# FSTR_FMT_MAX: 编译期 C printf 格式串缓冲宽度
# ============================================================
FSTR_BUF_SIZE: t.CDefine = 1024
FSTR_SPEC_MAX: t.CDefine = 64
FSTR_FMT_MAX: t.CDefine = 64
# ============================================================
# ExprGenMixin - 表达式处理 Mixin(对象化 P3,wiki/14-oo-refactor.md)
#
# 从 HandlesExpr.vp(48 函数,无全局状态)与 HandlesExprOps.vp
# 迁移:模块级纯函数 → 类方法(self 替代,参数保留含 builder/pool)。
#
# 迁移原则(与 P2 一致,行为零变化):
# 1. 方法保留原函数签名(含 builder/pool 首参),仅函数体内
# 本模块函数调用改为 self.xxx(...)
# 2. 外部模块调用(HandlesExprCall.xxx / HandlesType.xxx 等)保留模块前缀
# 3. HandlesExpr.vp / HandlesExprOps.vp 原函数保留为"委托":本地
# 模块级单例 _g_gen(BuildPipeline/main 注入)cast 成 Generator 类型
# 4. ExprHandle 类保留在 HandlesExpr.vp(translator handler 模式)
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整)。
# ============================================================
# ============================================================
# ExprGenMixin - 表达式/常量/下标/属性访问/运算符
# ============================================================
@t.NoVTable
class ExprGenMixin(ExprGenBase.ExprGenBase):
"""表达式处理 Mixin(纯方法化迁移,无状态字段)"""
# ============================================================
# 翻译值表达式(RHS 分派)— 模块级版本
# ============================================================
def translate_value(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr = None,
func_count: int = 0,
trans: HT.Translator | t.CPtr = None,
target_ty: llvmlite.LLVMType | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译值表达式为 LLVM Value(深度守卫包装器,原逻辑见 _translate_value_impl)
target_ty: 目标类型上下文(如调用形参类型/赋值目标类型),用于单引号
单字符字面量(CONST_CHAR)在字符串目标下物化为 1 字符字符串(对齐 TPC)。
"""
if trans is not None:
if trans.TranslateDepth >= HT.TRANSLATE_MAX_DEPTH:
self.Gen.TypeGenErr.fatal_error(
node, "表达式翻译嵌套过深(疑似 AST 自引用环或翻译 bug)", "RecursionError")
trans.TranslateDepth += 1
rv: llvmlite.Value | t.CPtr = self._translate_value_impl(
builder, pool, mod, node, funcs_ptr, func_count, trans, target_ty)
if trans is not None:
trans.TranslateDepth -= 1
return rv
def _translate_value_impl(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr = None,
func_count: int = 0,
trans: HT.Translator | t.CPtr = None,
target_ty: llvmlite.LLVMType | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译值表达式为 LLVM Value"""
if node is None:
return None
k: int = node.kind()
if k == ast.ASTKind.Constant:
rv: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.translate_constant(builder, pool, mod, node, trans, target_ty)
return rv
elif k == ast.ASTKind.Name:
return self.Gen.ExprGenName.translate_name_value(builder, pool, node, trans)
elif k == ast.ASTKind.BinOp:
return self.Gen.ExprGenOps.translate_binop(pool, builder, mod, node, trans)
elif k == ast.ASTKind.Call:
return self.Gen.CallGen.translate_call(pool, builder, mod, node,
funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Compare:
return self.Gen.ExprGenOps.translate_compare(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp:
return self.Gen.ExprGenOps.translate_unaryop(builder, pool, mod, node, trans)
elif k == ast.ASTKind.BoolOp:
return self.Gen.ExprGenOps.translate_boolop(builder, pool, mod, node,
funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Subscript:
return self.Gen.ExprGenName.translate_subscript(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Attribute:
return self.Gen.ExprGenAttr.translate_attribute(builder, pool, mod, node, trans)
elif k == ast.ASTKind.List:
return self.Gen.ExprGenConst.translate_list_literal(builder, pool, mod, node, None, trans)
elif k == ast.ASTKind.IfExp:
return self.Gen.ExprGenOps.translate_ifexp(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Lambda:
# 模块级委托:translate_lambda 定义在 FuncGenMixin(跨 Mixin
# 方法不能 self. 直接调用,见 HandlesExpr.translate_lambda)
return self.Gen.FuncGen.translate_lambda(builder, pool, mod, node, trans)
elif k == ast.ASTKind.JoinedStr:
return self.Gen.ExprGenFstr.translate_joined_str(builder, pool, mod, node, trans)
elif k == ast.ASTKind.FormattedValue:
# 解析器对 f"{expr:spec}"(单 FormattedValue 无字面量)返回裸 FormattedValue
# 而非 JoinedStr(见 ast/parser.vp _parse_fstring),需单独翻译
return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Await:
# 协程 await(TPV-M1):await 目标是 async 函数调用时内联翻译
# (子帧创建 + resume 到 DONE + 取子帧 ret 存父帧 await 槽 + 父挂起),
# 返回子协程 ret 值(i32)。顶层 await(AnnAssign/Assign 的 value 直接
# 是 Await)由 AsyncGen 段翻译特判处理,本分支覆盖表达式上下文中的
# await(M1 覆盖有限场景,详见 AsyncGenMixin._emit_await)。
aw: ast.Await | t.CPtr = (ast.Await | t.CPtr)(node)
if aw is not None and aw.value is not None and aw.value.kind() == ast.ASTKind.Call:
aw_cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(aw.value)
if aw_cl.func is not None and aw_cl.func.kind() == ast.ASTKind.Name:
aw_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aw_cl.func)
if aw_nm.id is not None and trans is not None:
if self.Gen.AsyncGen.is_async_func(trans, aw_nm.id) != 0:
return self.Gen.AsyncGen._emit_await(
builder, pool, mod, trans, aw, aw_nm.id)
return None
return None
@@ -1,758 +0,0 @@
import lib.core.Gen.GenApi as GenApi
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.TranslatorGenMixin as TranslatorGenMixin
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.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.Projectrans.Config as Config
import lib.Stub.StubMerger.StubMergerBuild as StubMergerBuild
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesTranslator - 翻译器状态管理 + 主入口
#
# 从 translator.py 拆分出来,负责:
# 1. Translator 类 - 状态管理(Module, 变量表, 函数表, 导入)
# 2. translate() - 主翻译入口
# 3. dump_ir() - IR 输出
#
# 语句/表达式翻译全部委托给 Handles 模块:
# HandlesMain - wrapper main 创建 + children 遍历
# HandlesBody - 语句分派
# HandlesExpr - 表达式翻译
# HandlesFunctions - 函数定义处理
# 注意:str = bytes = t.CChar | t.CPtr = i8*
#
# P6-E 对象化重构:模块级 global/nonlocal 名称管理函数已迁移为
# lib.core.Gen.TranslatorGenMixin 的方法,本模块保留同名模块级
# 函数作为"一行委托"(同 P2-P5 模式)。Translator 类保留在本模块。
# ============================================================
# 常量
MAX_VARS: t.CDefine = 1024
MAX_FUNCS: t.CDefine = 1024
MAX_GLOBAL_NAMES: t.CDefine = 32
# 协程表容量(TPV-M1):async 函数数 / 协程变量·局部名数
MAX_CORO_FUNCS: t.CDefine = 256
MAX_CORO_VARS: t.CDefine = 256
MAX_CORO_TRY: t.CDefine = 16
# 翻译主环最大递归深度(translate_stmt/translate_value 嵌套)。AST 自引用环
# 或翻译 bug 可致翻译主环(语句/表达式/调用)无限递归 → ASan stack-overflow。
# match 守卫(MatchTranslateDepth)只保护 match 递归,本常量保护语句/表达式
# 翻译环(fail-fast,对齐 TypeGenResolve 深度守卫模式)。
TRANSLATE_MAX_DEPTH: t.CDefine = 256
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
@t.NoVTable
class Translator:
"""翻译器:管理编译状态,委托 Handles 模块执行翻译"""
# LLVM 上下文(共享状态)
Module: llvmlite.LLVMModule | t.CPtr
Pool: memhub.MemBuddy | t.CPtr
# 函数表
_funcs: GenTypes.FuncEntry | t.CPtr
_func_count: t.CInt
# 协程(TPV-M1 async def / await / coro.coro_run)
# _async_funcs: 已注册 async 函数裸名表(char* 数组,8 字节/项)
# _coro_var_async: 变量名→async 函数名 成对表(char* 数组,16 字节/项)
# _coro_locals: 当前 async 函数局部变量名表(char* 数组,8 字节/项)
# _coro_frames: async 名→帧类型 成对表(16 字节/项 = char* + LLVMType*)
_async_funcs: str
_async_func_count: t.CInt
_coro_var_async: str
_coro_var_async_count: t.CInt
_coro_locals: str
_coro_local_count: t.CInt
_coro_frames: str
_coro_frame_count: t.CInt
# resume_<name> 翻译上下文(AsyncGenMixin 段翻译共享)
_coro_state_ptr: llvmlite.Value | t.CPtr
_coro_done_ptr: llvmlite.Value | t.CPtr
_coro_ret_ptr: llvmlite.Value | t.CPtr
_coro_exit_bb: llvmlite.BasicBlock | t.CPtr
_coro_await_slot: llvmlite.Value | t.CPtr
_coro_frame: llvmlite.Value | t.CPtr
_coro_next_state: t.CInt
_coro_nseg: t.CInt
# M2:async 参数表(char* 数组,8 字节/项)+ 预扫描计数
_coro_params: str
_coro_param_count: t.CInt
_coro_hoist_count: t.CInt # __await_N 槽计数(预扫描与翻译共用,序一致)
_coro_await_count: t.CInt # 总 await 数(= 恢复块数 = switch case 数)
_coro_local_base: t.CInt # 局部槽起始 index(= 3 + nparams)
_coro_extra_base: t.CInt # 额外槽(__await_N)起始 index
_coro_break_bb: llvmlite.BasicBlock | t.CPtr # While break 目标(M2 单层)
_coro_continue_bb: llvmlite.BasicBlock | t.CPtr # While continue 目标
_coro_state_bbs: t.CSizeT | t.CPtr # 预建 state 块数组(await 恢复块定位)
# M3-M7 协程扩展
_coro_exc_ptr: llvmlite.Value | t.CPtr # 帧 exc 槽(i32,M4)
_coro_msg_ptr: llvmlite.Value | t.CPtr # 帧 msg 槽(i8*,M7)
_coro_wake_ptr: llvmlite.Value | t.CPtr # 帧 wake 槽(i64,M3 coro_sleep)
_coro_try_stack: t.CSizeT | t.CPtr # try 栈:except/finally 块指针数组(8B/项)
_coro_try_stack_count: t.CInt
_coro_for_counter: t.CInt # range-For 编号(M3,翻译期递增)
_coro_scan_for_count: t.CInt # 预扫描期 For 计数
_coro_uses_sleep: t.CInt # 函数体是否用 coro_sleep(预扫描置位)
_coro_extra_types: str # 额外槽类型表(i8 数组:1=i32 2=i64)
_coro_extra_count: t.CInt # 额外槽总数
_coro_await_slots: t.CInt | t.CPtr # __await_N 的帧相对槽 index(预扫描填)
_coro_for_slots: t.CInt | t.CPtr # range-For N 的 __f_idx 帧相对槽 index(预扫描填)
# per-async wake 槽 index 表(coro_run/gather 轮询反查用)
_coro_wake_names: str # char* 数组(8B/项)
_coro_wake_idxs: t.CInt | t.CPtr # i32 数组(4B/项,-1=无 wake 槽)
_coro_wake_count: t.CInt
# 导入模块跟踪
_imported_modules: str
_from_imports: str
# 当前翻译上下文
_cur_func: llvmlite.Function | t.CPtr
_cur_builder: llvmlite.IRBuilder | t.CPtr
# 当前赋值语句的注解节点(AnnAssign 翻译 rhs 前设置,Assign 翻译前清空)。
# 供 c.Deref(i8*) 推断读取宽度:v: int = c.Deref(p) → bitcast i32* load,
# 对齐 TPC HandlesSpecialCall._infer_deref_target_type(DictTest 500→-12 根因:
# i8* Deref 固定读 1 字节 + sext 截断)。
CurAssignAnnot: ast.AST | t.CPtr
# 当前赋值语句的 RHS 节点(AnnAssign 翻译 rhs 前设置,rhs 翻译后清除)。
# 供 c.Deref 判定"是否为赋值直接 RHS":仅 v: int = c.Deref(p) 时用
# CurAssignAnnot 推断读取宽度;嵌套在 while 条件/比较/binop/类型转换
# 调用中(如 while c.Deref(p) != 0、total += t.CInt(c.Deref(p)))不推断,
# 否则 i8* 会被残留 CurAssignAnnot 误判为 i32* 读 4 字节(对齐 TPC
# _infer_deref_target_type 的直接 RHS 检查)。
CurAssignNode: ast.AST | t.CPtr
# 循环控制流目标(break/continue)
_break_bb: llvmlite.BasicBlock | t.CPtr
_continue_bb: llvmlite.BasicBlock | t.CPtr
# 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调)
_label_counter: t.CInt
# 追加90:控制流 merge 块可达性(1=有 br 进入可达/0=全分支 return 结构性不可达)
_ctrl_merge_reachable: t.CInt
# match 翻译递归深度(match → case body → translate_value → 嵌套 match)。
# 守卫:AST 自引用环(子节点回指祖先)或翻译 bug 导致的无限递归在此
# fail-fast(对齐 TypeGenResolve 深度守卫,防 ASan stack-overflow)。
MatchTranslateDepth: t.CInt
# 翻译主环递归深度(translate_stmt/translate_value 入口计数)。match 守卫
# 只覆盖 match 递归;语句/表达式/调用环(如 translate_value ↔ translate_call)
# 由本字段守卫,超 TRANSLATE_MAX_DEPTH 即 fail-fast(防 ASan stack-overflow)。
TranslateDepth: t.CInt
# global 声明的变量名集合(当前函数内)
_global_names: str
_global_name_count: t.CInt
# nonlocal 声明的变量名集合(当前函数内)
_nonlocal_names: str
_nonlocal_name_count: t.CInt
# nonlocal 变量的类型信息(LLVMType 指针数组,与 _nonlocal_names 一一对应)
# 用于 env 指针数组方案:子函数访问 nonlocal 变量时需要知道原始类型
_nonlocal_types: str
# 闭包相关:当前函数名(用于嵌套函数提升命名)
_cur_func_name: str
# *args 变长参数支持:当前函数的 va_list 指针(i8* alloca)
# 仅当函数声明了 *args 时设置,供 arg(type) 糖函数使用
_va_list_ptr: llvmlite.Value | t.CPtr
# *args 参数名(如 "args"),用于符号表注册
_vararg_name: str
# OOP iter 协议:当前 __next__ 方法的隐藏 stop-flag 参数(i1*)。
# _translate_method 注入 __stop_iter_flag__ 参数时设置;translate_raise
# 检测 raise StopIteration 时对该指针 store 1(对齐 TPC HandlesRaise.py)。
# 非 __next__ 函数中为 None。
_stop_iter_flag_ptr: llvmlite.Value | t.CPtr
# try-except 机制(对齐 TPC HandlesTry.py):当前最内层 try 的
# 分发块 + 异常编码/消息 alloca。translate_try 设置,translate_raise
# 与调用侧 EH 检测写入/跳转。try 外为 None。
_eh_dispatch_bb: llvmlite.BasicBlock | t.CPtr
_eh_code_ptr: llvmlite.Value | t.CPtr
_eh_msg_ptr: llvmlite.Value | t.CPtr
# 当前函数的 __eh_msg_out__(i8**)/__eh_code_out__(i32*)输出参数
# (函数签名含 raise 时由 translate_function_def/_translate_method 注入)。
# 无 EH 参数时 _cur_func_has_eh == 0。
_eh_msg_out_param: llvmlite.Value | t.CPtr
_eh_code_out_param: llvmlite.Value | t.CPtr
_cur_func_has_eh: int
# 模块 SHA1 前缀(16 字符),用于函数名混淆(SHA1 命名空间)
ModuleSha1: str
# 当前文件所属包名(如 "llvmlite"),用于解析相对导入(from . import ...)
# None 表示当前文件是顶级模块(无包),相对导入无法解析
CurrentPackage: str
# 闭包 env 中的 nonlocal 变量偏移映射(每个 nonlocal 变量在 env 中的字节偏移)
_closure_env_offsets: t.CInt
_closure_env_count: t.CInt
# lambda 表达式全局唯一 ID 计数器(生成提升函数名 __lambda_{id})
# 独立于 _closure_env_count:后者随函数进入被 clear_scope_names 重置,
# lambda ID 需跨函数全局唯一(提升函数名避免冲突)
_lambda_count: t.CInt
# 函数链内 nonlocal 变量集合(预扫描收集,含嵌套函数声明的 nonlocal)。
# 用于"不同层捕获不同变量"场景(如 level1→a, level2→b):b 定义在最外层
# 但 level1 不捕获——level1 env 无 b 槽,level2 无法经 env 链获取 b 的堆。
# 解决:在最外层函数中为链内所有 nonlocal 建堆,并把堆地址 store 到
# 模块级映射变量 @nlheap.{sha1}.{name};内层闭包创建时从映射 load。
_nl_chain_names: t.CVoid | t.CPtr
_nl_chain_count: t.CInt
# 链内 nonlocal 堆预建标志(每函数只建一次):translate_function_def 进入
# 新函数时重置为 0;_prepare_chain_nonlocals 首次调用置 1。多个嵌套函数
# 定义共享同一堆(防重复 malloc + 二次重定向 VarEntry.Alloca)。
_nl_chain_done: t.CInt
# 泛型特化上下文:当前正在特化的类型参数名/实参名列表
# 由 _specialize_generic_class 设置,方法体翻译时用于将 T 替换为具体类型
# None 表示不在泛型特化上下文中
GenericTypeParamNames: list[str] | t.CPtr
GenericTypeArgs: list[str] | t.CPtr
# Phase 1a 声明模式标志:1=只注册 struct/enum/union 不翻译代码体,0=全量翻译
_declare_only: t.CInt
# Phase A 依赖未就绪标志:1=本文件翻译时依赖模块的 text.ll 尚未生成
# (同项目源文件按顺序翻译,main.vp 先于其 import 的 mbuddytest.vp),
# 跨模块函数返回类型无法精确解析。Phase A 多遍循环据此下遍重试。
_deps_pending: t.CInt
# 嵌套作用域符号表
SymTab: GenTypes.SymbolTable | t.CPtr
def __init__(self):
self.Module = None
self.Pool = None
self._funcs = None
self._func_count = 0
self._cur_func = None
self._cur_builder = None
self._break_bb = None
self._continue_bb = None
self._label_counter = 0
self._imported_modules = None
self._from_imports = None
self._global_names = None
self._global_name_count = 0
self._nonlocal_names = None
self._nonlocal_name_count = 0
self._nonlocal_types = None
self._cur_func_name = None
self._va_list_ptr = None
self._vararg_name = None
self._stop_iter_flag_ptr = None
self._eh_dispatch_bb = None
self._eh_code_ptr = None
self._eh_msg_ptr = None
self._eh_msg_out_param = None
self._eh_code_out_param = None
self._cur_func_has_eh = 0
self.ModuleSha1 = None
self.CurrentPackage = None
self._closure_env_offsets = 0
self._closure_env_count = 0
self._lambda_count = 0
self._nl_chain_names = None
self._nl_chain_count = 0
self._nl_chain_done = 0
self.GenericTypeParamNames = None
self.GenericTypeArgs = None
self._declare_only = 0
self._deps_pending = 0
self.SymTab = None
self._async_funcs = None
self._async_func_count = 0
self._coro_var_async = None
self._coro_var_async_count = 0
self._coro_locals = None
self._coro_local_count = 0
self._coro_frames = None
self._coro_frame_count = 0
self._coro_state_ptr = None
self._coro_done_ptr = None
self._coro_ret_ptr = None
self._coro_exit_bb = None
self._coro_await_slot = None
self._coro_frame = None
self._coro_next_state = 1
self._coro_nseg = 0
self._coro_params = None
self._coro_param_count = 0
self._coro_hoist_count = 0
self._coro_await_count = 0
self._coro_local_base = 3
self._coro_extra_base = 3
self._coro_break_bb = None
self._coro_continue_bb = None
self._coro_state_bbs = None
self._coro_exc_ptr = None
self._coro_msg_ptr = None
self._coro_wake_ptr = None
self._coro_try_stack = None
self._coro_try_stack_count = 0
self._coro_for_counter = 0
self._coro_scan_for_count = 0
self._coro_uses_sleep = 0
self._coro_extra_types = None
self._coro_extra_count = 0
self._coro_await_slots = None
self._coro_for_slots = None
self._coro_wake_names = None
self._coro_wake_idxs = None
self._coro_wake_count = 0
# ============================================================
# 状态初始化
# ============================================================
def _init_state(self, pool: memhub.MemBuddy | t.CPtr):
"""初始化变量表、函数表和子 Handle"""
self.Pool = pool
if self._funcs is None:
self._funcs = GenApi.init_func_table(pool, MAX_FUNCS)
# 嵌套作用域符号表(新版)
if self.SymTab is None:
self.SymTab = GenApi.init_symbol_table(pool)
# global/nonlocal 名称集合缓冲区(32 个 char* 指针 = 256 字节)
if self._global_names is None:
self._global_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
if self._global_names is not None:
string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8)
self._global_name_count = 0
if self._nonlocal_names is None:
self._nonlocal_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
if self._nonlocal_names is not None:
string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8)
self._nonlocal_name_count = 0
# nonlocal 变量类型数组(LLVMType 指针数组,与 _nonlocal_names 一一对应)
if self._nonlocal_types is None:
self._nonlocal_types = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
if self._nonlocal_types is not None:
string.memset(self._nonlocal_types, 0, MAX_GLOBAL_NAMES * 8)
# 协程表(TPV-M1):async 函数名 / 变量→async 映射 / 局部名 / 帧类型
if self._async_funcs is None:
self._async_funcs = stdlib.malloc(MAX_CORO_FUNCS * 8)
if self._async_funcs is not None:
string.memset(self._async_funcs, 0, MAX_CORO_FUNCS * 8)
self._async_func_count = 0
if self._coro_var_async is None:
self._coro_var_async = stdlib.malloc(MAX_CORO_VARS * 16)
if self._coro_var_async is not None:
string.memset(self._coro_var_async, 0, MAX_CORO_VARS * 16)
self._coro_var_async_count = 0
if self._coro_locals is None:
self._coro_locals = stdlib.malloc(MAX_CORO_VARS * 8)
if self._coro_locals is not None:
string.memset(self._coro_locals, 0, MAX_CORO_VARS * 8)
if self._coro_params is None:
self._coro_params = stdlib.malloc(MAX_CORO_VARS * 8)
if self._coro_params is not None:
string.memset(self._coro_params, 0, MAX_CORO_VARS * 8)
if self._coro_try_stack is None:
self._coro_try_stack = stdlib.malloc(MAX_CORO_TRY * 8)
if self._coro_try_stack is not None:
string.memset(self._coro_try_stack, 0, MAX_CORO_TRY * 8)
if self._coro_extra_types is None:
self._coro_extra_types = stdlib.malloc(MAX_CORO_VARS)
if self._coro_extra_types is not None:
string.memset(self._coro_extra_types, 0, MAX_CORO_VARS)
if self._coro_await_slots is None:
self._coro_await_slots = stdlib.malloc(MAX_CORO_VARS * 4)
if self._coro_await_slots is not None:
string.memset(self._coro_await_slots, 0, MAX_CORO_VARS * 4)
if self._coro_for_slots is None:
self._coro_for_slots = stdlib.malloc(MAX_CORO_VARS * 4)
if self._coro_for_slots is not None:
string.memset(self._coro_for_slots, 0, MAX_CORO_VARS * 4)
if self._coro_wake_names is None:
self._coro_wake_names = stdlib.malloc(MAX_CORO_FUNCS * 8)
if self._coro_wake_names is not None:
string.memset(self._coro_wake_names, 0, MAX_CORO_FUNCS * 8)
if self._coro_wake_idxs is None:
self._coro_wake_idxs = stdlib.malloc(MAX_CORO_FUNCS * 4)
if self._coro_wake_idxs is not None:
string.memset(self._coro_wake_idxs, 0, MAX_CORO_FUNCS * 4)
self._coro_local_count = 0
if self._coro_frames is None:
self._coro_frames = stdlib.malloc(MAX_CORO_FUNCS * 16)
if self._coro_frames is not None:
string.memset(self._coro_frames, 0, MAX_CORO_FUNCS * 16)
self._coro_frame_count = 0
# ============================================================
# 主翻译入口
# ============================================================
def translate(self, tree: ast.AST | t.CPtr) -> int:
"""将 AST 翻译为 LLVM IR"""
if tree is None:
return 1
if _mbuddy is None:
return 1
pool: memhub.MemBuddy | t.CPtr = _mbuddy
# 初始化状态
self._init_state(pool)
# 创建 LLVM 模块
mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main")
if mod is None:
VLogger.error("NewModule returned NULL", "TR")
return 1
self.Module = mod
# 设置目标(优先使用 project.vpj 中的配置)
triple: str = Config.TargetTriple
if triple is None:
triple = "x86_64-pc-windows-msvc"
llvmlite.module_set_target(mod, triple)
# 类型
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
# 声明 printf
printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "printf", i32_ty)
if printf_func is None:
VLogger.error("CreateDeclare printf returned NULL", "TR")
return 1
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
printf_func.IsVarArg = 1
# 声明 LLVM va_start/va_end intrinsic(供 *args 函数体内使用)
# declare void @llvm.va_start(i8*)
# declare void @llvm.va_end(i8*)
void_ty_decl: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
va_start_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "llvm.va_start", void_ty_decl)
if va_start_func is not None:
llvmlite.add_param(pool, va_start_func, i8_ptr_ty, "ap")
va_end_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "llvm.va_end", void_ty_decl)
if va_end_func is not None:
llvmlite.add_param(pool, va_end_func, i8_ptr_ty, "ap")
# 声明 malloc(闭包分配用)
malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
pool, mod, "malloc", i8_ptr_ty)
if malloc_func is not None:
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
# 检查用户是否定义了 main 函数
has_user_main: int = 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is not None:
cn_count: t.CSizeT = len(ch)
for ci in range(cn_count):
child: ast.AST | t.CPtr = ch.get(ci)
if child is not None and child.kind() == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
if fd is not None and fd.name is not None:
if string.strcmp(fd.name, "main") == 0:
has_user_main = 1
break
if self._declare_only != 0:
# Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder
self._translate_module_level(pool, mod, tree)
elif has_user_main == 0:
# 无用户 main → 只翻译模块级语句,不创建 wrapper main
# 修复:避免每个文件都生成 define i32 @main() 导致链接时 main 冲突
# 只有包含 def main() 的入口文件才会有 define i32 @main()
self._translate_module_level(pool, mod, tree)
else:
# 用户已定义 main → 委托 HandlesMain 翻译模块级
self._translate_module_level(pool, mod, tree)
return 0
# ============================================================
# 包装 main 函数(无用户 main 时)→ 委托 HandlesMain
# ============================================================
def _translate_wrapper_main(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
tree: ast.AST | t.CPtr,
i32_ty: llvmlite.LLVMType | t.CPtr):
"""委托 GenApi.create_wrapper_main() 创建包装 main(trans 单参)"""
added: int = GenApi.create_wrapper_main(self, tree, i32_ty)
# ============================================================
# 模块级翻译(用户已定义 main)→ 委托 HandlesMain
# ============================================================
def _translate_module_level(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
tree: ast.AST | t.CPtr):
"""委托 GenApi.translate_children() 翻译模块级语句(trans 单参)"""
# 全量翻译模式下,先处理导入语句,再创建前向声明,解决前向引用问题
if self._declare_only == 0:
# 预处理导入语句,确保 _imported_modules 和 _from_imports 已填充
# (前向声明需要解析类型注解,如 t.CArray[str] 依赖 t 模块已导入)
# 记录最后处理的 import 行号,供 vpi 注入错误上下文帧定位
cur_imp_lineno: int = 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is not None:
cn_count: t.CSizeT = len(ch)
for ci in range(cn_count):
child: ast.AST | t.CPtr = ch.get(ci)
if child is None:
continue
kd: int = child.kind()
if kd == ast.ASTKind.Import:
cur_imp_lineno = child.lineno
GenApi.translate_import(self, child)
elif kd == ast.ASTKind.ImportFrom:
cur_imp_lineno = child.lineno
GenApi.translate_import_from_module(self, child)
GenApi.translate_import_from_names(self, child)
# 对齐 TPC _inject_auto_imports:检测源文件对 list/dict 容器的使用
# (裸名注解 d: dict / 构造 dict(...) / 下标 list[T]),自动把容器
# 类标记为可见结构体。背景:_list.vp/_dict.vp 定义内建容器类且已由
# Phase1 注册,但源文件不显式 import 它们(TPC 在翻译前自动注入
# import _list/_dict);TPV 用可见性机制等效替代——否则裸名
# `d: dict` 注解 resolve_annotation_type 时 is_struct_visible=0
# 解析失败(DictTest 的 "变量类型注解解析失败")。
self._inject_auto_container_visibility(pool, tree)
# 扫描当前模块的 CTypedef 声明已由 Phase1 1b 文本扫描注册
# (RegisterCTypedefFromSource,见 Phase1Main.vp)——AST 字符串字段
# token 零拷贝指向 src_buf,跨阶段内容不稳定,此处 AST 扫描读 attr
# 会 0xC0000005(stdint.vp 崩溃根因),故移除。
# 跨模块 .vpi 注入:加载依赖模块的 .vpi 文件,
# 将函数 declare 声明注入到当前模块,解决跨模块函数调用找不到函数的问题
# 严格保证 declare_only == 0 时才注入(避免 Phase A-pre-inc 死锁)
if self._imported_modules is not None:
# 错误上下文帧:当前模块触发依赖 stub 加载的 import 位置
GenApi.push_trace(GenApi.get_current_file(), cur_imp_lineno)
StubMergerBuild.LoadDepVpiIntoModule(
pool, mod, self._imported_modules, self._from_imports,
GenApi.get_temp_dir(), self)
GenApi.pop_trace()
# 预注册模块级变量(AnnAssign/Assign)到 SymTab
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
# _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后,
# 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None
# 预处理先于 translate_children 注册所有模块级变量,
# 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var
# 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209)
if ch is not None:
for ci in range(cn_count):
child: ast.AST | t.CPtr = ch.get(ci)
if child is None:
continue
kd_mv: int = child.kind()
if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign:
GenApi.handle_module_level_var(self, child)
# 创建前向声明
GenApi.forward_declare_functions(self, tree)
added: int = GenApi.translate_children(self, tree)
# ============================================================
# 容器模块自动可见性注入(对齐 TPC _inject_auto_imports)
#
# TPC 在翻译前自动注入 `import _list / import _dict (+json)` 到源文件,
# 使 list/dict 内建容器类在符号表中可见。TPV 用可见性机制等效替代:
# _list.vp/_dict.vp 已由 Phase1 注册(可达集合含它们),这里只需在
# 当前文件翻译时把容器类名标记为可见结构体,裸名注解/构造即可解析。
#
# 检测模式(与 TPC Phase2Translator._inject_auto_imports 一致):
# - AnnAssign 注解裸名 Name(list/dict):d: dict
# - 构造调用 func 裸名 Name(list/dict):dict(bd)
# - Subscript 的 value 裸名 Name(list/dict):list[int]
# ============================================================
def _inject_auto_container_visibility(self, pool: memhub.MemBuddy | t.CPtr,
tree: ast.AST | t.CPtr):
"""检测 list/dict 容器使用,注入容器类可见性"""
if tree is None or tree.children is None:
return
# 用栈式缓冲区传递检测结果(跨函数参数用 4 字节 int 指针)
need_list_box: t.CPtr = stdlib.malloc(4)
need_dict_box: t.CPtr = stdlib.malloc(4)
if need_list_box is None or need_dict_box is None:
if need_list_box is not None:
stdlib.free(need_list_box)
if need_dict_box is not None:
stdlib.free(need_dict_box)
return
need_list_box[0] = 0
need_dict_box[0] = 0
self._scan_container_usage(tree, need_list_box, need_dict_box)
if need_dict_box[0] != 0:
# dict 类可见 + _dict 模块导入(构造/方法调用的 SHA1 解析)
GenApi.add_visible_struct(pool, "dict")
if self._imported_modules is None or \
GenApi.is_module_imported(self._imported_modules, "_dict") == 0:
self._imported_modules = GenApi.add_imported_module(
pool, self._imported_modules, "_dict")
if need_list_box[0] != 0:
GenApi.add_visible_struct(pool, "list")
if self._imported_modules is None or \
GenApi.is_module_imported(self._imported_modules, "_list") == 0:
self._imported_modules = GenApi.add_imported_module(
pool, self._imported_modules, "_list")
stdlib.free(need_list_box)
stdlib.free(need_dict_box)
def _scan_container_usage(self, node: ast.AST | t.CPtr,
need_list_box: t.CPtr,
need_dict_box: t.CPtr):
"""递归扫描 AST 语句结构,检测 list/dict 容器使用"""
if node is None:
return
k: int = node.kind()
if k == ast.ASTKind.AnnAssign:
aa_s: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
if aa_s.annotation is not None:
self._check_container_type_node(aa_s.annotation, need_list_box, need_dict_box)
elif k == ast.ASTKind.Call:
cl_s: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
if cl_s.func is not None:
self._check_container_type_node(cl_s.func, need_list_box, need_dict_box)
elif k == ast.ASTKind.Subscript:
sub_s: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
if sub_s.value is not None:
self._check_container_type_node(sub_s.value, need_list_box, need_dict_box)
elif k == ast.ASTKind.List:
# [] 字面量:容器模板仍需注册
need_list_box[0] = 1
elif k == ast.ASTKind.Dict:
# {} 字面量:容器模板仍需注册
need_dict_box[0] = 1
# 递归语句块子节点
if node.children is not None:
ch_s: list[ast.AST | t.CPtr] | t.CPtr = node.children
n_s: t.CSizeT = len(ch_s)
for ci_s in range(n_s):
self._scan_container_usage(ch_s.get(ci_s), need_list_box, need_dict_box)
def _check_container_type_node(self, node: ast.AST | t.CPtr,
need_list_box: t.CPtr,
need_dict_box: t.CPtr):
"""检测类型位置节点是否为 list/dict(支持 Name 与 Subscript 外层)"""
if node is None:
return
k: int = node.kind()
if k == ast.ASTKind.Name:
nm_s: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
if nm_s.id is not None:
if string.strcmp(nm_s.id, "dict") == 0:
need_dict_box[0] = 1
elif string.strcmp(nm_s.id, "list") == 0:
need_list_box[0] = 1
elif k == ast.ASTKind.Subscript:
sub_s: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node)
if sub_s.value is not None:
self._check_container_type_node(sub_s.value, need_list_box, need_dict_box)
# ============================================================
# IR 输出
# ============================================================
def dump_ir(self, buf: bytes, size: t.CSizeT, mode: int):
"""将 LLVM IR 输出到缓冲区
mode: 0=完整, 1=stub(仅声明), 2=text(仅代码)
"""
if self.Module is None or buf is None:
return
if _mbuddy is None:
return
buf[0] = '\0'
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
# ============================================================
# global/nonlocal 名称管理(模块级辅助函数,委托到 gen 方法)
# ============================================================
def add_global_name(trans: HT.Translator | t.CPtr, name: str):
"""添加一个 global 变量名(委托到 gen.add_global_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.TranslatorGen.add_global_name(trans, name)
def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int:
"""检查 name 是否在当前函数的 global 集合中(委托到 gen.is_global_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TranslatorGen.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 变量名(委托到 gen.add_nonlocal_name)
Args:
name: nonlocal 变量名
var_ty: 变量的 LLVM 类型(用于 env 指针数组方案的类型恢复,
None 时回退为 i32)
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.TranslatorGen.add_nonlocal_name(trans, name, var_ty)
def get_nonlocal_type(trans: HT.Translator | t.CPtr,
name: str) -> llvmlite.LLVMType | t.CPtr:
"""获取 nonlocal 变量的 LLVM 类型(委托到 gen.get_nonlocal_type)
Returns: 找到的类型指针,找不到返回 None
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TranslatorGen.get_nonlocal_type(trans, name)
return None
def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int:
"""检查 name 是否在当前函数的 nonlocal 集合中(委托到 gen.is_nonlocal_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TranslatorGen.is_nonlocal_name(trans, name)
return 0
def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int:
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1(委托到 gen.get_nonlocal_index)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.TranslatorGen.get_nonlocal_index(trans, name)
return 0
def clear_scope_names(trans: HT.Translator | t.CPtr):
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)(委托到 gen.clear_scope_names)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.TranslatorGen.clear_scope_names(trans)
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
+111 -201
View File
@@ -1,8 +1,6 @@
import lib.core.Gen.GenApi as GenApi
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Gen.Translator as HandlesTranslator
import lib.Phase.BuildPipeline as BuildPipeline
import lib.core.IncludesScanner as IncludesScanner
import lib.Stub.StubMerger as StubMerger
@@ -42,12 +40,12 @@ CODE_PAGE: t.CDefine = 65001
# Source code buffer size (1MB)
SRC_BUF_SIZE: t.CDefine = 1048576
# Version (dev/beta/rc)
V_VIPER_VERSION: t.CDefine = "1.0.3-dev.30 2026-07-27 Non-LTS"
V_TPV_VERSION: t.CDefine = "0.0.3-dev.230"
V_RUNTIME_VERSION: t.CDefine = "0.2.2+4-Non-LTS"
V_TPC_COMMIT: t.CDefine = "1dc23ffdde"
V_TPV_COMMIT: t.CDefine = "f4fee79d4d"
V_RUNTIME_COMMIT: t.CDefine = "4ce6095359"
V_VIPER_VERSION: t.CDefine = "1.0.3-dev.31 2026-07-27 Non-LTS"
V_TPV_VERSION: t.CDefine = "0.0.3-dev.428"
V_RUNTIME_VERSION: t.CDefine = "0.2.3+19-Non-LTS"
V_TPC_COMMIT: t.CDefine = "e376b949c9"
V_TPV_COMMIT: t.CDefine = "ab0f37e1a8"
V_RUNTIME_COMMIT: t.CDefine = "f087aa88e2"
V_TARGET: t.CDefine = "x86_64-w64-windows-gnu"
V_LLVM: t.CDefine = "22.1.8"
@@ -58,10 +56,6 @@ def main() -> int:
w32cmd.SetConsoleOutputCP(CODE_PAGE)
w32cmd.SetConsoleCP(CODE_PAGE)
# [DET] 分配检测开关:在创建内存池前扫描命令行(sys._init_argv 依赖 mb,
# 不能提前;GetCommandLineA 直接读原始命令行,不含任何 pool 分配)。
# --detection 开启后 mb/perm_pool 均启用前后 0xCDCD 标记 + 记录表探测
# 越界写(定位"存活块被部分覆盖"的写入者,如 KwEntry cargs)。
detect_flag: int = 0
cmd_line_d: str = w32base.GetCommandLineA()
if cmd_line_d is not None and string.strstr(cmd_line_d, "--detection") is not None:
@@ -78,17 +72,18 @@ def main() -> int:
stdio.printf("FAIL: malloc for perm_pool arena failed\n")
return 1
mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE, detect_flag)
mb: rowptr[memhub.MemBuddy] = memhub.MemBuddy(arena, POOL_SIZE, detect_flag)
if mb is None:
stdio.printf("FAIL: MemBuddy init failed\n")
return 1
perm_pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(perm_arena, PERM_POOL_SIZE, detect_flag)
perm_pool: rowptr[memhub.MemBuddy] = memhub.MemBuddy(perm_arena, PERM_POOL_SIZE, detect_flag)
if perm_pool is None:
stdio.printf("FAIL: perm_pool init failed\n")
return 1
CompilerFactory.set_factory(CompilerFactory.CompilerFactory(mb, perm_pool))
CompilerFactory.factory = CompilerFactory.CompilerFactory(mb, perm_pool)
# 设置全局 mbuddy 指针(sys 和 argparse 都需要)
sys._mbuddy = mb
@@ -109,7 +104,7 @@ def main() -> int:
lib._mbuddy = mb
# P2: 创建项目级 Generator 单例(Phase1/Phase2/BuildPipeline 全程复用;
gen: GenGenerator.Generator | t.CPtr = mb.alloc(GenGenerator.Generator.__sizeof__())
gen: rowptr[GenGenerator.Generator] = mb.alloc(GenGenerator.Generator.__sizeof__())
if gen is None:
stdio.printf("FAIL: Generator alloc failed\n")
return 1
@@ -122,13 +117,11 @@ def main() -> int:
# 种子 TPC 时代用裸名 @_g_gen(全局共享),遗漏三个 Handles 模块无感,
# 自举后 HT/HE/HEC 委托读各自 _g_gen=None 恒失效(is_global_name 恒 0 误报)
GenApi._g_gen = gen
HandlesTranslator._g_gen = gen
HandlesExpr._g_gen = gen
HandlesExprCall._g_gen = gen
# P6: 注入语句/赋值/变量/导入/翻译驱动模块的单例
# 初始化 VLogger 并打印启动日志
log: VLogger.Logger | t.CPtr = VLogger.get_logger()
VLogger.init_logger()
log: VLogger.Logger | t.CPtr = VLogger.logger
if log is None:
log.error("TransPyV Failed to parse parameters")
@@ -153,14 +146,15 @@ def main() -> int:
parser.add_argument("--phase2command", None, argparse.STRING, 0, None, False, argparse.STORE, "Do not run llc/link: write Phase2 llc(opt+llc) and clang link commands to the given .bat path")
parser.add_argument("--nowarn-register", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Suppress Phase A dependency WARN")
parser.add_argument("--detection", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Enable MemBuddy allocation detection (0xCDCD markers + record-table probe for out-of-bounds writes; applies to both mb and perm_pool)")
parser.add_argument("--show-args", None, argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show all parsed arguments")
parser.add_argument("--build-dir", None, argparse.STRING, 0, None, False, argparse.STORE, "Override project.vpj build_dir (default ./.tpv_build; relative paths resolve against the project dir)")
parser.add_argument("--version", "-v", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show version and exit")
parser.add_argument("--help", "-h", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "Show help and exit")
# 解析命令行参数
args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv)
if args is None:
if log is not None:
log.error("参数解析失败", "argparse")
log.error("参数解析失败", "argparse")
return 1
if args.get_bool("help"):
@@ -184,39 +178,40 @@ Target: %s
return 0
# 打印解析结果
#if log is not None:
# log.banner("TransPyV 参数解析结果")
# log.banner("TransPyV 参数解析结果")
# 字符串参数
project: str = args.get_str("project")
src: str = args.get_str("src")
temp: str = args.get_str("temp")
output: str = args.get_str("output")
phase: str = args.get_str("phase")
cc: str = args.get_str("cc")
_gb_clean: INT = args.get_bool("clean")
#if project is not None: stdio.printf(" --project: %s\n", project)
#else: stdio.printf(" --project: (未指定)\n")
#if src is not None: stdio.printf(" --src: %s\n", src)
#else: stdio.printf(" --src: (未指定)\n")
#if temp is not None: stdio.printf(" --temp: %s\n", temp)
#else: stdio.printf(" --temp: (未指定)\n")
#if output is not None: stdio.printf(" --output: %s\n", output)
#else: stdio.printf(" --output: (未指定)\n")
#if phase is not None: stdio.printf(" --phase: %s\n", phase)
#else: stdio.printf(" --phase: (未指定,默认 all)\n")
#if cc is not None: stdio.printf(" --cc: %s\n", cc)
#else: stdio.printf(" --cc: (未指定)\n")
#if _gb_clean: stdio.printf(" --clean: True\n")
#else: stdio.printf(" --clean: False\n")
#if args.get_bool("run"): stdio.printf(" --run: True\n")
#else: stdio.printf(" --run: False\n")
#if args.get_bool("rebuild-includes"): stdio.printf(" --rebuild-includes: True\n")
#else: stdio.printf(" --rebuild-includes: False\n")
#if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n")
#else: stdio.printf(" --clear-cache: False\n")
#stdio.printf("\n参数解析完成。\n")
project: str = args.get_str("project")
src: str = args.get_str("src")
temp: str = args.get_str("temp")
output: str = args.get_str("output")
phase: str = args.get_str("phase")
cc: str = args.get_str("cc")
build_dir: str = args.get_str("build-dir")
_gb_clean: bool = args.get_bool("clean")
show_args: bool = args.get_bool("show-args")
if show_args:
if project is not None: stdio.printf(" --project: %s\n", project)
else: stdio.printf(" --project: (未指定)\n")
if src is not None: stdio.printf(" --src: %s\n", src)
else: stdio.printf(" --src: (未指定)\n")
if temp is not None: stdio.printf(" --temp: %s\n", temp)
else: stdio.printf(" --temp: (未指定)\n")
if output is not None: stdio.printf(" --output: %s\n", output)
else: stdio.printf(" --output: (未指定)\n")
if phase is not None: stdio.printf(" --phase: %s\n", phase)
else: stdio.printf(" --phase: (未指定,默认 all)\n")
if cc is not None: stdio.printf(" --cc: %s\n", cc)
else: stdio.printf(" --cc: (未指定)\n")
if _gb_clean: stdio.printf(" --clean: True\n")
else: stdio.printf(" --clean: False\n")
if args.get_bool("run"): stdio.printf(" --run: True\n")
else: stdio.printf(" --run: False\n")
if args.get_bool("rebuild-includes"): stdio.printf(" --rebuild-includes: True\n")
else: stdio.printf(" --rebuild-includes: False\n")
if args.get_bool("clear-cache"): stdio.printf(" --clear-cache: True\n")
else: stdio.printf(" --clear-cache: False\n")
stdio.printf("参数解析完成。\n\n")
# ASan 模式
# includes 缓存用独立目录 .binary_asan 隔离 asan 插桩 obj,避免与非 asan obj 混链
@@ -224,17 +219,12 @@ Target: %s
if args.get_bool("asan"):
BuildPipeline._asan_mode = True
Config._inc_bin_suffix = ".binary_asan"
if log is not None:
log.info("ASan 模式已启用(opt -passes=asan + libclang_rt)", "asan")
log.info("ASan 模式已启用(opt -passes=asan + libclang_rt)", "asan")
# ASan 模式清理 asan includes 缓存(强制重建 asan 插桩 obj)
mf_inc_bin_asan: str = Config.get_includes_binary_dir()
if mf_inc_bin_asan is not None:
n_asan: int = Utils.CleanDir(mf_inc_bin_asan)
if log is not None:
fb_asan: str = VLogger.fmt_buf()
if fb_asan is not None:
viperlib.snprintf(fb_asan, 1024, "ASan 模式清理 includes 缓存: %d 个文件(将重建 asan obj)", n_asan)
log.info(fb_asan, "asan")
log.info(f"ASan 模式清理 includes 缓存: {n_asan} 个文件(将重建 asan obj)", "asan")
else:
BuildPipeline._asan_mode = False
Config._inc_bin_suffix = ".binary"
@@ -245,34 +235,23 @@ Target: %s
p2c: str = args.get_str("phase2command")
if p2c is not None:
BuildPipeline._phase2_cmd_path = p2c
if log is not None:
fb_p2c: str = VLogger.fmt_buf()
if fb_p2c is not None:
viperlib.snprintf(fb_p2c, 1024, "--phase2command: 不执行 llc/链接,命令写入 %s", p2c)
log.info(fb_p2c, "phase2cmd")
log.info(f"--phase2command: 不执行 llc/链接,命令写入 {p2c}", "phase2cmd")
# --nowarn-register:抑制"外部函数返回类型未登记"类 WARN 输出
# --nowarn-register:抑制 Phase A 依赖类 WARN 输出(跨模块 text.ll 未生成,下遍收敛)
if args.get_bool("nowarn-register"):
VLogger.set_nowarn_register(1)
if log is not None:
log.info("--nowarn-register 已启用:抑制注册类 WARN 输出", "vlogger")
VLogger._nowarn_register = 1
log.info("--nowarn-register 已启用:抑制注册类 WARN 输出", "vlogger")
# 加载 project.vpj 配置
proj_loaded: int = 0
proj_path: str = project
if proj_path is not None:
if log is not None:
log.banner("工程配置")
log.banner("工程配置")
cfg_ret: int = Config.Load_project_config(proj_path)
if cfg_ret == 0:
proj_loaded = 1
else:
if log is not None:
warn_buf: str = stdlib.malloc(256)
if warn_buf is not None:
viperlib.snprintf(warn_buf, 256, "无法加载 project.vpj: %s", proj_path)
log.warning(warn_buf, "config")
stdlib.free(warn_buf)
log.warning(f"无法加载 project.vpj: {proj_path}", "config")
else:
# 尝试默认路径 project.vpj(当前目录和上级目录)
proj_path = "project.vpj"
@@ -298,63 +277,45 @@ Target: %s
if proj_dir is not None:
string.memcpy(proj_dir, proj_path, slash_pos)
proj_dir[slash_pos] = '\0'
# [--build-dir] 命令行覆盖 project.vpj 的 build_dir:在 resolve_paths 前
# 设置,使相对路径仍基于 project_dir 解析(如 ./tpv_build2 → Test/tpv_build2),
# 绝对路径(/ 或 \ 开头)由 _join_path 原样保留。
if build_dir is not None:
Config.BuildDir = build_dir
Config.resolve_paths(proj_dir)
Config.print_config()
# === --clean: 清理 temp、output 和 includes.binary 目录 ===
if _gb_clean:
if log is not None:
log.info("清理临时目录...", "clean")
log.info("清理临时目录...", "clean")
if Config.TempDir is not None:
n: int = Utils.CleanDir(Config.TempDir)
if log is not None:
fb: str = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "%s: 删除 %d 个文件", Config.TempDir, n)
log.info(fb, "clean")
log.info(f"{Config.TempDir}: 删除 {n} 个文件", "clean")
if Config.OutputDir is not None:
n2: int = Utils.CleanDir(Config.OutputDir)
if log is not None:
fb2: str = VLogger.fmt_buf()
if fb2 is not None:
viperlib.snprintf(fb2, 1024, "%s: 删除 %d 个文件", Config.OutputDir, n2)
log.info(fb2, "clean")
log.info(f"{Config.OutputDir}: 删除 {n2} 个文件", "clean")
# 清理 includes.binary 目录(旧 .obj 文件会导致跳过重新编译)
mf_inc_bin_clean: str = Config.get_includes_binary_dir()
if mf_inc_bin_clean is not None:
n3: int = Utils.CleanDir(mf_inc_bin_clean)
if log is not None:
fb3: str = VLogger.fmt_buf()
if fb3 is not None:
viperlib.snprintf(fb3, 1024, "%s: 删除 %d 个文件", mf_inc_bin_clean, n3)
log.info(fb3, "clean")
log.info(f"{mf_inc_bin_clean}: 删除 {n3} 个文件", "clean")
# === --rebuild-includes: 删除 includes.binary 预编译缓存 ===
# 强制下次编译时重新编译所有 includes(不清 temp/output)
if args.get_bool("rebuild-includes"):
if log is not None:
log.info("重建 includes 缓存...", "rebuild-includes")
log.info("重建 includes 缓存...", "rebuild-includes")
mf_inc_bin_rb: str = Config.get_includes_binary_dir()
if mf_inc_bin_rb is not None:
n_rb: int = Utils.CleanDir(mf_inc_bin_rb)
if log is not None:
fb_rb: str = VLogger.fmt_buf()
if fb_rb is not None:
viperlib.snprintf(fb_rb, 1024, "%s: 删除 %d 个文件(includes 将重新编译)", mf_inc_bin_rb, n_rb)
log.info(fb_rb, "rebuild-includes")
log.info(f"{mf_inc_bin_rb}: 删除 {n_rb} 个文件(includes 将重新编译)", "rebuild-includes")
# === --clear-cache: 清除 temp 目录缓存(.vpi/.stub.ll/.text.ll) ===
# 强制下次 Phase1 重新生成 stub(不清 output/includes.binary)
if args.get_bool("clear-cache"):
if log is not None:
log.info("清除 temp 缓存...", "clear-cache")
log.info("清除 temp 缓存...", "clear-cache")
if Config.TempDir is not None:
n_cc: int = Utils.CleanDir(Config.TempDir)
if log is not None:
fb_cc: str = VLogger.fmt_buf()
if fb_cc is not None:
viperlib.snprintf(fb_cc, 1024, "%s: 删除 %d 个文件(.vpi/.stub.ll 缓存)", Config.TempDir, n_cc)
log.info(fb_cc, "clear-cache")
log.info(f"{Config.TempDir}: 删除 {n_cc} 个文件(.vpi/.stub.ll 缓存)", "clear-cache")
# === --phase 参数控制 ===
# phase=1: 仅 stub 分离(生成 .stub.ll/.text.ll),不编译
@@ -370,11 +331,7 @@ Target: %s
do_phase1 = 1
if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0:
do_phase2 = 1
if log is not None:
fb3: str = VLogger.fmt_buf()
if fb3 is not None:
viperlib.snprintf(fb3, 1024, "模式: %s (phase1=%d phase2=%d)", phase_mode, do_phase1, do_phase2)
log.info(fb3, "phase")
log.info(f"模式: {phase_mode} (phase1={do_phase1} phase2={do_phase2})", "phase")
# === Phase1: 扫描 includes(按需翻译)===
# 对 includes 目录中每个 .vp/.py 文件,若 stub 不存在则翻译并分离 stub
@@ -387,8 +344,7 @@ Target: %s
return 1
# 如果仅 Phase1(不执行 Phase2),直接退出
if do_phase2 == 0:
if log is not None:
log.info("Phase1 完成,退出", "phase")
log.info("Phase1 完成,退出", "phase")
return 0
# AST 解析:如果指定了 --src 或 --project,读取文件并解析为 AST 树
@@ -399,71 +355,56 @@ Target: %s
# 未初始化的 Config 字段可能为垃圾指针 → is not None 检查通过 →
# 用非法路径 → 崩溃且 ASan 堆栈来不及输出)
if proj_loaded == 0 and src_path is None:
if log is not None:
log.error("未找到 project.vpj(当前目录/上级目录)且未指定 --src,无法构建", "config")
log.error("未找到 project.vpj(当前目录/上级目录)且未指定 --src,无法构建", "config")
argparse.release(args)
return 1
# === 多文件项目模式 ===
# 当 --project 指定但 --src 未指定时,扫描 source_dir 下所有 .vp/.py 文件编译
if src_path is None and project is not None and Config.SourceDir is not None:
mf_temp: str = Config.TempDir if Config.TempDir is not None else "."
mf_output: str = Config.OutputDir if Config.OutputDir is not None else "."
mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc"
mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic"
mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++"
mf_temp: str = Config.TempDir if Config.TempDir is not None else "."
mf_output: str = Config.OutputDir if Config.OutputDir is not None else "."
mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc"
mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic"
mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++"
mf_linker_flags: str = Config.LinkerFlags if Config.LinkerFlags is not None else "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition"
mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe"
mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe"
mf_static_libs: str = Config.LinkerStaticLibs
mf_dynamic_libs: str = Config.LinkerDynamicLibs
mf_includes_bin: str = Config.get_includes_binary_dir()
mf_ret: int = Phase2.RunMultiFileProject(
mb, Config.SourceDir, mf_temp, mf_output,
mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out,
mf_includes_bin, Config.IncludesDirs, do_phase1, do_phase2, log, args)
mf_includes_bin, Config.IncludesDirs, do_phase1, do_phase2, log, args,
mf_static_libs, mf_dynamic_libs)
argparse.release(args)
if log is not None:
log.success("TransPyV 完成")
log.success("TransPyV 完成")
return mf_ret
# === 单文件模式:--src 指定时使用指定文件;--project 但无 SourceDir 时回退 ===
if src_path is None and project is not None:
if Config.SourceDir is not None:
# 构造入口路径: 优先 SourceDir/main.vp,回退 SourceDir/main.py
# 构造入口路径: SourceDir/main.vp(不再做 vp -> py 后缀识别回退)
sd_len: t.CSizeT = string.strlen(Config.SourceDir)
path_buf: bytes = stdlib.malloc(sd_len + 16)
if path_buf is not None:
# 优先尝试 main.vp
viperlib.snprintf(path_buf, sd_len + 16, "%s/main.vp", Config.SourceDir)
ef: fileio.File | t.CPtr = fileio.File(path_buf, fileio.MODE.R)
if ef.closed:
# .vp 不存在,回退 main.py
viperlib.snprintf(path_buf, sd_len + 16, "%s/main.py", Config.SourceDir)
else:
ef.close()
src_path = path_buf
if log is not None:
fb4: str = VLogger.fmt_buf()
if fb4 is not None:
viperlib.snprintf(fb4, 1024, "入口文件: %s", src_path)
log.info(fb4, "project")
log.info(f"入口文件: {src_path}", "project")
if src_path is not None:
if log is not None:
log.banner("AST 解析")
log.banner("AST 解析")
# 打开文件
f: fileio.File | t.CPtr = fileio.File(src_path, fileio.MODE.R)
if f.closed:
if log is not None:
fb5: str = VLogger.fmt_buf()
if fb5 is not None:
viperlib.snprintf(fb5, 1024, "无法打开文件: %s", src_path)
log.error(fb5, "fileio")
log.error(f"无法打开文件: {src_path}", "fileio")
argparse.release(args)
return 1
# 分配源代码缓冲区
src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE)
if src_buf is None:
if log is not None:
log.error("malloc for src_buf failed", "memhub")
log.error("malloc for src_buf failed", "memhub")
f.close()
argparse.release(args)
return 1
@@ -471,11 +412,7 @@ Target: %s
bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE)
f.close()
if bytes_read < 0:
if log is not None:
fb6: str = VLogger.fmt_buf()
if fb6 is not None:
viperlib.snprintf(fb6, 1024, "读取文件失败 (错误码: %d)", bytes_read)
log.error(fb6, "fileio")
log.error(f"读取文件失败 (错误码: {bytes_read})", "fileio")
argparse.release(args)
return 1
# 添加 null 终止符,确保 strlen 和 SHA1 计算正确
@@ -483,12 +420,8 @@ Target: %s
src_buf[bytes_read] = 0
else:
src_buf[SRC_BUF_SIZE - 1] = 0
if log is not None:
log.info("文件读取完成", "fileio")
fb7: str = VLogger.fmt_buf()
if fb7 is not None:
viperlib.snprintf(fb7, 1024, "读取 %d 字节", bytes_read)
log.info(fb7, "fileio")
log.info(f"读取 {bytes_read} 字节", "fileio")
# 解析 AST(拆分为词法+语法两阶段,便于调试)
ast._init_tables(mb)
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
@@ -496,14 +429,12 @@ Target: %s
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
if tree is None:
if log is not None:
log.error("AST 解析失败", "ast")
log.error("AST 解析失败", "ast")
argparse.release(args)
return 1
# === 翻译 AST → LLVM IR ===
if log is not None:
log.banner("LLVM IR 翻译")
log.banner("LLVM IR 翻译")
tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
result: int = tr.translate(tree)
if result == 0:
@@ -513,8 +444,7 @@ Target: %s
tr.dump_ir(ir_buf, IR_BUF_SIZE, llvmlite.OUTPUT_FULL)
# === 编译管线: .ll → .obj → .exe ===
if log is not None:
log.banner("编译管线")
log.banner("编译管线")
# module_name 用源代码内容的 SHA1(前 16 字符),与 Projectrans.py 一致
# output_name 从文件名推导(如 test.vp -> test.exe),保持可读性
@@ -566,6 +496,8 @@ Target: %s
cc_flags: str = "-filetype=obj -relocation-model=pic"
linker_cmd: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++"
linker_flags: str = "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition"
linker_static_libs: str = Config.LinkerStaticLibs
linker_dynamic_libs: str = Config.LinkerDynamicLibs
# --project 模式且未显式指定 --src 时:使用 config 中的 linker_output(如 TransPyV.exe)
# 显式指定 --src 时:使用从文件名推导的 output_name(如 test.exe),避免覆盖正在运行的 exe
if project is not None and Config.LinkerOutput is not None and args.get_str("src") is None:
@@ -582,8 +514,7 @@ Target: %s
# === Phase1 stub 分离:使用 OUTPUT_STUB/TEXT 模式分别生成 stub.ll 和 text.ll ===
if do_phase1 != 0 and temp_dir is not None and module_name is not None:
if log is not None:
log.banner("stub 分离")
log.banner("stub 分离")
SF_IR_SIZE: t.CSizeT = 262144
td_len_sf: t.CSizeT = string.strlen(temp_dir)
# 保存 stub.ll
@@ -615,8 +546,7 @@ Target: %s
# phase=1 模式:仅生成 stub,不执行编译
if do_phase2 == 0:
if log is not None:
log.success("Phase1 完成(仅 stub 分离,跳过编译)")
log.success("Phase1 完成(仅 stub 分离,跳过编译)")
argparse.release(args)
return 0
@@ -624,8 +554,7 @@ Target: %s
final_ir: bytes = ir_buf
final_ir_len: t.CSizeT = ir_len
if temp_dir is not None and module_name is not None:
if log is not None:
log.banner("IR 组合")
log.banner("IR 组合")
SF_COMBINED_SIZE: t.CSizeT = 4194304 # 4MB
combined_buf: bytes = stdlib.malloc(SF_COMBINED_SIZE)
if combined_buf is not None:
@@ -640,50 +569,31 @@ Target: %s
br: BuildPipeline.BuildResult | t.CPtr = BuildPipeline.run_pipeline(
final_ir, final_ir_len, temp_dir, output_dir, module_name,
cc_cmd, cc_flags, linker_cmd, linker_flags, linker_output,
includes_binary_dir
includes_binary_dir, linker_static_libs, linker_dynamic_libs
)
if br is not None and br.Success == 1:
if log is not None:
log.success("编译管线完成")
fb8: str = VLogger.fmt_buf()
if fb8 is not None:
viperlib.snprintf(fb8, 1024, "输出: %s/%s", output_dir, linker_output)
log.info(fb8)
log.success("编译管线完成")
log.info(f"输出: {output_dir}/{linker_output}")
# --run 模式:执行生成的可执行文件
# phase2command 模式:exe 尚未链接(命令在 bat 中),跳过 --run
if args.get_bool("run") and BuildPipeline._phase2_cmd_path is None:
exe_path: bytes = stdlib.malloc(string.strlen(output_dir) + string.strlen(linker_output) + 2)
if exe_path is not None:
viperlib.snprintf(exe_path, 256, "%s/%s", output_dir, linker_output)
if log is not None:
fb9: str = VLogger.fmt_buf()
if fb9 is not None:
viperlib.snprintf(fb9, 1024, "执行: %s", exe_path)
log.info(fb9, "run")
log.info(f"执行: {exe_path}")
r: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False)
if r is not None:
if log is not None:
fb10: str = VLogger.fmt_buf()
if fb10 is not None:
viperlib.snprintf(fb10, 1024, "退出码: %d", r.returncode)
log.info(fb10, "run")
log.info(f"退出码: {r.returncode}")
else:
if log is not None:
log.error("编译管线失败", "pipeline")
if br is not None and br.ErrorMsg is not None:
fb11: str = VLogger.fmt_buf()
if fb11 is not None:
viperlib.snprintf(fb11, 1024, "编译管线失败: %s", br.ErrorMsg)
log.error(fb11, "FATAL")
log.error("编译管线失败", "pipeline")
if br is not None and br.ErrorMsg is not None:
log.error(f"编译管线失败: {br.ErrorMsg}", "FATAL")
sys.exit(1)
else:
if log is not None:
log.error("malloc for IR buffer failed", "memhub")
log.error("malloc for IR buffer failed", "memhub")
else:
if log is not None:
log.error("翻译失败", "translator")
log.error("翻译失败", "translator")
argparse.release(args)
if log is not None:
log.success("TransPyV 完成")
log.success("TransPyV 完成")
return 0