refactor(gen): 去除 Handles 委托层——链式化 + GenTypes/GenApi 迁移

- Gen 内部 1742 处 HandlesX.func() 改 self.Gen.Y.method() 链式调用
- 数据类/常量迁移 GenTypes.vp(10 类 + CLASS_META_*/META_*/SEQ_KIND_*/FIELD_MAX 等)
- 管线/保留文件经 GenApi.vp 模块级入口(48 函数带类型注解,从 Gen 方法签名自动生成)
- 删除 26 个纯委托 Handles 文件,仅留 5 个实体文件(Base/Translator/Expr/ExprCall/ExprCallTable)
- 修复字段分裂:TypeGenErr CurrentFile/TraceCount 链式化;CallGenBase TempDir/Cexport 真源化
This commit is contained in:
TermiNexus committed 2026-08-21 06:32:40 +08:00
1 parent ca1453c0ec
commit 89995dffde
96 files changed
+50608 -62634

No files matched your search

File diff suppressed because it is too large. Load diff
+1361 -1363
View File
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
+60 -58
View File
@@ -1,58 +1,60 @@
import t, c
from stdint import *
import memhub
import llvmlite
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# BaseGenMixin - 生成器基座(状态容器)
#
# 对象化重构 P1(方案见 wiki/14-oo-refactor.md):
# 将 Translator/Handles 的共享状态集中于此。后续 Mixin
# (TypeGen/StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/
# ImportsGen)单继承本类,逐步把 Handles* 模块的函数迁移为
# Generator 的方法,消除 (pool, builder, mod, node, ...) 六参连传。
#
# 注意:@t.NoVTable(静态绑定,骨架无多态需求;若未来需要
# 运行时多态再改 @t.CVTable,字段布局由编译器统一管理)。
# ============================================================
@t.NoVTable
class BaseGenMixin:
"""生成器状态容器(基座)"""
# 内存/IR 状态
Pool: memhub.MemBuddy | t.CPtr # 内存池
Module: llvmlite.LLVMModule | t.CPtr # 当前 LLVM 模块
Builder: llvmlite.IRBuilder | t.CPtr # 当前 IRBuilder
# 符号表/函数表
SymTab: HandlesVar.SymbolTable | t.CPtr
Funcs: HandlesExprCall.FuncEntry | t.CPtr
FuncCount: int
# 导入/模块信息
ImportedModules: str
FromImports: str
ModuleSha1: str
# 当前翻译上下文
CurFunc: llvmlite.Function | t.CPtr
CurBuilder: llvmlite.IRBuilder | t.CPtr
CurClassName: str
def InitBaseGen(self, pool: memhub.MemBuddy | t.CPtr) -> int:
"""初始化生成器状态(默认值;子类构造时调用)"""
if self is None:
return 1
self.Pool = pool
self.Module = None
self.Builder = None
self.SymTab = None
self.Funcs = None
self.FuncCount = 0
self.ImportedModules = None
self.FromImports = None
self.ModuleSha1 = None
self.CurFunc = None
self.CurBuilder = None
self.CurClassName = None
return 0
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import memhub
import llvmlite
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# BaseGenMixin - 生成器基座(状态容器)
#
# 对象化重构 P1(方案见 wiki/14-oo-refactor.md):
# 将 Translator/Handles 的共享状态集中于此。后续 Mixin
# (TypeGen/StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/
# ImportsGen)单继承本类,逐步把 Handles* 模块的函数迁移为
# Generator 的方法,消除 (pool, builder, mod, node, ...) 六参连传。
#
# 注意:@t.NoVTable(静态绑定,骨架无多态需求;若未来需要
# 运行时多态再改 @t.CVTable,字段布局由编译器统一管理)。
# ============================================================
@t.NoVTable
class BaseGenMixin:
"""生成器状态容器(基座)"""
# 内存/IR 状态
Gen: Generator.Generator | t.CPtr
Pool: memhub.MemBuddy | t.CPtr # 内存池
Module: llvmlite.LLVMModule | t.CPtr # 当前 LLVM 模块
Builder: llvmlite.IRBuilder | t.CPtr # 当前 IRBuilder
# 符号表/函数表
SymTab: GenTypes.SymbolTable | t.CPtr
Funcs: GenTypes.FuncEntry | t.CPtr
FuncCount: int
# 导入/模块信息
ImportedModules: str
FromImports: str
ModuleSha1: str
# 当前翻译上下文
CurFunc: llvmlite.Function | t.CPtr
CurBuilder: llvmlite.IRBuilder | t.CPtr
CurClassName: str
def InitBaseGen(self, pool: memhub.MemBuddy | t.CPtr) -> int:
"""初始化生成器状态(默认值;子类构造时调用)"""
if self is None:
return 1
self.Pool = pool
self.Module = None
self.Builder = None
self.SymTab = None
self.Funcs = None
self.FuncCount = 0
self.ImportedModules = None
self.FromImports = None
self.ModuleSha1 = None
self.CurFunc = None
self.CurBuilder = None
self.CurClassName = None
return 0
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
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+403 -410
View File
@@ -1,411 +1,404 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenFd(CallGenBase.CallGenBase):
"""FakeDuck / requires 字段注入 / provider 栈"""
# ============================================================
# _translate_fakeduck_call - FakeDuck: str 变量方法调用 → 扩展类 _Type/_str
#
# 对齐 TPC HandlesExprCall.py L2841-2880:
# ClassName 常规解析失败且对象是 char*(i8*)时,遍历扩展类查找
# {CN}.{method} 函数。对象是 Name 变量且有影子({var}__meta__,fd2
# 创建)时 self=影子;否则(字符串字面量/匿名 str)在入口创建临时
# 影子,写 __data__=obj 值、__mbuddy__=NULL 后作 self,避免
# bitcast i8* → _str* 读取垃圾指针导致 ACCESS_VIOLATION。
# ============================================================
# ============================================================
def _translate_fakeduck_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
if pool is None or builder is None or cl is None or trans is None:
return None
if method_name is None:
return None
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
# cls_name 为 None(表达式接收者解析失败)时也尝试
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
return None
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
return None
fd_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if fd_at is None or fd_at.value is None or fd_at.attr is None:
return None
if string.strcmp(fd_at.attr, method_name) != 0:
return None
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
fd_func: llvmlite.Function | t.CPtr = None
fd_cls: str = None
fd_key: str = pool.alloc(160)
if fd_key is not None:
for fd_ci in range(2):
fd_cn: str = "_Type"
if fd_ci == 1:
fd_cn = "_str"
viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name)
fd_func = self.find_func_in_module(mod, fd_key)
if fd_func is not None:
fd_cls = fd_cn
break
if fd_func is None or fd_cls is None:
return None
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
fd_sty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(fd_cls)
if fd_sty is None:
return None
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
fd_entry_fd: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(fd_sty)
fd_has_fields: int = 0
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
fd_has_fields = 1
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
fd_self: llvmlite.Value | t.CPtr = None
if fd_at.value.kind() == ast.ASTKind.Name:
fd_onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(fd_at.value)
if fd_onm.id is not None:
# pool 持久缓冲(f-string 栈缓冲在函数返回后失效)
fd_mn: str = pool.alloc(256)
if fd_mn is not None:
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
fd_meta: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
trans.SymTab, fd_mn)
if fd_meta is not None and fd_has_fields != 0:
fd_self = fd_meta
if fd_self is None:
if fd_has_fields != 0:
# 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
HandlesStruct.ensure_struct_def_in_module(pool, mod, fd_sty)
fd_self = HandlesVar._alloca_at_entry(builder, fd_sty)
if fd_self is None:
return None
fd_obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_val is not None:
fd_dfe: HandlesStruct.FieldEntry | t.CPtr = \
HandlesStruct.lookup_field(fd_sty, "__data__")
if fd_dfe is not None and fd_dfe.Ty is not None:
fd_dp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
if fd_dp is not None:
llvmlite.build_store(builder, fd_obj_val, fd_dp)
fd_bfe: HandlesStruct.FieldEntry | t.CPtr = \
HandlesStruct.lookup_field(fd_sty, "__mbuddy__")
if fd_bfe is not None and fd_bfe.Ty is not None:
fd_bp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
pool, fd_bfe.Ty, "null")
if fd_bp is not None and fd_null is not None:
llvmlite.build_store(builder, fd_null, fd_bp)
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
self._inject_requires_fields(
trans, pool, builder, mod, fd_self, fd_cls)
else:
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
fd_obj_v: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_v is None:
return None
fd_self = llvmlite.build_bitcast(
builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
if fd_self is None:
return None
# 构建参数链表: self → 其余参数
llvmlite.value_set_next(fd_self, None)
fd_head: llvmlite.Value | t.CPtr = fd_self
fd_tail: llvmlite.Value | t.CPtr = fd_self
fd_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args
fd_can: int = 0
if fd_args is not None:
fd_can = len(fd_args)
for fd_ai in range(fd_can):
fd_arg: ast.AST | t.CPtr = fd_args.get(fd_ai)
if fd_arg is not None:
fd_av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, fd_arg, None, 0, trans)
# char 常量参数 → 单字符字符串(char 隐式转 str,
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
if fd_arg.kind() == ast.ASTKind.Constant:
fd_ac: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(fd_arg)
if fd_ac.const_kind == ast.CONST_CHAR:
ch_buf: str = pool.alloc(2)
if ch_buf is not None:
ch_buf[0] = t.CChar(fd_ac.int_val)
ch_buf[1] = '\0'
fd_av = HandlesExpr.create_global_string(
builder, pool, mod, ch_buf, trans)
if fd_av is not None:
llvmlite.value_set_next(fd_av, None)
llvmlite.value_set_next(fd_tail, fd_av)
fd_tail = fd_av
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
fd_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(fd_func)
if fd_ret_ty is None:
fd_ret_ty = llvmlite.Int32(pool)
fd_fname: str = llvmlite.function_get_name(fd_func)
if fd_fname is None:
return None
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化
# 为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标
# 路径而非 list 内联 __getitem__(printf %s 解引用字符值崩溃)。
# 从定义模块 text.ll 读取精确返回类型(对齐普通方法调用 _translate_method_call)。
fd_sha1: str = pool.alloc(17)
if fd_sha1 is not None:
string.strncpy(fd_sha1, fd_fname, 16)
fd_sha1[16] = '\0'
fd_exact: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
pool, fd_sha1, fd_cls, method_name)
if fd_exact is not None:
fd_ret_ty = fd_exact
fd_total: int = 1 + fd_can
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
# ============================================================
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
#
# 对齐 TPC HandlesExprCall.py L4021-4079:
# 对类 __requires__ 元数据(fd1 注册)中的每个字段,运行时调用
# _find_provider(field) 查找 with 上下文提供的指针;非 NULL 时
# bitcast 到字段类型写入 meta_ptr 对应槽位(条件注入,避免覆盖
# 用户已手动设置的值)。_find_provider 未注册(未 import
# _withcontent)时跳过注入,不影响非 with 场景。
# ============================================================
# ============================================================
def _inject_requires_fields(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
meta_ptr: llvmlite.Value | t.CPtr,
class_name: str) -> int:
"""在 with 上下文注入 requires 字段,返回注入字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if meta_ptr is None or class_name is None:
return 0
# _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent
# 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
fd_fn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_find_provider")
if fd_fn_probe is None:
return 0
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
if fd_fname is None:
return 0
cnt: int = HandlesType.class_meta_count(
HandlesType.CLASS_META_REQUIRES, class_name)
if cnt <= 0:
return 0
sty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(class_name)
if sty is None:
return 0
i8_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty_j is None:
return 0
i8_ptr_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_j)
if i8_ptr_ty_j is None:
return 0
cur_func: llvmlite.Function | t.CPtr = trans._cur_func
if cur_func is None:
return 0
injected: int = 0
for ji in range(cnt):
fname: str = HandlesType.class_meta_field_at(
HandlesType.CLASS_META_REQUIRES, class_name, ji)
if fname is None:
continue
fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field(
sty, fname)
if fe is None or fe.Ty is None:
continue
# 参数:字段名字符串(i8*)
fd_fstr: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string(
builder, pool, mod, fname, trans)
if fd_fstr is None:
continue
llvmlite.value_set_next(fd_fstr, None)
self._ensure_method_declare(
pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
fd_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
if fd_ptr is None:
continue
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
pool, i8_ptr_ty_j, "null")
if fd_null is None:
continue
fd_cmp: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
if fd_cmp is None:
continue
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
# 冲突 → llc "Terminator found in the middle of a basic block")
vtc2: int = trans._label_counter
trans._label_counter = vtc2 + 1
fd_bb_buf2: str = pool.alloc(64)
if fd_bb_buf2 is None:
continue
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
fd_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, cur_func, fd_bb_buf2)
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
fd_inject_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, cur_func, fd_bb_buf2)
if fd_skip_bb is None or fd_inject_bb is None:
continue
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
# inject 块:bitcast + GEP + store,跳回 skip
llvmlite.position_at_end(builder, fd_inject_bb)
fd_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, fd_ptr, fe.Ty)
if fd_cast is not None:
fd_fp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, sty, fe.Ty, meta_ptr, fe.Index)
if fd_fp is not None:
llvmlite.build_store(builder, fd_cast, fd_fp)
llvmlite.build_br(builder, fd_skip_bb)
# skip 块:恢复 CurBlock,继续后续代码生成
llvmlite.position_at_end(builder, fd_skip_bb)
injected += 1
return injected
# ============================================================
# _emit_provider_push / _emit_provider_pop - FakeDuck: with 上下文
# provider push/pop(__provides__ 元数据,fd1 注册)
#
# 对齐 TPC HandlesWith.py L138-174:
# with 进入时对每个提供字段生成 _push_provider(field_str, ctx_i8);
# 退出时生成等量 _pop_provider()。运行时 _withcontent 模块负责
# 维护 TLS provider 栈,供 _inject_requires_fields 查找。
# ============================================================
# ============================================================
def _emit_provider_push(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str,
ctx_val: llvmlite.Value | t.CPtr) -> int:
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if cls_name is None or ctx_val is None:
return 0
fd_pc: int = HandlesType.class_meta_count(
HandlesType.CLASS_META_PROVIDES, cls_name)
if fd_pc <= 0:
return 0
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pfn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_push_provider")
if fd_pfn_probe is None:
return 0
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
if fd_pfn is None:
return 0
i8_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty_p is None:
return 0
i8_ptr_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_p)
if i8_ptr_ty_p is None:
return 0
ret_i32_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if ret_i32_p is None:
return 0
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
fd_ctx_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, ctx_val, i8_ptr_ty_p)
if fd_ctx_i8 is None:
return 0
for pi in range(fd_pc):
fname: str = HandlesType.class_meta_field_at(
HandlesType.CLASS_META_PROVIDES, cls_name, pi)
if fname is None:
continue
fd_fstr: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string(
builder, pool, mod, fname, trans)
if fd_fstr is None:
continue
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
llvmlite.value_set_next(fd_ctx_i8, None)
self._ensure_method_declare(
pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
return fd_pc
def _emit_provider_pop(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str) -> int:
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if cls_name is None:
return 0
fd_pc: int = HandlesType.class_meta_count(
HandlesType.CLASS_META_PROVIDES, cls_name)
if fd_pc <= 0:
return 0
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pon_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_pop_provider")
if fd_pon_probe is None:
return 0
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
if fd_pon is None:
return 0
ret_i32_q: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if ret_i32_q is None:
return 0
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
for _pi in range(fd_pc):
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenFd - CallGenMixin 拆分(阶段 B):FakeDuck / requires 字段注入 / provider 栈
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenFd(CallGenBase.CallGenBase):
"""FakeDuck / requires 字段注入 / provider 栈"""
# ============================================================
# _translate_fakeduck_call - FakeDuck: str 变量方法调用 → 扩展类 _Type/_str
#
# 对齐 TPC HandlesExprCall.py L2841-2880:
# ClassName 常规解析失败且对象是 char*(i8*)时,遍历扩展类查找
# {CN}.{method} 函数。对象是 Name 变量且有影子({var}__meta__,fd2
# 创建)时 self=影子;否则(字符串字面量/匿名 str)在入口创建临时
# 影子,写 __data__=obj 值、__mbuddy__=NULL 后作 self,避免
# bitcast i8* → _str* 读取垃圾指针导致 ACCESS_VIOLATION。
# ============================================================
# ============================================================
def _translate_fakeduck_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""FakeDuck: str 变量方法调用解析到扩展类 _Type/_str,返回 call 结果或 None"""
if pool is None or builder is None or cl is None or trans is None:
return None
if method_name is None:
return None
# 仅对 str 类型触发(AnnotClassName == "str",对象是 char*);
# cls_name 为 None(表达式接收者解析失败)时也尝试
if cls_name is not None and string.strcmp(cls_name, "str") != 0:
return None
if cl.func is None or cl.func.kind() != ast.ASTKind.Attribute:
return None
fd_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if fd_at is None or fd_at.value is None or fd_at.attr is None:
return None
if string.strcmp(fd_at.attr, method_name) != 0:
return None
# 候选扩展类:先 _Type(a.type_id())后 _str(a.upper() 等)
fd_func: llvmlite.Function | t.CPtr = None
fd_cls: str = None
fd_key: str = pool.alloc(160)
if fd_key is not None:
for fd_ci in range(2):
fd_cn: str = "_Type"
if fd_ci == 1:
fd_cn = "_str"
viperlib.snprintf(fd_key, 160, "%s.%s", fd_cn, method_name)
fd_func = self.find_func_in_module(mod, fd_key)
if fd_func is not None:
fd_cls = fd_cn
break
if fd_func is None or fd_cls is None:
return None
# 扩展类结构体必须已注册(GEP/临时影子需要类型)
fd_sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(fd_cls)
if fd_sty is None:
return None
# 扩展类字段数:有字段(_str)时 self 用影子结构体指针;
# 无字段(_Type)时 self 用对象值 bitcast 到扩展类指针(对齐 TPC L2856-2876)
fd_entry_fd: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct_by_type(fd_sty)
fd_has_fields: int = 0
if fd_entry_fd is not None and fd_entry_fd.FieldCount > 0:
fd_has_fields = 1
# self 参数:优先使用已有影子 {var}__meta__(fd2 创建,仅当扩展类有字段时)
fd_self: llvmlite.Value | t.CPtr = None
if fd_at.value.kind() == ast.ASTKind.Name:
fd_onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(fd_at.value)
if fd_onm.id is not None:
# pool 持久缓冲(f-string 栈缓冲在函数返回后失效)
fd_mn: str = pool.alloc(256)
if fd_mn is not None:
viperlib.snprintf(fd_mn, 256, "%s__meta__", fd_onm.id)
fd_meta: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_current(
trans.SymTab, fd_mn)
if fd_meta is not None and fd_has_fields != 0:
fd_self = fd_meta
if fd_self is None:
if fd_has_fields != 0:
# 有字段扩展类且无影子(字符串字面量等):入口创建临时影子并初始化
# 先确保 _str 完整定义(跨模块结构体默认 opaque,alloca 报 unsized)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, fd_sty)
fd_self = self.Gen.VarGen._alloca_at_entry(builder, fd_sty)
if fd_self is None:
return None
fd_obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_val is not None:
fd_dfe: GenTypes.FieldEntry | t.CPtr = \
self.Gen.StructGen.lookup_field(fd_sty, "__data__")
if fd_dfe is not None and fd_dfe.Ty is not None:
fd_dp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, fd_sty, fd_dfe.Ty, fd_self, fd_dfe.Index)
if fd_dp is not None:
llvmlite.build_store(builder, fd_obj_val, fd_dp)
fd_bfe: GenTypes.FieldEntry | t.CPtr = \
self.Gen.StructGen.lookup_field(fd_sty, "__mbuddy__")
if fd_bfe is not None and fd_bfe.Ty is not None:
fd_bp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, fd_sty, fd_bfe.Ty, fd_self, fd_bfe.Index)
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
pool, fd_bfe.Ty, "null")
if fd_bp is not None and fd_null is not None:
llvmlite.build_store(builder, fd_null, fd_bp)
# FakeDuck: with 上下文自动注入 requires 字段(如 __mbuddy__)
self._inject_requires_fields(
trans, pool, builder, mod, fd_self, fd_cls)
else:
# 无字段扩展类(_Type):对象值 bitcast 到扩展类指针
fd_obj_v: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, fd_at.value, None, 0, trans)
if fd_obj_v is None:
return None
fd_self = llvmlite.build_bitcast(
builder, fd_obj_v, llvmlite.Ptr(pool, fd_sty))
if fd_self is None:
return None
# 构建参数链表: self → 其余参数
llvmlite.value_set_next(fd_self, None)
fd_head: llvmlite.Value | t.CPtr = fd_self
fd_tail: llvmlite.Value | t.CPtr = fd_self
fd_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args
fd_can: int = 0
if fd_args is not None:
fd_can = len(fd_args)
for fd_ai in range(fd_can):
fd_arg: ast.AST | t.CPtr = fd_args.get(fd_ai)
if fd_arg is not None:
fd_av: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, fd_arg, None, 0, trans)
# char 常量参数 → 单字符字符串(char 隐式转 str,
# 如 s1.split(','):',' 是 i32 值 44,传给 str 参数须先字符串化,
# 否则运行时 strlen/strncmp 解引用 44 崩溃)
if fd_arg.kind() == ast.ASTKind.Constant:
fd_ac: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(fd_arg)
if fd_ac.const_kind == ast.CONST_CHAR:
ch_buf: str = pool.alloc(2)
if ch_buf is not None:
ch_buf[0] = t.CChar(fd_ac.int_val)
ch_buf[1] = '\0'
fd_av = self.Gen.ExprGenConst.create_global_string(
builder, pool, mod, ch_buf, trans)
if fd_av is not None:
llvmlite.value_set_next(fd_av, None)
llvmlite.value_set_next(fd_tail, fd_av)
fd_tail = fd_av
# 返回类型与调用名(来自 find_func_in_module 命中的函数定义)
fd_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(fd_func)
if fd_ret_ty is None:
fd_ret_ty = llvmlite.Int32(pool)
fd_fname: str = llvmlite.function_get_name(fd_func)
if fd_fname is None:
return None
# 返回类型精确化:跨模块 declare 的 list[T] 特化返回类型可能被简化
# 为 Ptr(i8),调用方变量 alloca 类型随之退化 → parts[0] 走字符下标
# 路径而非 list 内联 __getitem__(printf %s 解引用字符值崩溃)。
# 从定义模块 text.ll 读取精确返回类型(对齐普通方法调用 _translate_method_call)。
fd_sha1: str = pool.alloc(17)
if fd_sha1 is not None:
string.strncpy(fd_sha1, fd_fname, 16)
fd_sha1[16] = '\0'
fd_exact: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
pool, fd_sha1, fd_cls, method_name)
if fd_exact is not None:
fd_ret_ty = fd_exact
fd_total: int = 1 + fd_can
return llvmlite.build_call(builder, fd_fname, fd_head, fd_total, fd_ret_ty, 0)
# ============================================================
# _inject_requires_fields - FakeDuck: with 上下文注入 requires 字段
#
# 对齐 TPC HandlesExprCall.py L4021-4079:
# 对类 __requires__ 元数据(fd1 注册)中的每个字段,运行时调用
# _find_provider(field) 查找 with 上下文提供的指针;非 NULL 时
# bitcast 到字段类型写入 meta_ptr 对应槽位(条件注入,避免覆盖
# 用户已手动设置的值)。_find_provider 未注册(未 import
# _withcontent)时跳过注入,不影响非 with 场景。
# ============================================================
# ============================================================
def _inject_requires_fields(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
meta_ptr: llvmlite.Value | t.CPtr,
class_name: str) -> int:
"""在 with 上下文注入 requires 字段,返回注入字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if meta_ptr is None or class_name is None:
return 0
# _withcontent._find_provider(跨模块):仅当本模块可见(_withcontent
# 被 import,vpi stub declare 已注入)时才注入。对齐 TPC L4048-4050
# (Gen.functions.get('_find_provider') 不存在则跳过)——否则非 with
# 项目(如 HashTableTest 未 import _withcontent)也会为每个 _str(...)
# 构造发射 {sha1}._find_provider 调用 → ld.lld undefined symbol。
fd_fn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_find_provider")
if fd_fn_probe is None:
return 0
fd_fname: str = llvmlite.function_get_name(fd_fn_probe)
if fd_fname is None:
return 0
cnt: int = self.Gen.ClassGenBase.class_meta_count(
GenTypes.CLASS_META_REQUIRES, class_name)
if cnt <= 0:
return 0
sty: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(class_name)
if sty is None:
return 0
i8_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty_j is None:
return 0
i8_ptr_ty_j: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_j)
if i8_ptr_ty_j is None:
return 0
cur_func: llvmlite.Function | t.CPtr = trans._cur_func
if cur_func is None:
return 0
injected: int = 0
for ji in range(cnt):
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
GenTypes.CLASS_META_REQUIRES, class_name, ji)
if fname is None:
continue
fe: GenTypes.FieldEntry | t.CPtr = self.Gen.StructGen.lookup_field(
sty, fname)
if fe is None or fe.Ty is None:
continue
# 参数:字段名字符串(i8*)
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
builder, pool, mod, fname, trans)
if fd_fstr is None:
continue
llvmlite.value_set_next(fd_fstr, None)
self._ensure_method_declare(
pool, mod, fd_fname, i8_ptr_ty_j, fd_fstr, 1)
fd_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
builder, fd_fname, fd_fstr, 1, i8_ptr_ty_j, 0)
if fd_ptr is None:
continue
# 条件注入:ptr != NULL 才写入(保留用户手动设置的值)
fd_null: llvmlite.Value | t.CPtr = llvmlite.ConstNull(
pool, i8_ptr_ty_j, "null")
if fd_null is None:
continue
fd_cmp: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
builder, llvmlite.ICMP_NE, fd_ptr, fd_null)
if fd_cmp is None:
continue
# 块名唯一化(create_block 不自动编号,同名 label 在文本 IR 中
# 冲突 → llc "Terminator found in the middle of a basic block")
vtc2: int = trans._label_counter
trans._label_counter = vtc2 + 1
fd_bb_buf2: str = pool.alloc(64)
if fd_bb_buf2 is None:
continue
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
fd_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, cur_func, fd_bb_buf2)
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
fd_inject_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, cur_func, fd_bb_buf2)
if fd_skip_bb is None or fd_inject_bb is None:
continue
llvmlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
# inject 块:bitcast + GEP + store,跳回 skip
llvmlite.position_at_end(builder, fd_inject_bb)
fd_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, fd_ptr, fe.Ty)
if fd_cast is not None:
fd_fp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, sty, fe.Ty, meta_ptr, fe.Index)
if fd_fp is not None:
llvmlite.build_store(builder, fd_cast, fd_fp)
llvmlite.build_br(builder, fd_skip_bb)
# skip 块:恢复 CurBlock,继续后续代码生成
llvmlite.position_at_end(builder, fd_skip_bb)
injected += 1
return injected
# ============================================================
# _emit_provider_push / _emit_provider_pop - FakeDuck: with 上下文
# provider push/pop(__provides__ 元数据,fd1 注册)
#
# 对齐 TPC HandlesWith.py L138-174:
# with 进入时对每个提供字段生成 _push_provider(field_str, ctx_i8);
# 退出时生成等量 _pop_provider()。运行时 _withcontent 模块负责
# 维护 TLS provider 栈,供 _inject_requires_fields 查找。
# ============================================================
# ============================================================
def _emit_provider_push(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str,
ctx_val: llvmlite.Value | t.CPtr) -> int:
"""生成 _push_provider(field, ctx_i8) 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if cls_name is None or ctx_val is None:
return 0
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
GenTypes.CLASS_META_PROVIDES, cls_name)
if fd_pc <= 0:
return 0
# _withcontent._push_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pfn_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_push_provider")
if fd_pfn_probe is None:
return 0
fd_pfn: str = llvmlite.function_get_name(fd_pfn_probe)
if fd_pfn is None:
return 0
i8_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty_p is None:
return 0
i8_ptr_ty_p: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_p)
if i8_ptr_ty_p is None:
return 0
ret_i32_p: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if ret_i32_p is None:
return 0
# ctx 值 bitcast 到 i8*(provider 栈存 void*)
fd_ctx_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, ctx_val, i8_ptr_ty_p)
if fd_ctx_i8 is None:
return 0
for pi in range(fd_pc):
fname: str = self.Gen.ClassGenBase.class_meta_field_at(
GenTypes.CLASS_META_PROVIDES, cls_name, pi)
if fname is None:
continue
fd_fstr: llvmlite.Value | t.CPtr = self.Gen.ExprGenConst.create_global_string(
builder, pool, mod, fname, trans)
if fd_fstr is None:
continue
llvmlite.value_set_next(fd_fstr, fd_ctx_i8)
llvmlite.value_set_next(fd_ctx_i8, None)
self._ensure_method_declare(
pool, mod, fd_pfn, ret_i32_p, fd_fstr, 2)
llvmlite.build_call(builder, fd_pfn, fd_fstr, 2, ret_i32_p, 0)
return fd_pc
def _emit_provider_pop(self, trans: HT.Translator | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str) -> int:
"""生成 _pop_provider() 调用(每提供字段一次),返回字段数"""
if trans is None or pool is None or builder is None or mod is None:
return 0
if cls_name is None:
return 0
fd_pc: int = self.Gen.ClassGenBase.class_meta_count(
GenTypes.CLASS_META_PROVIDES, cls_name)
if fd_pc <= 0:
return 0
# _withcontent._pop_provider(跨模块,同 _find_provider 的可见性守卫:
# 本模块未 import _withcontent 时跳过,避免 undefined symbol)
fd_pon_probe: llvmlite.Function | t.CPtr = self.find_func_in_module(
mod, "_pop_provider")
if fd_pon_probe is None:
return 0
fd_pon: str = llvmlite.function_get_name(fd_pon_probe)
if fd_pon is None:
return 0
ret_i32_q: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if ret_i32_q is None:
return 0
self._ensure_method_declare(pool, mod, fd_pon, ret_i32_q, None, 0)
for _pi in range(fd_pc):
llvmlite.build_call(builder, fd_pon, None, 0, ret_i32_q, 0)
return fd_pc
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
+412 -419
View File
@@ -1,420 +1,413 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenProp - CallGenMixin 拆分(阶段 B):属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenProp(CallGenBase.CallGenBase):
"""属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)"""
# ============================================================
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
#
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
# ============================================================
# ============================================================
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
#
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
# ============================================================
# ============================================================
# _translate_property_call — 翻译属性方法调用
#
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
#
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
# ============================================================
def _translate_property_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
call_head: llvmlite.Value | t.CPtr,
call_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译属性/静态方法调用,返回 call 结果 Value"""
if pool is None or builder is None or class_name is None or method_name is None:
return None
# 构造查找名: ClassName.method_name
lookup_name: str = pool.alloc(128)
if lookup_name is None:
return None
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
# 查找函数(精确/后缀匹配)
found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, lookup_name)
# 确定调用名
call_name: str = lookup_name
if found_func is not None:
found_name: str = llvmlite.function_get_name(found_func)
if found_name is not None:
call_name = found_name
else:
# 未找到:用类所属模块的 SHA1 构造调用名
cls_sha1_pc: str = HandlesStruct.get_struct_sha1(class_name)
if cls_sha1_pc is not None:
mlen_pc: t.CSizeT = string.strlen(cls_sha1_pc) + string.strlen(lookup_name) + 2
mangled_pc: str = pool.alloc(mlen_pc)
if mangled_pc is not None:
viperlib.snprintf(mangled_pc, mlen_pc, "%s.%s", cls_sha1_pc, lookup_name)
call_name = mangled_pc
# 确定返回类型
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if found_func is not None:
frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func)
if frt is not None:
call_ret_ty = frt
else:
sp_ty1: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty(pool, class_name, method_name)
if sp_ty1 is not None:
call_ret_ty = sp_ty1
else:
cls_sha1_rt: str = HandlesStruct.get_struct_sha1(class_name)
looked_up_ty: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
pool, cls_sha1_rt, class_name, method_name)
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
else:
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType | t.CPtr = self._lookup_method_ret_ty_via_vpi(
pool, cls_sha1_rt, class_name, method_name)
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
else:
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
# 标记 pending 下遍重译(对齐 _translate_method_call L4783-4790),
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
if cls_sha1_rt is None \
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
if trans is not None:
trans._deps_pending = 1
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
else:
call_ret_ty = self._fail_method_ret_ty(method_name)
# 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
tgt_func_pc: llvmlite.Function | t.CPtr = found_func
if tgt_func_pc is None:
tgt_func_pc = self.find_func_in_module(mod, call_name)
if tgt_func_pc is not None:
prev_pc: llvmlite.Value | t.CPtr = None
cur_arg_pc: llvmlite.Value | t.CPtr = call_head
cur_param_pc: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(tgt_func_pc)
while cur_arg_pc is not None and cur_param_pc is not None:
param_ty_pc: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_pc)
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
coerced_pc: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
builder, cur_arg_pc, param_ty_pc)
if coerced_pc is not None and coerced_pc != cur_arg_pc:
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
if prev_pc is None:
call_head = coerced_pc
else:
llvmlite.value_set_next(prev_pc, coerced_pc)
cur_arg_pc = coerced_pc
prev_pc = cur_arg_pc
cur_arg_pc = cur_arg_pc.Next
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
# 确保 declare 存在,然后调用
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
# ============================================================
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
#
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
# 供属性访问/赋值/删除识别 property 时使用。
# ============================================================
# ============================================================
def _resolve_obj_class_name(self, pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr,
obj_node: ast.AST | t.CPtr) -> str:
"""解析对象表达式的类名(短名),失败返回 None"""
if pool is None or trans is None or obj_node is None:
return None
if obj_node.kind() == ast.ASTKind.Name:
obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(obj_node)
if obj_nm.id is not None:
var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
trans.SymTab, obj_nm.id)
if var_entry is not None and var_entry.AnnotClassName is not None:
annot_val: str = var_entry.AnnotClassName
dot_ptr: str = string.strrchr(annot_val, '.')
if dot_ptr is not None:
return dot_ptr + 1
return annot_val
return None
# ============================================================
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
#
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
# ============================================================
# ============================================================
def _try_property_getter_attr(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
at_node: ast.Attribute | t.CPtr,
obj_ptr: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr,
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
"""
if at_node is None or at_node.attr is None or obj_ptr is None or trans is None:
return None
class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value)
if class_name is None:
class_name = fallback_class_name
if class_name is None:
return None
meta: int = HandlesClassDef.lookup_method_meta(class_name, at_node.attr)
if meta & HandlesClassDef.META_PROP_GETTER == 0:
return None
# 单参数调用: obj → getter
llvmlite.value_set_next(obj_ptr, None)
return self._translate_property_call(
pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
# ============================================================
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
#
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
# ============================================================
# ============================================================
def _try_property_setter(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
rhs_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if target_attr is None or target_attr.attr is None or rhs_val is None:
return 0
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
if class_name is None:
return 0
meta: int = HandlesClassDef.lookup_method_meta(class_name, target_attr.attr)
if meta & HandlesClassDef.META_PROP_SETTER == 0:
return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None:
return 0
# 构建参数链表: obj → rhs
llvmlite.value_set_next(obj_val, None)
llvmlite.value_set_next(rhs_val, None)
llvmlite.value_set_next(obj_val, rhs_val)
# setter 函数名带 $set 后缀
setter_name_buf: str = pool.alloc(128)
if setter_name_buf is None:
return 0
viperlib.snprintf(setter_name_buf, 128, "%s$set", target_attr.attr)
self._translate_property_call(pool, builder, mod, class_name,
setter_name_buf, obj_val, 2, trans)
return 1
# ============================================================
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
#
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
# ============================================================
# ============================================================
def _try_property_deleter(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if target_attr is None or target_attr.attr is None:
return 0
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
if class_name is None:
return 0
meta: int = HandlesClassDef.lookup_method_meta(class_name, target_attr.attr)
if meta & HandlesClassDef.META_PROP_DELETER == 0:
return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None:
return 0
llvmlite.value_set_next(obj_val, None)
# deleter 函数名带 $del 后缀
del_name_buf: str = pool.alloc(128)
if del_name_buf is None:
return 0
viperlib.snprintf(del_name_buf, 128, "%s$del", target_attr.attr)
self._translate_property_call(pool, builder, mod, class_name,
del_name_buf, obj_val, 1, trans)
return 1
# ============================================================
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
#
# @staticmethod: 直接 call Class.method(args...),无 self
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
# ============================================================
# ============================================================
def _translate_static_class_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
if pool is None or builder is None or mod is None or trans is None:
return None
if class_name is None or method_name is None or cl is None:
return None
meta: int = HandlesClassDef.lookup_method_meta(class_name, method_name)
is_static: int = 0
is_class: int = 0
if meta & HandlesClassDef.META_STATIC != 0:
is_static = 1
if meta & HandlesClassDef.META_CLASS != 0:
is_class = 1
if is_static == 0 and is_class == 0:
return None
# 构建参数链表
head: llvmlite.Value | t.CPtr = None
total_count: int = 0
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
if is_class != 0:
struct_ty_cc: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(class_name)
if struct_ty_cc is None:
return None
cls_ptr: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty_cc)
if cls_ptr is None:
return None
llvmlite.value_set_next(cls_ptr, None)
head = cls_ptr
total_count = 1
# 翻译调用参数
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
can: t.CSizeT = 0
if cargs is not None:
can = len(cargs)
tail: llvmlite.Value | t.CPtr = head
for ai in range(can):
arg_node: ast.AST | t.CPtr = cargs.get(ai)
if arg_node is None:
continue
arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, arg_node, None, 0, trans)
if arg_val is None:
continue
llvmlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
tail = arg_val
else:
llvmlite.value_set_next(tail, arg_val)
tail = arg_val
total_count += 1
# 零参 @staticmethod(如 PyListObj.new()):head 保持 None 是合法的
# 无参调用,照常走 _translate_property_call(SHA1 前缀名 + 精确返回类型)。
# 若此处 return None,调用方回退通用路径把方法名当裸函数解析,生成
# call i32 @new() → 链接 undefined reference(CPythonTest 根因)。
# @classmethod 恒有 cls_ptr(head 非 None),不受影响。
return self._translate_property_call(pool, builder, mod, class_name,
method_name, head, total_count, trans)
# ============================================================
# _is_list_builtin_method - 判断是否是 list 泛型内置容器方法
#
# list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/
# __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list
# 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把
# list 特化 struct(如 list[AST | CPtr])误当普通结构体走
# _translate_method_call,会查不到 append 返回类型 → fail-fast
# (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。
#
# 返回: 1=list 内置方法(应落到 list 内置分支),0=普通方法
# ============================================================
# ============================================================
def _is_list_builtin_method(self, class_name: str,
method_name: str) -> int:
"""判断 (class_name, method_name) 是否是 list 泛型内置方法"""
if class_name is None or method_name is None:
return 0
# 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名)
if string.strncmp(class_name, "list", 4) != 0:
return 0
# 方法名必须是 list 内置方法集合
if string.strcmp(method_name, "append") == 0: return 1
if string.strcmp(method_name, "get") == 0: return 1
if string.strcmp(method_name, "set") == 0: return 1
if string.strcmp(method_name, "pop") == 0: return 1
if string.strcmp(method_name, "clear") == 0: return 1
if string.strcmp(method_name, "__iter__") == 0: return 1
if string.strcmp(method_name, "__len__") == 0: return 1
if string.strcmp(method_name, "__getitem__") == 0: return 1
if string.strcmp(method_name, "__setitem__") == 0: return 1
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenProp - CallGenMixin 拆分(阶段 B):属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenProp(CallGenBase.CallGenBase):
"""属性访问(getter/setter/deleter / 静态类调用 / list 内置方法)"""
# ============================================================
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
#
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
# ============================================================
# ============================================================
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
#
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
# ============================================================
# ============================================================
# _translate_property_call — 翻译属性方法调用
#
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
#
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
# ============================================================
def _translate_property_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
call_head: llvmlite.Value | t.CPtr,
call_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译属性/静态方法调用,返回 call 结果 Value"""
if pool is None or builder is None or class_name is None or method_name is None:
return None
# 构造查找名: ClassName.method_name
lookup_name: str = pool.alloc(128)
if lookup_name is None:
return None
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name)
# 查找函数(精确/后缀匹配)
found_func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, lookup_name)
# 确定调用名
call_name: str = lookup_name
if found_func is not None:
found_name: str = llvmlite.function_get_name(found_func)
if found_name is not None:
call_name = found_name
else:
# 未找到:用类所属模块的 SHA1 构造调用名
cls_sha1_pc: str = self.Gen.StructGen.get_struct_sha1(class_name)
if cls_sha1_pc is not None:
mlen_pc: t.CSizeT = string.strlen(cls_sha1_pc) + string.strlen(lookup_name) + 2
mangled_pc: str = pool.alloc(mlen_pc)
if mangled_pc is not None:
viperlib.snprintf(mangled_pc, mlen_pc, "%s.%s", cls_sha1_pc, lookup_name)
call_name = mangled_pc
# 确定返回类型
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if found_func is not None:
frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func)
if frt is not None:
call_ret_ty = frt
else:
sp_ty1: llvmlite.LLVMType | t.CPtr = self._special_method_ret_ty(pool, class_name, method_name)
if sp_ty1 is not None:
call_ret_ty = sp_ty1
else:
cls_sha1_rt: str = self.Gen.StructGen.get_struct_sha1(class_name)
looked_up_ty: llvmlite.LLVMType | t.CPtr = self._LookupMethodRetTyFromTextLL(
pool, cls_sha1_rt, class_name, method_name)
if looked_up_ty is not None:
call_ret_ty = looked_up_ty
else:
# 精确查找:vpi stub 返回注解缓存(方法定义处,不硬编码白名单)
vpi_ret_ty: llvmlite.LLVMType | t.CPtr = self._lookup_method_ret_ty_via_vpi(
pool, cls_sha1_rt, class_name, method_name)
if vpi_ret_ty is not None:
call_ret_ty = vpi_ret_ty
else:
# Phase A 依赖未就绪(cls_sha1_rt None / 定义模块 text.ll 未生成):
# 标记 pending 下遍重译(对齐 _translate_method_call L4783-4790),
# 绝不 fail-fast 中断多遍收敛;真实错误由收敛检查兜底。
if cls_sha1_rt is None \
or self._dep_text_ll_exists(pool, cls_sha1_rt) == 0:
if trans is not None:
trans._deps_pending = 1
# 依赖未就绪:保持默认 i32(build_call(Void) 返回 None
# 会破坏表达式翻译;pending 文件本遍不写盘,下遍重译)
call_ret_ty = llvmlite.Int32(pool)
else:
call_ret_ty = self._fail_method_ret_ty(method_name)
# 参数类型对齐:按目标函数声明的参数类型转换实参(与 _translate_method_call
# 一致)。例如 from_long(10) 的 i32 字面量 → i64 形参(v: t.CLong),
# 不转换则 call(i32) 与 declare(i64) 不匹配,llc 报参数类型错误。
# 目标函数优先用已找到的 found_func,否则按 mangled 调用名查模块 declare。
tgt_func_pc: llvmlite.Function | t.CPtr = found_func
if tgt_func_pc is None:
tgt_func_pc = self.find_func_in_module(mod, call_name)
if tgt_func_pc is not None:
prev_pc: llvmlite.Value | t.CPtr = None
cur_arg_pc: llvmlite.Value | t.CPtr = call_head
cur_param_pc: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(tgt_func_pc)
while cur_arg_pc is not None and cur_param_pc is not None:
param_ty_pc: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param_pc)
if param_ty_pc is not None and cur_arg_pc.Ty is not None:
coerced_pc: llvmlite.Value | t.CPtr = self.Gen.ExprGenBase.coerce_to_type(
builder, cur_arg_pc, param_ty_pc)
if coerced_pc is not None and coerced_pc != cur_arg_pc:
# 保持链表完整性:新 Value 继承原节点的 Next,前驱指向新节点
llvmlite.value_set_next(coerced_pc, cur_arg_pc.Next)
if prev_pc is None:
call_head = coerced_pc
else:
llvmlite.value_set_next(prev_pc, coerced_pc)
cur_arg_pc = coerced_pc
prev_pc = cur_arg_pc
cur_arg_pc = cur_arg_pc.Next
cur_param_pc = llvmlite.param_get_next(cur_param_pc)
# 确保 declare 存在,然后调用
self._ensure_method_declare(pool, mod, call_name, call_ret_ty, call_head, call_count)
return llvmlite.build_call(builder, call_name, call_head, call_count, call_ret_ty, 0)
# ============================================================
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
#
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
# 供属性访问/赋值/删除识别 property 时使用。
# ============================================================
# ============================================================
def _resolve_obj_class_name(self, pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr,
obj_node: ast.AST | t.CPtr) -> str:
"""解析对象表达式的类名(短名),失败返回 None"""
if pool is None or trans is None or obj_node is None:
return None
if obj_node.kind() == ast.ASTKind.Name:
obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(obj_node)
if obj_nm.id is not None:
var_entry: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, obj_nm.id)
if var_entry is not None and var_entry.AnnotClassName is not None:
annot_val: str = var_entry.AnnotClassName
dot_ptr: str = string.strrchr(annot_val, '.')
if dot_ptr is not None:
return dot_ptr + 1
return annot_val
return None
# ============================================================
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
#
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
# ============================================================
# ============================================================
def _try_property_getter_attr(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
at_node: ast.Attribute | t.CPtr,
obj_ptr: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr,
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None
fallback_class_name: 对象表达式非 Name 时从 LLVM 类型解析出的类名兜底。
"""
if at_node is None or at_node.attr is None or obj_ptr is None or trans is None:
return None
class_name: str = self._resolve_obj_class_name(pool, trans, at_node.value)
if class_name is None:
class_name = fallback_class_name
if class_name is None:
return None
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, at_node.attr)
if meta & GenTypes.META_PROP_GETTER == 0:
return None
# 单参数调用: obj → getter
llvmlite.value_set_next(obj_ptr, None)
return self._translate_property_call(
pool, builder, mod, class_name, at_node.attr, obj_ptr, 1, trans)
# ============================================================
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
#
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
# ============================================================
# ============================================================
def _try_property_setter(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
rhs_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property setter 赋值,返回 1=已处理(生成调用)"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if target_attr is None or target_attr.attr is None or rhs_val is None:
return 0
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
if class_name is None:
return 0
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
if meta & GenTypes.META_PROP_SETTER == 0:
return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None:
return 0
# 构建参数链表: obj → rhs
llvmlite.value_set_next(obj_val, None)
llvmlite.value_set_next(rhs_val, None)
llvmlite.value_set_next(obj_val, rhs_val)
# setter 函数名带 $set 后缀
setter_name_buf: str = pool.alloc(128)
if setter_name_buf is None:
return 0
viperlib.snprintf(setter_name_buf, 128, "%s$set", target_attr.attr)
self._translate_property_call(pool, builder, mod, class_name,
setter_name_buf, obj_val, 2, trans)
return 1
# ============================================================
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
#
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
# ============================================================
# ============================================================
def _try_property_deleter(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property deleter 删除,返回 1=已处理(生成调用)"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if target_attr is None or target_attr.attr is None:
return 0
class_name: str = self._resolve_obj_class_name(pool, trans, target_attr.value)
if class_name is None:
return 0
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, target_attr.attr)
if meta & GenTypes.META_PROP_DELETER == 0:
return 0
# 翻译对象值(self 参数)
obj_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, target_attr.value, None, 0, trans)
if obj_val is None:
return 0
llvmlite.value_set_next(obj_val, None)
# deleter 函数名带 $del 后缀
del_name_buf: str = pool.alloc(128)
if del_name_buf is None:
return 0
viperlib.snprintf(del_name_buf, 128, "%s$del", target_attr.attr)
self._translate_property_call(pool, builder, mod, class_name,
del_name_buf, obj_val, 1, trans)
return 1
# ============================================================
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
#
# @staticmethod: 直接 call Class.method(args...),无 self
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
# ============================================================
# ============================================================
def _translate_static_class_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None"""
if pool is None or builder is None or mod is None or trans is None:
return None
if class_name is None or method_name is None or cl is None:
return None
meta: int = self.Gen.ClassGenBase.lookup_method_meta(class_name, method_name)
is_static: int = 0
is_class: int = 0
if meta & GenTypes.META_STATIC != 0:
is_static = 1
if meta & GenTypes.META_CLASS != 0:
is_class = 1
if is_static == 0 and is_class == 0:
return None
# 构建参数链表
head: llvmlite.Value | t.CPtr = None
total_count: int = 0
# @classmethod: 插入栈上分配的类实例指针作为 cls 参数
if is_class != 0:
struct_ty_cc: llvmlite.LLVMType | t.CPtr = self.Gen.StructGen.get_struct_type(class_name)
if struct_ty_cc is None:
return None
cls_ptr: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty_cc)
if cls_ptr is None:
return None
llvmlite.value_set_next(cls_ptr, None)
head = cls_ptr
total_count = 1
# 翻译调用参数
cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args
can: t.CSizeT = 0
if cargs is not None:
can = len(cargs)
tail: llvmlite.Value | t.CPtr = head
for ai in range(can):
arg_node: ast.AST | t.CPtr = cargs.get(ai)
if arg_node is None:
continue
arg_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, arg_node, None, 0, trans)
if arg_val is None:
continue
llvmlite.value_set_next(arg_val, None)
if head is None:
head = arg_val
tail = arg_val
else:
llvmlite.value_set_next(tail, arg_val)
tail = arg_val
total_count += 1
# 零参 @staticmethod(如 PyListObj.new()):head 保持 None 是合法的
# 无参调用,照常走 _translate_property_call(SHA1 前缀名 + 精确返回类型)。
# 若此处 return None,调用方回退通用路径把方法名当裸函数解析,生成
# call i32 @new() → 链接 undefined reference(CPythonTest 根因)。
# @classmethod 恒有 cls_ptr(head 非 None),不受影响。
return self._translate_property_call(pool, builder, mod, class_name,
method_name, head, total_count, trans)
# ============================================================
# _is_list_builtin_method - 判断是否是 list 泛型内置容器方法
#
# list[T] 是内置泛型容器(_list.vp),其方法(append/get/set/pop/clear/
# __iter__/__len__/__getitem__/__setitem__)由 translate_call 的 list
# 内置分支内联 GEP 处理,不注册为方法函数。若 obj.method() 检测把
# list 特化 struct(如 list[AST | CPtr])误当普通结构体走
# _translate_method_call,会查不到 append 返回类型 → fail-fast
# (NewAstTest body.append 根因)。此判断用于跳过 method_call 路径。
#
# 返回: 1=list 内置方法(应落到 list 内置分支),0=普通方法
# ============================================================
# ============================================================
def _is_list_builtin_method(self, class_name: str,
method_name: str) -> int:
"""判断 (class_name, method_name) 是否是 list 泛型内置方法"""
if class_name is None or method_name is None:
return 0
# 类名必须以 "list" 开头(list / list[AST | CPtr] 特化名)
if string.strncmp(class_name, "list", 4) != 0:
return 0
# 方法名必须是 list 内置方法集合
if string.strcmp(method_name, "append") == 0: return 1
if string.strcmp(method_name, "get") == 0: return 1
if string.strcmp(method_name, "set") == 0: return 1
if string.strcmp(method_name, "pop") == 0: return 1
if string.strcmp(method_name, "clear") == 0: return 1
if string.strcmp(method_name, "__iter__") == 0: return 1
if string.strcmp(method_name, "__len__") == 0: return 1
if string.strcmp(method_name, "__getitem__") == 0: return 1
if string.strcmp(method_name, "__setitem__") == 0: return 1
return 0
+325 -333
View File
@@ -1,334 +1,326 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenVa - CallGenMixin 拆分(阶段 B):va_arg 变长参数(start/arg/end / 变长调用提升)
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenVa(CallGenBase.CallGenBase):
"""va_arg 变长参数(start/arg/end / 变长调用提升)"""
# ============================================================
# _func_has_eh_params - 被调函数签名是否含 try-except EH 输出参数
#
# EH 参数(%__eh_msg_out__/__eh_code_out__)由 translate_function_def/
# _translate_method 在含 raise 的函数签名末尾注入(main 除外)。
# ============================================================
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
arg_node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""获取 va_list 变量的 alloca 指针(不 load)
va_arg/va_start/va_end 需要的是 va_list 对象的地址(alloca 指针),
而非 va_list 的值。若 arg_node 是 Name,查符号表获取 alloca;
否则用 translate_value 翻译(调用者负责确保传入的是指针)。
"""
if arg_node is None:
return None
# Name 节点:直接查符号表获取 alloca 指针(不 load)
if arg_node.kind() == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg_node)
if nm.id is not None:
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
if alloca is not None:
return alloca
# 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况)
return HandlesExpr.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans)
def _resolve_va_arg_type(self, pool: memhub.MemBuddy | t.CPtr,
type_node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""解析 va_arg/arg 的类型参数为 LLVMType
支持的类型表达式:
t.CInt / t.CInt32T → i32
t.CInt64T → i64
t.CDouble → double
t.CPtr / str → i8*
str / bytes → i8*
无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32)
"""
if type_node is None:
return llvmlite.Int32(pool)
# 使用 HandlesType.resolve_annotation_type 解析类型表达式
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
pool, type_node, trans._imported_modules, trans._from_imports, trans)
if resolved is not None:
return resolved
# 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位)
HandlesType.fatal_error(type_node, "va_arg 类型解析失败", "TypeError")
return llvmlite.Int32(pool)
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>
生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm)
# 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址;
# 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, ap_node, None, 0, trans)
if ap_val is None:
return llvmlite.const_int32(pool, 0)
ap_ptr: llvmlite.Value | t.CPtr = ap_val
# 第二个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if can >= 2:
type_node: ast.AST | t.CPtr = cargs.get(1)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(对齐 TPC emit_va_arg L72-73)
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
abits_va: int = HandlesExpr.get_llvm_type_bits(arg_ty)
if abits_va != 0 and abits_va < 64:
read_ty = llvmlite.Int64(pool)
# 生成 va_arg 指令
return llvmlite.build_va_arg(builder, ap_ptr, read_ty)
def _translate_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>
使用当前函数的隐式 va_list(trans._va_list_ptr),
简化 *args 函数体内的 va_arg 调用。
"""
if trans._va_list_ptr is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if can >= 1 and cargs is not None:
type_node: ast.AST | t.CPtr = cargs.get(0)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(与 _translate_va_arg_sugar 一致)
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
abits_arg: int = HandlesExpr.get_llvm_type_bits(arg_ty)
if abits_arg != 0 and abits_arg < 64:
read_ty = llvmlite.Int64(pool)
# 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址)
return llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
def _translate_va_start_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)
初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_start 接受 i8*)
i8_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_vs)
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
void_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
return llvmlite.const_int32(pool, 0)
def _translate_va_end_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_end(ap) → call void @llvm.va_end(i8* %ap)
清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_end 接受 i8*)
i8_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_ve)
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
void_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
return llvmlite.const_int32(pool, 0)
def _get_func_fixed_param_count(self, func: llvmlite.Function | t.CPtr) -> int:
"""获取函数的固定参数数量(遍历 Params 链表)"""
if func is None:
return 0
count: int = 0
param: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
while param is not None:
count += 1
param = llvmlite.param_get_next(param)
return count
def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
call_name: str,
head: llvmlite.Value | t.CPtr,
can: t.CSizeT,
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
self_offset: int = 0,
trans: HT.Translator | t.CPtr = None) -> int:
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升
返回: is_variadic (1=变长调用, 0=普通调用)
副作用: 修改 head 链表中超过固定参数数量的节点(C ABI 提升)
arg_nodes: 实参 AST 链表(不含 self),用于 i8/i16 提升的无符号性判断
self_offset: Value 链中 self 占用的偏移(方法调用=1,普通函数=0)
trans: 供 _node_type_unsigned 查询变量注解
"""
if mod is None or call_name is None or head is None:
return 0
# 查找函数对象
func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, call_name)
if func is None:
return 0
if func.IsVarArg != 1:
return 0
# 获取固定参数数量
fixed_count: int = self._get_func_fixed_param_count(func)
# 无变长参数(实参数量 <= 固定参数数量),仍需 is_variadic=1
if can <= fixed_count:
return 1
# 遍历到第 fixed_count 个节点(固定参数的最后一个)
cur: llvmlite.Value | t.CPtr = head
prev: llvmlite.Value | t.CPtr = None
idx: int = 0
while cur is not None and idx < fixed_count:
prev = cur
cur = cur.Next
idx += 1
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
# 对变长参数进行 C ABI 提升
i32_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
double_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
v_idx: int = fixed_count
while cur is not None:
next_node: llvmlite.Value | t.CPtr = cur.Next
promoted: llvmlite.Value | t.CPtr = cur
# C ABI integer promotion: i8/i16 → i32
arg_bits: int = HandlesExpr.get_llvm_type_bits(cur.Ty)
if arg_bits != 0 and arg_bits < 32:
# 无符号整型(t.CUInt8T/CUInt16T 等)→ zext;有符号/未知 → sext。
# 修复: printf("%02x", buf[i]) 中 buf[i] 是 CUInt8T,sext 得
# 0xFFFFFFF3 打印 fffffff3(哈希摘要输出垃圾),应 zext 得 0xF3。
is_u_va: int = 0
if arg_nodes is not None and trans is not None:
ast_idx_va: int = v_idx - self_offset
if ast_idx_va >= 0 and ast_idx_va < len(arg_nodes):
an_va: ast.AST | t.CPtr = arg_nodes.get(ast_idx_va)
if an_va is not None:
if HandlesExpr._node_type_unsigned(pool, an_va, trans) != 0:
is_u_va = 1
if is_u_va != 0:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
else:
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
# "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略),
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
if HandlesExpr.get_llvm_type_bits(cur.Ty) == 8:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
else:
promoted = HandlesExpr.coerce_to_type(builder, cur, i32_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
if prev is not None:
prev.Next = promoted
# C ABI float promotion: float → double
arg_fbits: int = HandlesExpr.get_llvm_float_bits(promoted.Ty)
if arg_fbits != 0 and arg_fbits < 64:
promoted = HandlesExpr.coerce_to_type(builder, promoted, double_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
if prev is not None:
prev.Next = promoted
prev = promoted
cur = next_node
v_idx += 1
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenVa - CallGenMixin 拆分(阶段 B):va_arg 变长参数(start/arg/end / 变长调用提升)
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenVa(CallGenBase.CallGenBase):
"""va_arg 变长参数(start/arg/end / 变长调用提升)"""
# ============================================================
# _func_has_eh_params - 被调函数签名是否含 try-except EH 输出参数
#
# EH 参数(%__eh_msg_out__/__eh_code_out__)由 translate_function_def/
# _translate_method 在含 raise 的函数签名末尾注入(main 除外)。
# ============================================================
def _va_arg_get_alloca_ptr(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
arg_node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""获取 va_list 变量的 alloca 指针(不 load)
va_arg/va_start/va_end 需要的是 va_list 对象的地址(alloca 指针),
而非 va_list 的值。若 arg_node 是 Name,查符号表获取 alloca;
否则用 translate_value 翻译(调用者负责确保传入的是指针)。
"""
if arg_node is None:
return None
# Name 节点:直接查符号表获取 alloca 指针(不 load)
if arg_node.kind() == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg_node)
if nm.id is not None:
alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var(trans.SymTab, nm.id)
if alloca is not None:
return alloca
# 回退:translate_value(可能返回 load 后的值,仅适用于已是指针的情况)
return self.Gen.ExprGen.translate_value(builder, pool, mod, arg_node, funcs_ptr, func_count, trans)
def _resolve_va_arg_type(self, pool: memhub.MemBuddy | t.CPtr,
type_node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""解析 va_arg/arg 的类型参数为 LLVMType
支持的类型表达式:
t.CInt / t.CInt32T → i32
t.CInt64T → i64
t.CDouble → double
t.CPtr / str → i8*
str / bytes → i8*
无类型参数时默认 i32(vsnprintf 中 va_arg(ap) 常用于读取 i32)
"""
if type_node is None:
return llvmlite.Int32(pool)
# 使用 HandlesType.resolve_annotation_type 解析类型表达式
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, type_node, trans._imported_modules, trans._from_imports, trans)
if resolved is not None:
return resolved
# 类型节点存在但解析失败:fail-fast,绝不回退 i32(会按错宽度读变参槽位)
self.Gen.TypeGenErr.fatal_error(type_node, "va_arg 类型解析失败", "TypeError")
return llvmlite.Int32(pool)
def _translate_va_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>
生成 LLVM va_arg 指令,从 va_list 读取下一个变长参数。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list(求值为 i8* 地址值,对齐 TPC _HandleVaArgLlvm)
# 当前函数 *args:translate_value 经 vararg 名映射直接返回 va_list 缓冲区地址;
# 转发场景(sprintf → vsnprintf 的 ap 参数):translate_value load 参数得到地址值。
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_val: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(
builder, pool, mod, ap_node, None, 0, trans)
if ap_val is None:
return llvmlite.const_int32(pool, 0)
ap_ptr: llvmlite.Value | t.CPtr = ap_val
# 第二个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if can >= 2:
type_node: ast.AST | t.CPtr = cargs.get(1)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(对齐 TPC emit_va_arg L72-73)
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
abits_va: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
if abits_va != 0 and abits_va < 64:
read_ty = llvmlite.Int64(pool)
# 生成 va_arg 指令
return llvmlite.build_va_arg(builder, ap_ptr, read_ty)
def _translate_arg_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>
使用当前函数的隐式 va_list(trans._va_list_ptr),
简化 *args 函数体内的 va_arg 调用。
"""
if trans._va_list_ptr is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:目标类型(可选,默认 i32)
arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
if can >= 1 and cargs is not None:
type_node: ast.AST | t.CPtr = cargs.get(0)
arg_ty = self._resolve_va_arg_type(pool, type_node, trans)
# Win64 变参槽位为 8 字节:<64 位整数按 i64 读取(与 _translate_va_arg_sugar 一致)
read_ty: llvmlite.LLVMType | t.CPtr = arg_ty
abits_arg: int = self.Gen.ExprGenBase.get_llvm_type_bits(arg_ty)
if abits_arg != 0 and abits_arg < 64:
read_ty = llvmlite.Int64(pool)
# 生成 va_arg 指令(使用 trans._va_list_ptr 作为 va_list 地址)
return llvmlite.build_va_arg(builder, trans._va_list_ptr, read_ty)
def _translate_va_start_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)
初始化 va_list。第二个参数 last_arg 在 LLVM intrinsic 中不使用(C 宏兼容)。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_start 接受 i8*)
i8_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_vs)
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_vs)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
void_ty_vs: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_start", ap_i8, 1, void_ty_vs, 0)
return llvmlite.const_int32(pool, 0)
def _translate_va_end_sugar(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_end(ap) → call void @llvm.va_end(i8* %ap)
清理 va_list。在大多数平台上是 no-op,但调用它是良好的 C ABI 习惯。
"""
if can == 0 or cargs is None:
return llvmlite.const_int32(pool, 0)
# 第一个参数:va_list 指针(获取 alloca,不 load)
ap_node: ast.AST | t.CPtr = cargs.get(0)
ap_ptr: llvmlite.Value | t.CPtr = self._va_arg_get_alloca_ptr(
pool, builder, mod, ap_node, funcs_ptr, func_count, trans)
if ap_ptr is None:
return llvmlite.const_int32(pool, 0)
# bitcast 到 i8*(@llvm.va_end 接受 i8*)
i8_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_ve)
ap_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ap_ptr, i8_ptr_ty_ve)
if ap_i8 is None:
return llvmlite.const_int32(pool, 0)
void_ty_ve: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool)
llvmlite.build_call(builder, "llvm.va_end", ap_i8, 1, void_ty_ve, 0)
return llvmlite.const_int32(pool, 0)
def _get_func_fixed_param_count(self, func: llvmlite.Function | t.CPtr) -> int:
"""获取函数的固定参数数量(遍历 Params 链表)"""
if func is None:
return 0
count: int = 0
param: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func)
while param is not None:
count += 1
param = llvmlite.param_get_next(param)
return count
def _check_and_promote_variadic_call(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
call_name: str,
head: llvmlite.Value | t.CPtr,
can: t.CSizeT,
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
self_offset: int = 0,
trans: HT.Translator | t.CPtr = None) -> int:
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升
返回: is_variadic (1=变长调用, 0=普通调用)
副作用: 修改 head 链表中超过固定参数数量的节点(C ABI 提升)
arg_nodes: 实参 AST 链表(不含 self),用于 i8/i16 提升的无符号性判断
self_offset: Value 链中 self 占用的偏移(方法调用=1,普通函数=0)
trans: 供 _node_type_unsigned 查询变量注解
"""
if mod is None or call_name is None or head is None:
return 0
# 查找函数对象
func: llvmlite.Function | t.CPtr = self.find_func_in_module(mod, call_name)
if func is None:
return 0
if func.IsVarArg != 1:
return 0
# 获取固定参数数量
fixed_count: int = self._get_func_fixed_param_count(func)
# 无变长参数(实参数量 <= 固定参数数量),仍需 is_variadic=1
if can <= fixed_count:
return 1
# 遍历到第 fixed_count 个节点(固定参数的最后一个)
cur: llvmlite.Value | t.CPtr = head
prev: llvmlite.Value | t.CPtr = None
idx: int = 0
while cur is not None and idx < fixed_count:
prev = cur
cur = cur.Next
idx += 1
# cur 指向第 fixed_count+1 个节点(第一个变长参数)
# 对变长参数进行 C ABI 提升
i32_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
double_ty_promote: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
v_idx: int = fixed_count
while cur is not None:
next_node: llvmlite.Value | t.CPtr = cur.Next
promoted: llvmlite.Value | t.CPtr = cur
# C ABI integer promotion: i8/i16 → i32
arg_bits: int = self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty)
if arg_bits != 0 and arg_bits < 32:
# 无符号整型(t.CUInt8T/CUInt16T 等)→ zext;有符号/未知 → sext。
# 修复: printf("%02x", buf[i]) 中 buf[i] 是 CUInt8T,sext 得
# 0xFFFFFFF3 打印 fffffff3(哈希摘要输出垃圾),应 zext 得 0xF3。
is_u_va: int = 0
if arg_nodes is not None and trans is not None:
ast_idx_va: int = v_idx - self_offset
if ast_idx_va >= 0 and ast_idx_va < len(arg_nodes):
an_va: ast.AST | t.CPtr = arg_nodes.get(ast_idx_va)
if an_va is not None:
if self.Gen.ExprGenOps._node_type_unsigned(pool, an_va, trans) != 0:
is_u_va = 1
if is_u_va != 0:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
else:
# is_u_va 判断失败(arg_nodes/trans 缺失或变量注解查不到)时,
# i8 按系统编程惯例默认 zext(对齐 should_zext_widen 的
# "i8 → zext(系统编程中 i8 几乎总是无符号字节)"策略),
# 否则 printf("%02x", buf[i]) 中 uint8 字节被 sext 成
# 0xFFFFFFF3,哈希摘要输出 ffffffXX 垃圾。
if self.Gen.ExprGenBase.get_llvm_type_bits(cur.Ty) == 8:
promoted = llvmlite.build_zext(builder, cur, i32_ty_promote)
else:
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, cur, i32_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
if prev is not None:
prev.Next = promoted
# C ABI float promotion: float → double
arg_fbits: int = self.Gen.ExprGenBase.get_llvm_float_bits(promoted.Ty)
if arg_fbits != 0 and arg_fbits < 64:
promoted = self.Gen.ExprGenBase.coerce_to_type(builder, promoted, double_ty_promote, None)
if promoted is not None:
promoted.Next = next_node
if prev is not None:
prev.Next = promoted
prev = promoted
cur = next_node
v_idx += 1
return 1
+230 -241
View File
@@ -1,242 +1,231 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallHandle as ExprCallHandle
# ============================================================
# CallGenVt - CallGenMixin 拆分(阶段 B):vtable 槽位写入
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenVt(CallGenBase.CallGenBase):
"""vtable 槽位写入"""
# ============================================================
# _write_vtable_slot / _write_vtable_attr — vtable 方法槽位直接写入
#
# serial0_file.open = serial0_open(devfs 驱动注册模式):把模块级函数
# 指针写入对象 vtable 的方法槽位。vtable 方法不是数据字段(FieldEntry),
# get_attribute_ptr 查不到 → 此前 fatal_error "属性写入失败"。
# 对齐 TPC HandlesAssign.py L905-949 的写时复制:
# 对象 vtable 仍指向类默认 vtable 时,先复制一份(internal 全局 +
# llvm.memcpy)并让对象指向副本,再 GEP method_index 槽位 store
# 函数指针(i8*)。多次写入互不覆盖(第二次起 vtable 已非默认,
# 跳过复制直接写槽位)。
# ============================================================
# ============================================================
def _write_vtable_slot(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
obj_ptr: llvmlite.Value | t.CPtr,
class_name: str,
method_index: int,
func_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""生成 vtable 槽位写入(写时复制),成功返回 1"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if obj_ptr is None or class_name is None or func_val is None:
return 0
if method_index < 0 or trans._cur_func is None:
return 0
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None:
return 0
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
return 0
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
if i8_ptr_ptr_ty is None:
return 0
method_count: int = HandlesStruct.get_vtable_method_count(class_name)
if method_count <= 0:
return 0
# 构造 vtable 类型 { i8*, i8*, ... }
vt_first: llvmlite.ParamNode | t.CPtr = None
vt_prev: llvmlite.ParamNode | t.CPtr = None
for vi in range(method_count):
pn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
if pn is None:
continue
if vt_first is None:
vt_first = pn
if vt_prev is not None:
llvmlite.paramnode_set_next(vt_prev, pn)
vt_prev = pn
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first, method_count, None)
if vtable_ty is None:
return 0
# 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段)
vtable_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, obj_ptr, i8_ptr_ptr_ty)
if vtable_slot is None:
return 0
vtable_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty, vtable_slot)
if vtable_ptr is None:
return 0
# 类默认 vtable 地址(比较用)
class_vt: llvmlite.Value | t.CPtr = ExprCallHandle._make_vtable_ref_i8(
pool, builder, mod, class_name, trans)
if class_vt is None:
return 0
cmp_vt: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
builder, llvmlite.ICMP_EQ, vtable_ptr, class_vt)
if cmp_vt is None:
return 0
# 块名唯一化(create_block 不自动编号;同函数多次 vtable 写入(如
# devfs open/close/read/write 连续赋值)同名 label 冲突)
vtc3: int = trans._label_counter
trans._label_counter = vtc3 + 1
vt_bb_buf3: str = pool.alloc(64)
if vt_bb_buf3 is None:
return 0
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
vt_copy_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, trans._cur_func, vt_bb_buf3)
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
vt_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, trans._cur_func, vt_bb_buf3)
if vt_copy_bb is None or vt_skip_bb is None:
return 0
llvmlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
# copy 块:创建 internal 副本全局(zeroinit)+ memcpy + 对象指向副本
llvmlite.position_at_end(builder, vt_copy_bb)
vtc: int = trans._label_counter
trans._label_counter = vtc + 1
vcopy_buf: str = pool.alloc(256)
if vcopy_buf is not None:
viperlib.snprintf(vcopy_buf, 256, "%s.vtable.copy.%d", class_name, vtc)
vcopy_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
pool, vcopy_buf, vtable_ty)
if vcopy_gv is not None:
llvmlite.module_add_global(mod, vcopy_gv)
vcopy_gv.Linkage = None
vcopy_gv.Initializer = "zeroinitializer"
vcopy_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
pool, llvmlite.Ptr(pool, vtable_ty), vcopy_buf)
if vcopy_ref is not None:
vcopy_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, vcopy_ref, i8_ptr_ty)
if vcopy_i8 is not None:
vt_size: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
pool, llvmlite.Int64(pool), method_count * 8, "vtsz")
if vt_size is not None:
ExprCallBase._emit_llvm_memcpy_intrinsic(
pool, builder, mod, vcopy_i8, class_vt, vt_size)
llvmlite.build_store(builder, vcopy_i8, vtable_slot)
llvmlite.build_br(builder, vt_skip_bb)
# skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*)
llvmlite.position_at_end(builder, vt_skip_bb)
vt_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty, vtable_slot)
if vt_ptr2 is None:
return 0
vt_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, vt_ptr2, llvmlite.Ptr(pool, vtable_ty))
if vt_typed is None:
return 0
vt_slotp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
if vt_slotp is None:
return 0
fptr_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, func_val, i8_ptr_ty)
if fptr_i8 is not None:
llvmlite.build_store(builder, fptr_i8, vt_slotp)
return 1
def _write_vtable_attr(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
rhs_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""属性写入 obj.method = func:检测 vtable 方法并生成槽位写入(成功返回 1)"""
if node is None or builder is None or pool is None or mod is None:
return 0
if rhs_val is None or trans is None:
return 0
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
if at is None or at.value is None or at.attr is None:
return 0
# 解析类名(AnnotClassName;去模块前缀)
class_nm_v: str = None
if at.value.kind() == ast.ASTKind.Name:
nm_v: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if nm_v.id is not None:
ve_v: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
trans.SymTab, nm_v.id)
if ve_v is not None:
class_nm_v = ve_v.AnnotClassName
elif at.value.kind() == ast.ASTKind.Attribute:
# 跨 Mixin:_resolve_attr_field_class 定义在 ExprGenMixin,经 gen 单例调用
import lib.core.Gen.Generator as Generator
g_vta: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(
t.CVoid(HandlesExpr._g_gen, t.CPtr))
if g_vta is not None:
class_nm_v = g_vta._resolve_attr_field_class(pool, trans, at.value)
if class_nm_v is None:
return 0
fd_dot_v: str = string.strrchr(class_nm_v, '.')
if fd_dot_v is not None:
class_nm_v = fd_dot_v + 1
if HandlesStruct.get_struct_type(class_nm_v) is None:
return 0
vm_idx_v: int = HandlesStruct.get_vtable_method_index(class_nm_v, at.attr)
if vm_idx_v < 0:
return 0
# 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca)
obj_ptr_v: llvmlite.Value | t.CPtr = None
if at.value.kind() == ast.ASTKind.Name:
obj_ptr_v = HandlesVar.lookup_var(
trans.SymTab, ((ast.Name | t.CPtr)(at.value)).id)
else:
obj_ptr_v = HandlesExpr.translate_value(
builder, pool, mod, at.value, None, 0, trans)
if obj_ptr_v is None or obj_ptr_v.Ty is None:
return 0
# X|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针
match obj_ptr_v.Ty:
case llvmlite.LLVMType.Ptr(inner_v):
match inner_v:
case llvmlite.LLVMType.Ptr(_):
obj_ptr_v = llvmlite.build_load(builder, inner_v, obj_ptr_v)
case _:
pass
case _:
pass
if obj_ptr_v is None:
return 0
return self._write_vtable_slot(
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Gen.ExprGenAttr as ExprGenAttr
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.CallGenBase as CallGenBase
# ============================================================
# CallGenVt - CallGenMixin 拆分(阶段 B):vtable 槽位写入
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class CallGenVt(CallGenBase.CallGenBase):
"""vtable 槽位写入"""
# ============================================================
# _write_vtable_slot / _write_vtable_attr — vtable 方法槽位直接写入
#
# serial0_file.open = serial0_open(devfs 驱动注册模式):把模块级函数
# 指针写入对象 vtable 的方法槽位。vtable 方法不是数据字段(FieldEntry),
# get_attribute_ptr 查不到 → 此前 fatal_error "属性写入失败"。
# 对齐 TPC HandlesAssign.py L905-949 的写时复制:
# 对象 vtable 仍指向类默认 vtable 时,先复制一份(internal 全局 +
# llvm.memcpy)并让对象指向副本,再 GEP method_index 槽位 store
# 函数指针(i8*)。多次写入互不覆盖(第二次起 vtable 已非默认,
# 跳过复制直接写槽位)。
# ============================================================
# ============================================================
def _write_vtable_slot(self, pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
obj_ptr: llvmlite.Value | t.CPtr,
class_name: str,
method_index: int,
func_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""生成 vtable 槽位写入(写时复制),成功返回 1"""
if pool is None or builder is None or mod is None or trans is None:
return 0
if obj_ptr is None or class_name is None or func_val is None:
return 0
if method_index < 0 or trans._cur_func is None:
return 0
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None:
return 0
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
return 0
i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty)
if i8_ptr_ptr_ty is None:
return 0
method_count: int = self.Gen.StructGen.get_vtable_method_count(class_name)
if method_count <= 0:
return 0
# 构造 vtable 类型 { i8*, i8*, ... }
vt_first: llvmlite.ParamNode | t.CPtr = None
vt_prev: llvmlite.ParamNode | t.CPtr = None
for vi in range(method_count):
pn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
if pn is None:
continue
if vt_first is None:
vt_first = pn
if vt_prev is not None:
llvmlite.paramnode_set_next(vt_prev, pn)
vt_prev = pn
vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first, method_count, None)
if vtable_ty is None:
return 0
# 对象 vtable 槽位(对象头 → i8**,vtable 指针总是第一个字段)
vtable_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, obj_ptr, i8_ptr_ptr_ty)
if vtable_slot is None:
return 0
vtable_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty, vtable_slot)
if vtable_ptr is None:
return 0
# 类默认 vtable 地址(比较用)
class_vt: llvmlite.Value | t.CPtr = self.Gen.CallGenLeafKit._make_vtable_ref_i8(
pool, builder, mod, class_name, trans)
if class_vt is None:
return 0
cmp_vt: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
builder, llvmlite.ICMP_EQ, vtable_ptr, class_vt)
if cmp_vt is None:
return 0
# 块名唯一化(create_block 不自动编号;同函数多次 vtable 写入(如
# devfs open/close/read/write 连续赋值)同名 label 冲突)
vtc3: int = trans._label_counter
trans._label_counter = vtc3 + 1
vt_bb_buf3: str = pool.alloc(64)
if vt_bb_buf3 is None:
return 0
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
vt_copy_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, trans._cur_func, vt_bb_buf3)
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
vt_skip_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
pool, trans._cur_func, vt_bb_buf3)
if vt_copy_bb is None or vt_skip_bb is None:
return 0
llvmlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
# copy 块:创建 internal 副本全局(zeroinit)+ memcpy + 对象指向副本
llvmlite.position_at_end(builder, vt_copy_bb)
vtc: int = trans._label_counter
trans._label_counter = vtc + 1
vcopy_buf: str = pool.alloc(256)
if vcopy_buf is not None:
viperlib.snprintf(vcopy_buf, 256, "%s.vtable.copy.%d", class_name, vtc)
vcopy_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(
pool, vcopy_buf, vtable_ty)
if vcopy_gv is not None:
llvmlite.module_add_global(mod, vcopy_gv)
vcopy_gv.Linkage = None
vcopy_gv.Initializer = "zeroinitializer"
vcopy_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
pool, llvmlite.Ptr(pool, vtable_ty), vcopy_buf)
if vcopy_ref is not None:
vcopy_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, vcopy_ref, i8_ptr_ty)
if vcopy_i8 is not None:
vt_size: llvmlite.Value | t.CPtr = llvmlite.ConstInt(
pool, llvmlite.Int64(pool), method_count * 8, "vtsz")
if vt_size is not None:
self.Gen.CallGenLib._emit_llvm_memcpy_intrinsic(
pool, builder, mod, vcopy_i8, class_vt, vt_size)
llvmlite.build_store(builder, vcopy_i8, vtable_slot)
llvmlite.build_br(builder, vt_skip_bb)
# skip 块:reload vtable → GEP 槽位 → store 函数指针(i8*)
llvmlite.position_at_end(builder, vt_skip_bb)
vt_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, i8_ptr_ty, vtable_slot)
if vt_ptr2 is None:
return 0
vt_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, vt_ptr2, llvmlite.Ptr(pool, vtable_ty))
if vt_typed is None:
return 0
vt_slotp: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, vtable_ty, i8_ptr_ty, vt_typed, method_index)
if vt_slotp is None:
return 0
fptr_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
builder, func_val, i8_ptr_ty)
if fptr_i8 is not None:
llvmlite.build_store(builder, fptr_i8, vt_slotp)
return 1
def _write_vtable_attr(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
rhs_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""属性写入 obj.method = func:检测 vtable 方法并生成槽位写入(成功返回 1)"""
if node is None or builder is None or pool is None or mod is None:
return 0
if rhs_val is None or trans is None:
return 0
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
if at is None or at.value is None or at.attr is None:
return 0
# 解析类名(AnnotClassName;去模块前缀)
class_nm_v: str = None
if at.value.kind() == ast.ASTKind.Name:
nm_v: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if nm_v.id is not None:
ve_v: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm_v.id)
if ve_v is not None:
class_nm_v = ve_v.AnnotClassName
elif at.value.kind() == ast.ASTKind.Attribute:
# 跨 Mixin:_resolve_attr_field_class 定义在 ExprGenAttr,经 self.Gen 调用
class_nm_v = self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, at.value)
if class_nm_v is None:
return 0
fd_dot_v: str = string.strrchr(class_nm_v, '.')
if fd_dot_v is not None:
class_nm_v = fd_dot_v + 1
if self.Gen.StructGen.get_struct_type(class_nm_v) is None:
return 0
vm_idx_v: int = self.Gen.StructGen.get_vtable_method_index(class_nm_v, at.attr)
if vm_idx_v < 0:
return 0
# 解析 obj_ptr(对齐 get_attribute_ptr 前半段:Name 直接查 alloca)
obj_ptr_v: llvmlite.Value | t.CPtr = None
if at.value.kind() == ast.ASTKind.Name:
obj_ptr_v = self.Gen.VarGen.lookup_var(
trans.SymTab, ((ast.Name | t.CPtr)(at.value)).id)
else:
obj_ptr_v = self.Gen.ExprGen.translate_value(
builder, pool, mod, at.value, None, 0, trans)
if obj_ptr_v is None or obj_ptr_v.Ty is None:
return 0
# X|t.CPtr 变量(Ptr(Ptr))load 解引用取对象指针
match obj_ptr_v.Ty:
case llvmlite.LLVMType.Ptr(inner_v):
match inner_v:
case llvmlite.LLVMType.Ptr(_):
obj_ptr_v = llvmlite.build_load(builder, inner_v, obj_ptr_v)
case _:
pass
case _:
pass
if obj_ptr_v is None:
return 0
return self._write_vtable_slot(
pool, builder, mod, obj_ptr_v, class_nm_v, vm_idx_v, rhs_val, trans)
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
File diff suppressed because it is too large. Load diff
+25 -32
View File
@@ -1,32 +1,25 @@
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.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.ClassGenBase as ClassGenBase
# ============================================================
# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum
#
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
# ClassGenBase/Enum/Generic/VTable/Def,本文件保留类声明。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenMixin(ClassGenBase.ClassGenBase):
"""类定义处理 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
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.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.ClassGenBase as ClassGenBase
# ============================================================
# ClassGenMixin - 类定义/继承/泛型/vtable/enum/union/renum
#
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
# ClassGenBase/Enum/Generic/VTable/Def,本文件保留类声明。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ClassGenMixin(ClassGenBase.ClassGenBase):
"""类定义处理 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
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
File diff suppressed because it is too large. Load diff
+492 -502
View File
@@ -1,503 +1,493 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
import lib.core.StubMergerStore as StubMergerStore
import lib.core.Handles.ExprCallBase as ExprCallBase
# ============================================================
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,本地副本避免
# 跨模块 CDefine 查找 bug:ExprGenCls(C) 在 ExprGenMixin(M) 之前按
# 文件序编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
# ============================================================
DOC_MAX: t.CDefine = 512
DOC_KEY_SZ: t.CDefine = 192
DOC_VAL_SZ: t.CDefine = 4096
# ============================================================
# ExprGenCls - ExprGenMixin 拆分(阶段 D):类名推断/docstring 登记
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenCls(ExprGenBase.ExprGenBase):
"""类名推断/docstring 登记"""
# ============================================================
# docstring 提取/登记/查找(__doc__ 魔法属性支持)
#
# 预注册阶段(BuildPipeline.TranslateFileGetTrans)扫描所有
# App/includes 文件的 AST,提取函数/类/方法的 docstring 内容
# 登记到全局表(key = "{module_sha1}.{symbol}");__doc__ 属性
# 访问时查表,命中则当前模块内联生成字符串常量(无跨模块 IR
# 符号依赖),未命中返回 null。幂等查重,多遍翻译安全。
# ============================================================
def _extract_docstring_from_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> str:
"""从函数/类体提取 docstring:body[0] 为 Expr(Constant str) 时返回内容"""
if body is None or len(body) == 0:
return None
first: ast.AST | t.CPtr = body.get(0)
if first is None or first.kind() != ast.ASTKind.Expr:
return None
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(first)
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant:
return None
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(ex.value)
if cn is None or cn.const_kind != ast.CONST_STR:
return None
return cn.str_val
def register_docstring(self, module_sha1: str, symbol: str, doc: str) -> None:
"""登记 docstring(key="{module_sha1}.{symbol}"),查重幂等"""
if module_sha1 is None or symbol is None or doc is None:
return
if string.strlen(doc) == 0:
return
if self.DocKeys is None:
self.DocKeys = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_KEY_SZ)
self.DocValues = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_VAL_SZ)
if self.DocKeys is None or self.DocValues is None:
return
string.memset(self.DocKeys, 0, DOC_MAX * DOC_KEY_SZ)
string.memset(self.DocValues, 0, DOC_MAX * DOC_VAL_SZ)
if self.DocCount >= DOC_MAX:
return
ml: t.CSizeT = string.strlen(module_sha1)
sl: t.CSizeT = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
return
string.strcpy(self.DocKeys + self.DocCount * DOC_KEY_SZ, key_buf)
string.strcpy(self.DocValues + self.DocCount * DOC_VAL_SZ, doc)
self.DocCount += 1
stdlib.free(key_buf)
def lookup_docstring(self, module_sha1: str, symbol: str) -> str:
"""查找 docstring 内容(key="{module_sha1}.{symbol}"),未找到返回 None"""
if self.DocKeys is None or module_sha1 is None or symbol is None:
return None
ml: t.CSizeT = string.strlen(module_sha1)
sl: t.CSizeT = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return None
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
return self.DocValues + i * DOC_VAL_SZ
stdlib.free(key_buf)
return None
def extract_module_docstrings(self, tree: ast.AST | t.CPtr, module_sha1: str) -> None:
"""扫描模块 AST:登记模块级函数/类/方法的 docstring(幂等)"""
if tree is None or module_sha1 is None:
return
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is None:
return
cn: t.CSizeT = len(ch)
for ci in range(cn):
child: ast.AST | t.CPtr = ch.get(ci)
if child is None:
continue
kd: int = child.kind()
if kd == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
if fd is not None and fd.name is not None:
fd_body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
fdoc: str = self._extract_docstring_from_body(fd_body)
if fdoc is not None:
self.register_docstring(module_sha1, fd.name, fdoc)
elif kd == ast.ASTKind.ClassDef:
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
if cd is None or cd.name is None:
continue
cd_body0: list[ast.AST | t.CPtr] | t.CPtr = cd.children
cdoc: str = self._extract_docstring_from_body(cd_body0)
if cdoc is not None:
self.register_docstring(module_sha1, cd.name, cdoc)
# 类方法 docstring(key="{ClassName}.{method}")
cd_body: list[ast.AST | t.CPtr] | t.CPtr = cd.children
if cd_body is not None:
cbn: t.CSizeT = len(cd_body)
for mi in range(cbn):
m: ast.AST | t.CPtr = cd_body.get(mi)
if m is None or m.kind() != ast.ASTKind.FunctionDef:
continue
mfd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m)
if mfd is None or mfd.name is None:
continue
mdoc: str = self._extract_docstring_from_body(mfd.children)
if mdoc is not None:
cl_nl: t.CSizeT = string.strlen(cd.name)
mt_nl: t.CSizeT = string.strlen(mfd.name)
sym_buf: bytes = stdlib.malloc(cl_nl + mt_nl + 2)
if sym_buf is not None:
viperlib.snprintf(sym_buf, cl_nl + mt_nl + 2, "%s.%s", cd.name, mfd.name)
self.register_docstring(module_sha1, sym_buf, mdoc)
stdlib.free(sym_buf)
def _resolve_doc_symbol_name(self, trans: HT.Translator | t.CPtr, name_id: str,
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
"""解析 Name 符号的 docstring 归属,写入 out_mod/out_sym,成功返回 1
判定顺序:本地变量(函数变量)→ 结构体类(含跨模块预注册)→ 模块名。
"""
if trans is None or name_id is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
# 1. 本地变量(函数变量/全局变量)
if HandlesVar.lookup_var(trans.SymTab, name_id) is not None:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
# 2. 结构体类(entry.ModuleSha1 区分跨模块预注册的类)
se: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(name_id)
if se is not None:
if se.ModuleSha1 is not None:
string.strcpy(out_mod, se.ModuleSha1)
else:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
# 3. 模块名(模块本身,少见);用 StubMerger 模块级函数(避免
# 跨 Mixin self 调用生成不存在符号)
mod_sha1: str = StubMergerStore.LookupSha1ByModName(name_id)
if mod_sha1 is None:
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id)
if mod_sha1 is not None:
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, name_id)
return 1
# 4. 兜底当前模块
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
def _resolve_doc_symbol_attr(self, trans: HT.Translator | t.CPtr,
at: ast.Attribute | t.CPtr,
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
"""解析嵌套 Attribute 链的 docstring 归属,写入 out_mod/out_sym
支持形态:remote.remote_func / remote.RemoteClass /
remote.RemoteClass.remote_method / LocalClass.local_method 等。
最左 Name 判定:模块名 → 该模块 sha1;变量/类 → 类所属模块 sha1。
"""
if trans is None or at is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
# 收集 Attribute 链(最外层 attr 在前)
DOC_CHAIN_MAX: t.CInt = 8
items: bytes = stdlib.malloc(DOC_CHAIN_MAX * 128)
if items is None:
return 0
n_items: int = 0
cur: ast.AST | t.CPtr = (ast.AST | t.CPtr)(at)
while cur is not None and cur.kind() == ast.ASTKind.Attribute and n_items < DOC_CHAIN_MAX:
cat: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cur)
if cat.attr is None:
break
string.strcpy(items + n_items * 128, cat.attr)
n_items += 1
cur = cat.value
# 最左应为 Name
head_id: str = None
if cur is not None and cur.kind() == ast.ASTKind.Name:
hnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cur)
head_id = hnm.id
if head_id is None:
stdlib.free(items)
return 0
# head 判定:模块名 or 变量/类
is_mod: int = 0
mod_sha1: str = None
if HandlesVar.lookup_var(trans.SymTab, head_id) is None:
mod_sha1 = StubMergerStore.LookupSha1ByModName(head_id)
if mod_sha1 is None:
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id)
if mod_sha1 is not None:
is_mod = 1
if is_mod != 0:
# 模块限定:symbol = items 反转(不含 head_id)
if n_items == 0:
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, head_id)
stdlib.free(items)
return 1
total: t.CSizeT = 0
j: int
for j in range(n_items):
total += string.strlen(items + j * 128) + 1
sym_buf: bytes = stdlib.malloc(total + 1)
if sym_buf is None:
stdlib.free(items)
return 0
sym_buf[0] = '\0'
for j in range(n_items):
if j > 0:
string.strcat(sym_buf, ".")
string.strcat(sym_buf, items + (n_items - 1 - j) * 128)
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, sym_buf)
stdlib.free(sym_buf)
stdlib.free(items)
return 1
# 变量/类:symbol = head_id + '.' + items 反转
total2: t.CSizeT = string.strlen(head_id)
for j in range(n_items):
total2 += string.strlen(items + j * 128) + 1
sym2: bytes = stdlib.malloc(total2 + 1)
if sym2 is None:
stdlib.free(items)
return 0
sym2[0] = '\0'
string.strcat(sym2, head_id)
for j in range(n_items):
string.strcat(sym2, ".")
string.strcat(sym2, items + (n_items - 1 - j) * 128)
se2: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(head_id)
if se2 is not None and se2.ModuleSha1 is not None:
string.strcpy(out_mod, se2.ModuleSha1)
else:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, sym2)
stdlib.free(sym2)
stdlib.free(items)
return 1
# ============================================================
# P3 迁移方法(来自 HandlesExprOps.vp:运算符重载 + 二元运算)
# ============================================================
# ============================================================
# infer_expr_class - 从表达式推断结构体类名(共享推断)
#
# 无注解赋值(HandlesAssign)与方法调用分派(CallGenMixin)共用:
# 联合类型 X|t.CPtr 简化为 Ptr(i8),不含类名,需按表达式结构推断:
# Call → 类实例化(func 为已注册结构体名);func 为 Attribute
# 时是方法调用,经 vpi 返回注解缓存解析返回类名
# Name → 源变量的 AnnotClassName
# BinOp/UnaryOp → lhs 类名 + 存在对应 dunder 方法(返回同类对象)
# Attribute → 字段注解类名(_resolve_attr_field_class)
# 仅采用已注册结构体;无法精确推断返回 None(fail-fast 由调用方暴露)。
# ============================================================
def infer_expr_class(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr) -> str:
"""从表达式推断结构体类名,无法推断返回 None"""
if node is None or trans is None:
return None
k: int = node.kind()
# Call: 类实例化 / 方法调用
if k == ast.ASTKind.Call:
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
if cl is None or cl.func is None:
return None
if cl.func.kind() == ast.ASTKind.Name:
cand: str = ((ast.Name | t.CPtr)(cl.func)).id
if cand is None:
return None
if HandlesStruct.find_struct(cand) is not None:
return cand
return None
if cl.func.kind() == ast.ASTKind.Attribute:
# 方法调用 a.cross(b):vpi 返回注解缓存精确解析返回类名
# (方法可返回非同类对象,如 Transform.world_position → 'Vec3')。
ca: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if ca is None or ca.attr is None or ca.value is None:
return None
obj_cls: str = self.infer_expr_class(pool, mod, ca.value, trans)
if obj_cls is None:
return None
if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0:
return None
cls_sha1: str = HandlesStruct.get_struct_sha1(obj_cls)
if cls_sha1 is None and trans.ModuleSha1 is not None:
cls_sha1 = trans.ModuleSha1
ret_cls: str = None
if cls_sha1 is not None:
import lib.StubGen.VpiReader as VpiReader
temp_dir: str = None
# 跨 Mixin 不能 self 访问 Generator 的 TempDir 字段(字段按
# 声明类隔离),经全局单例获取(同 HandlesAssign 模式)
import lib.core.Gen.Generator as Generator
g2: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(
t.CVoid(HandlesExpr._g_gen, t.CPtr))
if g2 is not None and g2.TempDir is not None:
temp_dir = g2.TempDir
if temp_dir is not None:
VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir)
annot_ret: str = VpiReader._lookup_vpi_ret_annot(
cls_sha1, obj_cls, ca.attr)
if annot_ret is not None:
ret_cls = self._extract_annot_class_name(pool, annot_ret)
return ret_cls
return None
# Name: 源变量注解
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
if nm is None or nm.id is None:
return None
ve: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
trans.SymTab, nm.id)
if ve is None:
return None
acn_n: str = ve.AnnotClassName
if acn_n is None:
return None
# 去模块前缀:json.JsonValue → JsonValue。AnnotClassName 可能带
# 模块限定(extract_class_name_from_annotation 的 Attribute 分支返回
# "memhub.MemBuddy" 形式),而 find_struct/_cls_has_dunder/
# get_struct_sha1 查找都用裸类名(struct 注册名)。泛型名
# (list[str] 含 '[')不截断(方括号内可能有点号)。
acn_dot_n: str = string.strrchr(acn_n, 46)
if acn_dot_n is not None and string.strchr(acn_n, 91) is None:
acn_n = acn_dot_n + 1
return acn_n
# BinOp/UnaryOp: 运算符重载返回同类对象
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
if bop is None or bop.left is None:
return None
dunder: str = HandlesExpr._binop_to_dunder(bop.op)
if dunder is None:
return None
lhs_cls: str = self.infer_expr_class(pool, mod, bop.left, trans)
if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0:
return None
return lhs_cls
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
if uop is None or uop.operand is None:
return None
dunder: str = HandlesExpr._unaryop_to_dunder(uop.op)
if dunder is None:
return None
opr_cls: str = self.infer_expr_class(pool, mod, uop.operand, trans)
if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0:
return None
return opr_cls
# Attribute: 字段注解类名(属性链递归,如 p = r.origin)
if k == ast.ASTKind.Attribute:
return HandlesExpr._resolve_attr_field_class(pool, trans, node)
return None
# ============================================================
# _cls_has_dunder - 检查类(含继承链)是否存在 dunder/方法
#
# 与 try_operator_overload 的查找一致:当前模块内定义或跨模块类有
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
# 避免把原生运算误标为类类型。
# ============================================================
def _cls_has_dunder(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str, dunder: str) -> int:
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
if class_name is None or dunder is None or mod is None:
return 0
lookup_name: str = pool.alloc(128)
if lookup_name is None:
return 0
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder)
if ExprCallBase.find_func_in_module(mod, lookup_name) is not None:
return 1
# 继承链祖先查找
mro_ptr: t.CSizeT | t.CPtr = HandlesStruct.get_mro_chain(pool, class_name)
mi: int = 1
while mro_ptr is not None and mro_ptr[mi] != 0:
anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mi], t.CPtr))
if anc is not None:
anc_lookup: str = pool.alloc(128)
if anc_lookup is not None:
viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder)
if ExprCallBase.find_func_in_module(mod, anc_lookup) is not None:
return 1
mi += 1
# 跨模块:类有 SHA1(stub 中声明该方法)视为存在
if HandlesStruct.get_struct_sha1(class_name) is not None:
return 1
return 0
# ============================================================
# _extract_annot_class_name - 从返回注解文本提取结构体类名
#
# vpi 返回注解文本(如 "'Vec3' | CPtr")按 '|' 分段,每段去除
# 空格/引号后查结构体注册表:命中即类名(内置类型 str/int/
# CFloat64T/t.CPtr 等均不注册 struct,天然过滤)。"A | B" 联合
# 多候选时取首个命中段。
# ============================================================
def _extract_annot_class_name(self, pool: memhub.MemBuddy | t.CPtr,
annot: str) -> str:
"""从返回注解文本提取已注册结构体类名,无命中返回 None"""
if pool is None or annot is None:
return None
alen: t.CSizeT = string.strlen(annot)
if alen == 0:
return None
seg: str = pool.alloc(256)
if seg is None:
return None
start: t.CSizeT = 0
i: t.CSizeT
for i in range(alen):
if annot[i] == '|':
s: t.CSizeT = start
e: t.CSizeT = i
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
s += 1
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
e -= 1
seglen: t.CSizeT = e - s
if seglen > 0 and seglen < 256:
string.strncpy(seg, annot + s, seglen)
seg[seglen] = '\0'
if HandlesStruct.find_struct(seg) is not None:
return seg
start = i + 1
# 最后一段(无 '|' 后缀)
s: t.CSizeT = start
e: t.CSizeT = alen
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
s += 1
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
e -= 1
seglen: t.CSizeT = e - s
if seglen > 0 and seglen < 256:
string.strncpy(seg, annot + s, seglen)
seg[seglen] = '\0'
if HandlesStruct.find_struct(seg) is not None:
return seg
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Gen.CallGenBase as CallGenBase
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
import lib.core.StubMergerStore as StubMergerStore
# ============================================================
# docstring 登记表容量常量(与 ExprGenMixin 保持一致,本地副本避免
# 跨模块 CDefine 查找 bug:ExprGenCls(C) 在 ExprGenMixin(M) 之前按
# 文件序编译时,跨模块 CDefine 全局表未注册 → NameError 未定义)
# ============================================================
DOC_MAX: t.CDefine = 512
DOC_KEY_SZ: t.CDefine = 192
DOC_VAL_SZ: t.CDefine = 4096
# ============================================================
# ExprGenCls - ExprGenMixin 拆分(阶段 D):类名推断/docstring 登记
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenCls(ExprGenBase.ExprGenBase):
"""类名推断/docstring 登记"""
# ============================================================
# docstring 提取/登记/查找(__doc__ 魔法属性支持)
#
# 预注册阶段(BuildPipeline.TranslateFileGetTrans)扫描所有
# App/includes 文件的 AST,提取函数/类/方法的 docstring 内容
# 登记到全局表(key = "{module_sha1}.{symbol}");__doc__ 属性
# 访问时查表,命中则当前模块内联生成字符串常量(无跨模块 IR
# 符号依赖),未命中返回 null。幂等查重,多遍翻译安全。
# ============================================================
def _extract_docstring_from_body(self, body: list[ast.AST | t.CPtr] | t.CPtr) -> str:
"""从函数/类体提取 docstring:body[0] 为 Expr(Constant str) 时返回内容"""
if body is None or len(body) == 0:
return None
first: ast.AST | t.CPtr = body.get(0)
if first is None or first.kind() != ast.ASTKind.Expr:
return None
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(first)
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant:
return None
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(ex.value)
if cn is None or cn.const_kind != ast.CONST_STR:
return None
return cn.str_val
def register_docstring(self, module_sha1: str, symbol: str, doc: str) -> None:
"""登记 docstring(key="{module_sha1}.{symbol}"),查重幂等"""
if module_sha1 is None or symbol is None or doc is None:
return
if string.strlen(doc) == 0:
return
if self.DocKeys is None:
self.DocKeys = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_KEY_SZ)
self.DocValues = CompilerFactory.get_perm_pool().alloc(DOC_MAX * DOC_VAL_SZ)
if self.DocKeys is None or self.DocValues is None:
return
string.memset(self.DocKeys, 0, DOC_MAX * DOC_KEY_SZ)
string.memset(self.DocValues, 0, DOC_MAX * DOC_VAL_SZ)
if self.DocCount >= DOC_MAX:
return
ml: t.CSizeT = string.strlen(module_sha1)
sl: t.CSizeT = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
return
string.strcpy(self.DocKeys + self.DocCount * DOC_KEY_SZ, key_buf)
string.strcpy(self.DocValues + self.DocCount * DOC_VAL_SZ, doc)
self.DocCount += 1
stdlib.free(key_buf)
def lookup_docstring(self, module_sha1: str, symbol: str) -> str:
"""查找 docstring 内容(key="{module_sha1}.{symbol}"),未找到返回 None"""
if self.DocKeys is None or module_sha1 is None or symbol is None:
return None
ml: t.CSizeT = string.strlen(module_sha1)
sl: t.CSizeT = string.strlen(symbol)
key_buf: bytes = stdlib.malloc(ml + sl + 2)
if key_buf is None:
return None
viperlib.snprintf(key_buf, ml + sl + 2, "%s.%s", module_sha1, symbol)
i: int
for i in range(self.DocCount):
if string.strcmp(self.DocKeys + i * DOC_KEY_SZ, key_buf) == 0:
stdlib.free(key_buf)
return self.DocValues + i * DOC_VAL_SZ
stdlib.free(key_buf)
return None
def extract_module_docstrings(self, tree: ast.AST | t.CPtr, module_sha1: str) -> None:
"""扫描模块 AST:登记模块级函数/类/方法的 docstring(幂等)"""
if tree is None or module_sha1 is None:
return
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is None:
return
cn: t.CSizeT = len(ch)
for ci in range(cn):
child: ast.AST | t.CPtr = ch.get(ci)
if child is None:
continue
kd: int = child.kind()
if kd == ast.ASTKind.FunctionDef:
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
if fd is not None and fd.name is not None:
fd_body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
fdoc: str = self._extract_docstring_from_body(fd_body)
if fdoc is not None:
self.register_docstring(module_sha1, fd.name, fdoc)
elif kd == ast.ASTKind.ClassDef:
cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
if cd is None or cd.name is None:
continue
cd_body0: list[ast.AST | t.CPtr] | t.CPtr = cd.children
cdoc: str = self._extract_docstring_from_body(cd_body0)
if cdoc is not None:
self.register_docstring(module_sha1, cd.name, cdoc)
# 类方法 docstring(key="{ClassName}.{method}")
cd_body: list[ast.AST | t.CPtr] | t.CPtr = cd.children
if cd_body is not None:
cbn: t.CSizeT = len(cd_body)
for mi in range(cbn):
m: ast.AST | t.CPtr = cd_body.get(mi)
if m is None or m.kind() != ast.ASTKind.FunctionDef:
continue
mfd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(m)
if mfd is None or mfd.name is None:
continue
mdoc: str = self._extract_docstring_from_body(mfd.children)
if mdoc is not None:
cl_nl: t.CSizeT = string.strlen(cd.name)
mt_nl: t.CSizeT = string.strlen(mfd.name)
sym_buf: bytes = stdlib.malloc(cl_nl + mt_nl + 2)
if sym_buf is not None:
viperlib.snprintf(sym_buf, cl_nl + mt_nl + 2, "%s.%s", cd.name, mfd.name)
self.register_docstring(module_sha1, sym_buf, mdoc)
stdlib.free(sym_buf)
def _resolve_doc_symbol_name(self, trans: HT.Translator | t.CPtr, name_id: str,
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
"""解析 Name 符号的 docstring 归属,写入 out_mod/out_sym,成功返回 1
判定顺序:本地变量(函数变量)→ 结构体类(含跨模块预注册)→ 模块名。
"""
if trans is None or name_id is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
# 1. 本地变量(函数变量/全局变量)
if self.Gen.VarGen.lookup_var(trans.SymTab, name_id) is not None:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
# 2. 结构体类(entry.ModuleSha1 区分跨模块预注册的类)
se: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(name_id)
if se is not None:
if se.ModuleSha1 is not None:
string.strcpy(out_mod, se.ModuleSha1)
else:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
# 3. 模块名(模块本身,少见);用 StubMerger 模块级函数(避免
# 跨 Mixin self 调用生成不存在符号)
mod_sha1: str = StubMergerStore.LookupSha1ByModName(name_id)
if mod_sha1 is None:
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(name_id)
if mod_sha1 is not None:
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, name_id)
return 1
# 4. 兜底当前模块
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, name_id)
return 1
def _resolve_doc_symbol_attr(self, trans: HT.Translator | t.CPtr,
at: ast.Attribute | t.CPtr,
out_mod: str | t.CPtr, out_sym: str | t.CPtr) -> int:
"""解析嵌套 Attribute 链的 docstring 归属,写入 out_mod/out_sym
支持形态:remote.remote_func / remote.RemoteClass /
remote.RemoteClass.remote_method / LocalClass.local_method 等。
最左 Name 判定:模块名 → 该模块 sha1;变量/类 → 类所属模块 sha1。
"""
if trans is None or at is None or out_mod is None or out_sym is None:
return 0
if trans.ModuleSha1 is None:
return 0
# 收集 Attribute 链(最外层 attr 在前)
DOC_CHAIN_MAX: t.CInt = 8
items: bytes = stdlib.malloc(DOC_CHAIN_MAX * 128)
if items is None:
return 0
n_items: int = 0
cur: ast.AST | t.CPtr = (ast.AST | t.CPtr)(at)
while cur is not None and cur.kind() == ast.ASTKind.Attribute and n_items < DOC_CHAIN_MAX:
cat: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cur)
if cat.attr is None:
break
string.strcpy(items + n_items * 128, cat.attr)
n_items += 1
cur = cat.value
# 最左应为 Name
head_id: str = None
if cur is not None and cur.kind() == ast.ASTKind.Name:
hnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cur)
head_id = hnm.id
if head_id is None:
stdlib.free(items)
return 0
# head 判定:模块名 or 变量/类
is_mod: int = 0
mod_sha1: str = None
if self.Gen.VarGen.lookup_var(trans.SymTab, head_id) is None:
mod_sha1 = StubMergerStore.LookupSha1ByModName(head_id)
if mod_sha1 is None:
mod_sha1 = StubMergerStore.LookupSha1ByModNameSuffix(head_id)
if mod_sha1 is not None:
is_mod = 1
if is_mod != 0:
# 模块限定:symbol = items 反转(不含 head_id)
if n_items == 0:
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, head_id)
stdlib.free(items)
return 1
total: t.CSizeT = 0
j: int
for j in range(n_items):
total += string.strlen(items + j * 128) + 1
sym_buf: bytes = stdlib.malloc(total + 1)
if sym_buf is None:
stdlib.free(items)
return 0
sym_buf[0] = '\0'
for j in range(n_items):
if j > 0:
string.strcat(sym_buf, ".")
string.strcat(sym_buf, items + (n_items - 1 - j) * 128)
string.strcpy(out_mod, mod_sha1)
string.strcpy(out_sym, sym_buf)
stdlib.free(sym_buf)
stdlib.free(items)
return 1
# 变量/类:symbol = head_id + '.' + items 反转
total2: t.CSizeT = string.strlen(head_id)
for j in range(n_items):
total2 += string.strlen(items + j * 128) + 1
sym2: bytes = stdlib.malloc(total2 + 1)
if sym2 is None:
stdlib.free(items)
return 0
sym2[0] = '\0'
string.strcat(sym2, head_id)
for j in range(n_items):
string.strcat(sym2, ".")
string.strcat(sym2, items + (n_items - 1 - j) * 128)
se2: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(head_id)
if se2 is not None and se2.ModuleSha1 is not None:
string.strcpy(out_mod, se2.ModuleSha1)
else:
string.strcpy(out_mod, trans.ModuleSha1)
string.strcpy(out_sym, sym2)
stdlib.free(sym2)
stdlib.free(items)
return 1
# ============================================================
# P3 迁移方法(来自 HandlesExprOps.vp:运算符重载 + 二元运算)
# ============================================================
# ============================================================
# infer_expr_class - 从表达式推断结构体类名(共享推断)
#
# 无注解赋值(HandlesAssign)与方法调用分派(CallGenMixin)共用:
# 联合类型 X|t.CPtr 简化为 Ptr(i8),不含类名,需按表达式结构推断:
# Call → 类实例化(func 为已注册结构体名);func 为 Attribute
# 时是方法调用,经 vpi 返回注解缓存解析返回类名
# Name → 源变量的 AnnotClassName
# BinOp/UnaryOp → lhs 类名 + 存在对应 dunder 方法(返回同类对象)
# Attribute → 字段注解类名(_resolve_attr_field_class)
# 仅采用已注册结构体;无法精确推断返回 None(fail-fast 由调用方暴露)。
# ============================================================
def infer_expr_class(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr) -> str:
"""从表达式推断结构体类名,无法推断返回 None"""
if node is None or trans is None:
return None
k: int = node.kind()
# Call: 类实例化 / 方法调用
if k == ast.ASTKind.Call:
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
if cl is None or cl.func is None:
return None
if cl.func.kind() == ast.ASTKind.Name:
cand: str = ((ast.Name | t.CPtr)(cl.func)).id
if cand is None:
return None
if self.Gen.StructGen.find_struct(cand) is not None:
return cand
return None
if cl.func.kind() == ast.ASTKind.Attribute:
# 方法调用 a.cross(b):vpi 返回注解缓存精确解析返回类名
# (方法可返回非同类对象,如 Transform.world_position → 'Vec3')。
ca: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if ca is None or ca.attr is None or ca.value is None:
return None
obj_cls: str = self.infer_expr_class(pool, mod, ca.value, trans)
if obj_cls is None:
return None
if self._cls_has_dunder(pool, mod, obj_cls, ca.attr) == 0:
return None
cls_sha1: str = self.Gen.StructGen.get_struct_sha1(obj_cls)
if cls_sha1 is None and trans.ModuleSha1 is not None:
cls_sha1 = trans.ModuleSha1
ret_cls: str = None
if cls_sha1 is not None:
import lib.StubGen.VpiReader as VpiReader
temp_dir: str = None
# 跨子对象访问经 self.Gen 取 CallGenBase.TempDir(双向引用)
if self.Gen.CallGenBase.TempDir is not None:
temp_dir = self.Gen.CallGenBase.TempDir
if temp_dir is not None:
VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, temp_dir)
annot_ret: str = VpiReader._lookup_vpi_ret_annot(
cls_sha1, obj_cls, ca.attr)
if annot_ret is not None:
ret_cls = self._extract_annot_class_name(pool, annot_ret)
return ret_cls
return None
# Name: 源变量注解
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
if nm is None or nm.id is None:
return None
ve: GenTypes.VarEntry | t.CPtr = self.Gen.VarGen.lookup_var_entry(
trans.SymTab, nm.id)
if ve is None:
return None
acn_n: str = ve.AnnotClassName
if acn_n is None:
return None
# 去模块前缀:json.JsonValue → JsonValue。AnnotClassName 可能带
# 模块限定(extract_class_name_from_annotation 的 Attribute 分支返回
# "memhub.MemBuddy" 形式),而 find_struct/_cls_has_dunder/
# get_struct_sha1 查找都用裸类名(struct 注册名)。泛型名
# (list[str] 含 '[')不截断(方括号内可能有点号)。
acn_dot_n: str = string.strrchr(acn_n, 46)
if acn_dot_n is not None and string.strchr(acn_n, 91) is None:
acn_n = acn_dot_n + 1
return acn_n
# BinOp/UnaryOp: 运算符重载返回同类对象
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
if bop is None or bop.left is None:
return None
dunder: str = self.Gen.ExprGenOps._binop_to_dunder(bop.op)
if dunder is None:
return None
lhs_cls: str = self.infer_expr_class(pool, mod, bop.left, trans)
if lhs_cls is None or self._cls_has_dunder(pool, mod, lhs_cls, dunder) == 0:
return None
return lhs_cls
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
if uop is None or uop.operand is None:
return None
dunder: str = self.Gen.ExprGenOps._unaryop_to_dunder(uop.op)
if dunder is None:
return None
opr_cls: str = self.infer_expr_class(pool, mod, uop.operand, trans)
if opr_cls is None or self._cls_has_dunder(pool, mod, opr_cls, dunder) == 0:
return None
return opr_cls
# Attribute: 字段注解类名(属性链递归,如 p = r.origin)
if k == ast.ASTKind.Attribute:
return self.Gen.ExprGenAttr._resolve_attr_field_class(pool, trans, node)
return None
# ============================================================
# _cls_has_dunder - 检查类(含继承链)是否存在 dunder/方法
#
# 与 try_operator_overload 的查找一致:当前模块内定义或跨模块类有
# SHA1(stub 中声明)即视为存在。仅在确实存在时采用推断类名,
# 避免把原生运算误标为类类型。
# ============================================================
def _cls_has_dunder(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str, dunder: str) -> int:
"""类及其 MRO 祖先链中是否存在 dunder 方法,存在返回 1"""
if class_name is None or dunder is None or mod is None:
return 0
lookup_name: str = pool.alloc(128)
if lookup_name is None:
return 0
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder)
if self.Gen.CallGenBase.find_func_in_module(mod, lookup_name) is not None:
return 1
# 继承链祖先查找
mro_ptr: t.CSizeT | t.CPtr = self.Gen.StructGen.get_mro_chain(pool, class_name)
mi: int = 1
while mro_ptr is not None and mro_ptr[mi] != 0:
anc: str = (str | t.CPtr)(t.CVoid(mro_ptr[mi], t.CPtr))
if anc is not None:
anc_lookup: str = pool.alloc(128)
if anc_lookup is not None:
viperlib.snprintf(anc_lookup, 128, "%s.%s", anc, dunder)
if self.Gen.CallGenBase.find_func_in_module(mod, anc_lookup) is not None:
return 1
mi += 1
# 跨模块:类有 SHA1(stub 中声明该方法)视为存在
if self.Gen.StructGen.get_struct_sha1(class_name) is not None:
return 1
return 0
# ============================================================
# _extract_annot_class_name - 从返回注解文本提取结构体类名
#
# vpi 返回注解文本(如 "'Vec3' | CPtr")按 '|' 分段,每段去除
# 空格/引号后查结构体注册表:命中即类名(内置类型 str/int/
# CFloat64T/t.CPtr 等均不注册 struct,天然过滤)。"A | B" 联合
# 多候选时取首个命中段。
# ============================================================
def _extract_annot_class_name(self, pool: memhub.MemBuddy | t.CPtr,
annot: str) -> str:
"""从返回注解文本提取已注册结构体类名,无命中返回 None"""
if pool is None or annot is None:
return None
alen: t.CSizeT = string.strlen(annot)
if alen == 0:
return None
seg: str = pool.alloc(256)
if seg is None:
return None
start: t.CSizeT = 0
i: t.CSizeT
for i in range(alen):
if annot[i] == '|':
s: t.CSizeT = start
e: t.CSizeT = i
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
s += 1
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
e -= 1
seglen: t.CSizeT = e - s
if seglen > 0 and seglen < 256:
string.strncpy(seg, annot + s, seglen)
seg[seglen] = '\0'
if self.Gen.StructGen.find_struct(seg) is not None:
return seg
start = i + 1
# 最后一段(无 '|' 后缀)
s: t.CSizeT = start
e: t.CSizeT = alen
while s < e and (annot[s] == ' ' or annot[s] == '\'' or annot[s] == '"'):
s += 1
while e > s and (annot[e - 1] == ' ' or annot[e - 1] == '\'' or annot[e - 1] == '"'):
e -= 1
seglen: t.CSizeT = e - s
if seglen > 0 and seglen < 256:
string.strncpy(seg, annot + s, seglen)
seg[seglen] = '\0'
if self.Gen.StructGen.find_struct(seg) is not None:
return seg
return None
+389 -398
View File
@@ -1,399 +1,390 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
import lib.core.Handles.ExprCallCtor as ExprCallCtor
# ============================================================
# ExprGenConst - ExprGenMixin 拆分(阶段 D):常量/全局字符串/list 字面量翻译
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenConst(ExprGenBase.ExprGenBase):
"""常量/全局字符串/list 字面量翻译"""
# ============================================================
# 创建全局字符串常量
# ============================================================
def create_global_string(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
str_val: str,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""创建全局字符串常量并返回 i8* bitcast"""
escaped: str = self.escape_llvm_string(pool, str_val)
if escaped is None:
return None
slen: t.CSizeT = string.strlen(str_val)
count: int = slen + 1
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, count)
# 使用模块级计数器(trans._label_counter)避免跨函数命名冲突
str_idx: int = trans._label_counter
trans._label_counter += 1
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
gv_name: str = pool.alloc(48)
if gv_name is None:
return None
if trans.ModuleSha1 is not None:
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
else:
viperlib.snprintf(gv_name, 48, ".str.%d", str_idx)
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
if gv is None:
return None
llvmlite.module_add_global(mod, gv)
# 去掉 private 链接,和函数一致:stub 中 declare,text 中 define
llvmlite.global_set_unnamed_addr(gv, 1)
llvmlite.global_set_constant(gv, 1)
# LLVM 22+ 不允许 external linkage 全局变量带初始值,设为 internal
gv.Linkage = "internal"
gv.Initializer = escaped
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
gv_ref_name: str = pool.alloc(64)
if gv_ref_name is None:
return None
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
return bc
# ============================================================
# 翻译常量表达式
# ============================================================
def translate_constant(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译常量(int/str/bool)"""
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn is None:
return None
ck: int = cn.const_kind
if cn.const_kind == ast.CONST_INT:
# 超出 i32 范围则用 i64(避免常量创建时被截断)
iv: t.CInt64T = cn.int_val
if iv > 2147483647 or iv < -2147483648:
return llvmlite.const_int64(pool, iv)
return llvmlite.const_int32(pool, iv)
elif cn.const_kind == ast.CONST_FLOAT:
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
elif cn.const_kind == ast.CONST_CHAR:
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
cv: t.CInt64T = cn.int_val
return llvmlite.const_int32(pool, cv)
elif cn.const_kind == ast.CONST_STR:
sv: str = cn.str_val
if sv is None:
return None
r: llvmlite.Value | t.CPtr = self.create_global_string(builder, pool, mod, sv, trans)
return r
elif cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0:
return llvmlite.const_int32(pool, 1)
return llvmlite.const_int32(pool, 0)
elif cn.const_kind == ast.CONST_NONE:
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None:
return None
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
return None
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
return rv_none
return None
# ============================================================
# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名
#
# 用于 list 字面量 [a, b, c] 的元素类型推断
# ============================================================
def _infer_elem_type_from_value(self, pool: memhub.MemBuddy | t.CPtr,
value: llvmlite.Value | t.CPtr) -> str:
"""从 LLVM Value 的类型推断 list 元素类型名
fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止),
绝不静默回退 "str"(掩盖上游 Value 类型缺失根因)。
"""
if value is None or value.Ty is None:
return None
ty: llvmlite.LLVMType | t.CPtr = value.Ty
bits: int = self.get_llvm_type_bits(ty)
if bits != 0:
if bits == 32:
return "int"
if bits == 64:
return "CSizeT"
if bits == 8:
return "CInt8T"
if bits == 16:
return "CInt16T"
return None
if self.is_ptr_type(ty) != 0:
return "str"
fbits: int = self.get_llvm_float_bits(ty)
if fbits != 0:
if fbits == 64:
return "CDouble"
if fbits == 32:
return "CFloat"
return None
# ============================================================
# _find_pool_var — 查找上下文中的 pool 变量
#
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
# ============================================================
def _find_pool_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""查找上下文中的 pool 变量,返回 alloca 或 None
查找顺序: pool → _mbuddy → mbuddy → mb
兜底: 若都未找到,注册外部全局 @_mbuddy (i8*) 供函数内动态 list 创建使用。
注意: 模块级 t.CArray 初始化不走此路径(由 _init_global_array_from_list 处理),
此兜底仅用于函数内的动态 list 字面量(如 op=[...])。
@_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。
"""
if trans is None:
return None
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, "pool")
if alloca is not None:
return alloca
alloca = HandlesVar.lookup_var(trans.SymTab, "_mbuddy")
if alloca is not None:
return alloca
alloca = HandlesVar.lookup_var(trans.SymTab, "mbuddy")
if alloca is not None:
return alloca
alloca = HandlesVar.lookup_var(trans.SymTab, "mb")
if alloca is not None:
return alloca
# 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer)
# 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享
# (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许
# 链接器合并同模板重复特化定义,zeroinitializer 保证编译链接通过。
# 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list),
# 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。
pool: memhub.MemBuddy | t.CPtr = trans.Pool
if pool is None or trans.Module is None or trans.SymTab is None:
return None
# 先检查是否已注册到模块作用域(避免重复创建全局变量)
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(trans.SymTab, "_mbuddy")
if existing is not None:
return existing
# 创建 i8* 类型(t.CVoid | t.CPtr = i8*)
i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb)
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
mb_name_fb: str = HandlesFunctions._mangle_name(trans, "_mbuddy")
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
if gv_ext is not None:
gv_ext.Linkage = "linkonce_odr"
gv_ext.Initializer = "zeroinitializer"
llvmlite.module_add_global(trans.Module, gv_ext)
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
ref_name_fb: str = pool.alloc(96)
if ref_name_fb is not None:
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref)
if HandlesClassDef._vtable_name_needs_quote(mb_name_fb) != 0:
viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb)
else:
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
# 注册到模块作用域,避免重复创建
HandlesVar.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
return gv_ref_fb
# ============================================================
# translate_list_literal — 翻译 list 字面量 [a, b, c]
#
# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列
#
# Args:
# builder: IRBuilder
# pool: 编译器内存池(MemBuddy)
# mod: LLVMModule
# node: ast.List 节点
# elem_type_name: 元素类型名(如 "str", "int"),None 表示从元素推断
# trans: Translator 对象
#
# Returns:
# list 对象指针(Ptr(list[T] struct)),None 失败
# ============================================================
def translate_list_literal(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
elem_type_name: str,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列"""
if node is None or trans is None:
return None
list_node: ast.List | t.CPtr = (ast.List | t.CPtr)(node)
if list_node is None:
return None
elts: list[ast.AST | t.CPtr] | t.CPtr = list_node.elts
elts_count: t.CSizeT = 0
if elts is not None:
elts_count = len(elts)
# 推断元素类型
inferred_type_name: str = elem_type_name
first_elem_val: llvmlite.Value | t.CPtr = None
if inferred_type_name is None:
if elts_count > 0:
first_elem_node: ast.AST | t.CPtr = elts.get(0)
first_elem_val = HandlesExpr.translate_value(builder, pool, mod, first_elem_node, None, 0, trans)
if first_elem_val is None or first_elem_val.Ty is None:
# fail-fast:首元素翻译失败/Value 类型缺失,立即终止编译(暴露上游根因)
HandlesType.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
inferred_type_name = self._infer_elem_type_from_value(pool, first_elem_val)
if inferred_type_name is None:
# fail-fast:首元素 Value 类型无法映射为 list 元素类型,立即终止编译
HandlesType.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
else:
# 空 list 无元素可推断,保持默认 str(list[str])
inferred_type_name = "str"
# 查找 pool 变量
pool_alloca: llvmlite.Value | t.CPtr = self._find_pool_var(trans)
if pool_alloca is None:
HandlesType.fatal_error(node, "list literal requires pool variable in context")
return None
# load pool 变量值(i8*)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
pool_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca)
if pool_val is None:
return None
# 特化 list[T] 类(elem_size=8:str 是指针,4 会导致双元素重叠损坏)
type_args: list[str] | t.CPtr = list[str](pool, 8)
type_args.append(inferred_type_name)
spec_name: str = HandlesClassDef._specialize_generic_class(trans, "list", type_args)
if spec_name is None:
HandlesType.fatal_error(node, "list literal generic specialization failed")
return None
# 查找 struct entry
struct_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name)
if struct_entry is None:
HandlesType.fatal_error(node, "list literal specialized class not registered")
return None
struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty
if struct_ty is None:
return None
# alloca 临时 list 空间
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
if tmp is None:
return None
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
# (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致,
# 避免为无 __new__ 的类生成过度声明)
storage_ptr: llvmlite.Value | t.CPtr = tmp
has_new_flag: int = 0
if struct_entry is not None:
has_new_flag = struct_entry.HasNew
if has_new_flag != 0:
new_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if new_args is None:
return None
string.memset(new_args, 0, 8 * 32)
new_args[0] = t.CSizeT(pool_val)
new_ptr: llvmlite.Value | t.CPtr = ExprCallCtor._call_method_on_ptr(
pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
if new_ptr is not None:
storage_ptr = new_ptr
# 调用 __before_init__(storage_ptr)
ExprCallCtor._call_method_on_ptr(
pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans)
# 调用 __init__(storage_ptr, pool_val, elem_size=0)
init_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if init_args is None:
return None
string.memset(init_args, 0, 8 * 32)
init_args[0] = t.CSizeT(pool_val)
elem_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0)
init_args[1] = t.CSizeT(elem_size_val)
ExprCallCtor._call_method_on_ptr(
pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans)
# 对每个元素调用 append(storage_ptr, elem_val)
if elts_count > 0:
# 第一个元素可能已经翻译过
if first_elem_val is not None:
append_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if append_args is not None:
string.memset(append_args, 0, 8 * 32)
append_args[0] = t.CSizeT(first_elem_val)
ExprCallCtor._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
# 翻译剩余元素
i: t.CSizeT = 1
while i < elts_count:
elem_node_i: ast.AST | t.CPtr = elts.get(i)
elem_val_i: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
if elem_val_i is not None:
ap_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if ap_args is not None:
string.memset(ap_args, 0, 8 * 32)
ap_args[0] = t.CSizeT(elem_val_i)
ExprCallCtor._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
i += 1
import lib.core.Gen.GenTypes as GenTypes
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
# ============================================================
# ExprGenConst - ExprGenMixin 拆分(阶段 D):常量/全局字符串/list 字面量翻译
#
# 继承 ExprGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExpr 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class ExprGenConst(ExprGenBase.ExprGenBase):
"""常量/全局字符串/list 字面量翻译"""
# ============================================================
# 创建全局字符串常量
# ============================================================
def create_global_string(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
str_val: str,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""创建全局字符串常量并返回 i8* bitcast"""
escaped: str = self.escape_llvm_string(pool, str_val)
if escaped is None:
return None
slen: t.CSizeT = string.strlen(str_val)
count: int = slen + 1
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, count)
# 使用模块级计数器(trans._label_counter)避免跨函数命名冲突
str_idx: int = trans._label_counter
trans._label_counter += 1
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
gv_name: str = pool.alloc(48)
if gv_name is None:
return None
if trans.ModuleSha1 is not None:
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
else:
viperlib.snprintf(gv_name, 48, ".str.%d", str_idx)
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
if gv is None:
return None
llvmlite.module_add_global(mod, gv)
# 去掉 private 链接,和函数一致:stub 中 declare,text 中 define
llvmlite.global_set_unnamed_addr(gv, 1)
llvmlite.global_set_constant(gv, 1)
# LLVM 22+ 不允许 external linkage 全局变量带初始值,设为 internal
gv.Linkage = "internal"
gv.Initializer = escaped
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
gv_ref_name: str = pool.alloc(64)
if gv_ref_name is None:
return None
viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name)
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty)
return bc
# ============================================================
# 翻译常量表达式
# ============================================================
def translate_constant(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译常量(int/str/bool)"""
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn is None:
return None
ck: int = cn.const_kind
if cn.const_kind == ast.CONST_INT:
# 超出 i32 范围则用 i64(避免常量创建时被截断)
iv: t.CInt64T = cn.int_val
if iv > 2147483647 or iv < -2147483648:
return llvmlite.const_int64(pool, iv)
return llvmlite.const_int32(pool, iv)
elif cn.const_kind == ast.CONST_FLOAT:
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
elif cn.const_kind == ast.CONST_CHAR:
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
cv: t.CInt64T = cn.int_val
return llvmlite.const_int32(pool, cv)
elif cn.const_kind == ast.CONST_STR:
sv: str = cn.str_val
if sv is None:
return None
r: llvmlite.Value | t.CPtr = self.create_global_string(builder, pool, mod, sv, trans)
return r
elif cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0:
return llvmlite.const_int32(pool, 1)
return llvmlite.const_int32(pool, 0)
elif cn.const_kind == ast.CONST_NONE:
# None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None:
return None
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
return None
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
return rv_none
return None
# ============================================================
# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名
#
# 用于 list 字面量 [a, b, c] 的元素类型推断
# ============================================================
def _infer_elem_type_from_value(self, pool: memhub.MemBuddy | t.CPtr,
value: llvmlite.Value | t.CPtr) -> str:
"""从 LLVM Value 的类型推断 list 元素类型名
fail-fast:值类型缺失/无法映射时返回 None(调用方携带节点报错终止),
绝不静默回退 "str"(掩盖上游 Value 类型缺失根因)。
"""
if value is None or value.Ty is None:
return None
ty: llvmlite.LLVMType | t.CPtr = value.Ty
bits: int = self.get_llvm_type_bits(ty)
if bits != 0:
if bits == 32:
return "int"
if bits == 64:
return "CSizeT"
if bits == 8:
return "CInt8T"
if bits == 16:
return "CInt16T"
return None
if self.is_ptr_type(ty) != 0:
return "str"
fbits: int = self.get_llvm_float_bits(ty)
if fbits != 0:
if fbits == 64:
return "CDouble"
if fbits == 32:
return "CFloat"
return None
# ============================================================
# _find_pool_var — 查找上下文中的 pool 变量
#
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
# ============================================================
def _find_pool_var(self, trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""查找上下文中的 pool 变量,返回 alloca 或 None
查找顺序: pool → _mbuddy → mbuddy → mb
兜底: 若都未找到,注册外部全局 @_mbuddy (i8*) 供函数内动态 list 创建使用。
注意: 模块级 t.CArray 初始化不走此路径(由 _init_global_array_from_list 处理),
此兜底仅用于函数内的动态 list 字面量(如 op=[...])。
@_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。
"""
if trans is None:
return None
alloca: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_var(trans.SymTab, "pool")
if alloca is not None:
return alloca
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "_mbuddy")
if alloca is not None:
return alloca
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mbuddy")
if alloca is not None:
return alloca
alloca = self.Gen.VarGen.lookup_var(trans.SymTab, "mb")
if alloca is not None:
return alloca
# 兜底: 创建当前模块 mangled 的 @_mbuddy 定义(linkonce_odr + zeroinitializer)
# 对齐模块级全局带 SHA1 前缀命名:裸名 @_mbuddy 依赖链接合并共享
# (--allow-multiple-definition),带前缀后每模块独立。linkonce_odr 允许
# 链接器合并同模板重复特化定义,zeroinitializer 保证编译链接通过。
# 运行时若该模块未在入口 main 赋值 _mbuddy(null pool 上动态建 list),
# 由真实崩溃暴露(fail-fast 哲学,不掩盖上游未初始化)。
pool: memhub.MemBuddy | t.CPtr = trans.Pool
if pool is None or trans.Module is None or trans.SymTab is None:
return None
# 先检查是否已注册到模块作用域(避免重复创建全局变量)
existing: llvmlite.Value | t.CPtr = self.Gen.VarGen.lookup_module_var(trans.SymTab, "_mbuddy")
if existing is not None:
return existing
# 创建 i8* 类型(t.CVoid | t.CPtr = i8*)
i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb)
# 当前模块 mangled 名(@<模块sha1>._mbuddy)
mb_name_fb: str = self.Gen.FuncGenBase._mangle_name(trans, "_mbuddy")
# 创建 linkonce_odr 定义(可被链接器合并,自给自足保证链接通过)
gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, mb_name_fb, i8_ptr_ty_fb)
if gv_ext is not None:
gv_ext.Linkage = "linkonce_odr"
gv_ext.Initializer = "zeroinitializer"
llvmlite.module_add_global(trans.Module, gv_ext)
# 创建 Value 引用(@<模块sha1>._mbuddy, 类型为 i8**)
i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb)
ref_name_fb: str = pool.alloc(96)
if ref_name_fb is not None:
# mangled 名带 SHA1 前缀(数字开头),引用必须加引号(见 make_global_ref)
if self.Gen.ClassGenVTable._vtable_name_needs_quote(mb_name_fb) != 0:
viperlib.snprintf(ref_name_fb, 96, "@\"%s\"", mb_name_fb)
else:
viperlib.snprintf(ref_name_fb, 96, "@%s", mb_name_fb)
gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb)
# 注册到模块作用域,避免重复创建
self.Gen.VarGen.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb)
return gv_ref_fb
# ============================================================
# translate_list_literal — 翻译 list 字面量 [a, b, c]
#
# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列
#
# Args:
# builder: IRBuilder
# pool: 编译器内存池(MemBuddy)
# mod: LLVMModule
# node: ast.List 节点
# elem_type_name: 元素类型名(如 "str", "int"),None 表示从元素推断
# trans: Translator 对象
#
# Returns:
# list 对象指针(Ptr(list[T] struct)),None 失败
# ============================================================
def translate_list_literal(self, builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
elem_type_name: str,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列"""
if node is None or trans is None:
return None
list_node: ast.List | t.CPtr = (ast.List | t.CPtr)(node)
if list_node is None:
return None
elts: list[ast.AST | t.CPtr] | t.CPtr = list_node.elts
elts_count: t.CSizeT = 0
if elts is not None:
elts_count = len(elts)
# 推断元素类型
inferred_type_name: str = elem_type_name
first_elem_val: llvmlite.Value | t.CPtr = None
if inferred_type_name is None:
if elts_count > 0:
first_elem_node: ast.AST | t.CPtr = elts.get(0)
first_elem_val = self.Gen.ExprGen.translate_value(builder, pool, mod, first_elem_node, None, 0, trans)
if first_elem_val is None or first_elem_val.Ty is None:
# fail-fast:首元素翻译失败/Value 类型缺失,立即终止编译(暴露上游根因)
self.Gen.TypeGenErr.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
inferred_type_name = self._infer_elem_type_from_value(pool, first_elem_val)
if inferred_type_name is None:
# fail-fast:首元素 Value 类型无法映射为 list 元素类型,立即终止编译
self.Gen.TypeGenErr.fatal_error(
first_elem_node, "list 字面量元素类型推断失败(Value 类型缺失)", "TypeError")
else:
# 空 list 无元素可推断,保持默认 str(list[str])
inferred_type_name = "str"
# 查找 pool 变量
pool_alloca: llvmlite.Value | t.CPtr = self._find_pool_var(trans)
if pool_alloca is None:
self.Gen.TypeGenErr.fatal_error(node, "list literal requires pool variable in context")
return None
# load pool 变量值(i8*)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
pool_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca)
if pool_val is None:
return None
# 特化 list[T] 类(elem_size=8:str 是指针,4 会导致双元素重叠损坏)
type_args: list[str] | t.CPtr = list[str](pool, 8)
type_args.append(inferred_type_name)
spec_name: str = self.Gen.ClassGenGeneric._specialize_generic_class(trans, "list", type_args)
if spec_name is None:
self.Gen.TypeGenErr.fatal_error(node, "list literal generic specialization failed")
return None
# 查找 struct entry
struct_entry: GenTypes.StructEntry | t.CPtr = self.Gen.StructGen.find_struct(spec_name)
if struct_entry is None:
self.Gen.TypeGenErr.fatal_error(node, "list literal specialized class not registered")
return None
struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty
if struct_ty is None:
return None
# alloca 临时 list 空间
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
self.Gen.StructGen.ensure_struct_def_in_module(pool, mod, struct_ty)
tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty)
if tmp is None:
return None
# 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针
# __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用
# (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致,
# 避免为无 __new__ 的类生成过度声明)
storage_ptr: llvmlite.Value | t.CPtr = tmp
has_new_flag: int = 0
if struct_entry is not None:
has_new_flag = struct_entry.HasNew
if has_new_flag != 0:
new_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if new_args is None:
return None
string.memset(new_args, 0, 8 * 32)
new_args[0] = t.CSizeT(pool_val)
new_ptr: llvmlite.Value | t.CPtr = self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans)
if new_ptr is not None:
storage_ptr = new_ptr
# 调用 __before_init__(storage_ptr)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans)
# 调用 __init__(storage_ptr, pool_val, elem_size=0)
init_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if init_args is None:
return None
string.memset(init_args, 0, 8 * 32)
init_args[0] = t.CSizeT(pool_val)
elem_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0)
init_args[1] = t.CSizeT(elem_size_val)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans)
# 对每个元素调用 append(storage_ptr, elem_val)
if elts_count > 0:
# 第一个元素可能已经翻译过
if first_elem_val is not None:
append_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if append_args is not None:
string.memset(append_args, 0, 8 * 32)
append_args[0] = t.CSizeT(first_elem_val)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans)
# 翻译剩余元素
i: t.CSizeT = 1
while i < elts_count:
elem_node_i: ast.AST | t.CPtr = elts.get(i)
elem_val_i: llvmlite.Value | t.CPtr = self.Gen.ExprGen.translate_value(builder, pool, mod, elem_node_i, None, 0, trans)
if elem_val_i is not None:
ap_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32)
if ap_args is not None:
string.memset(ap_args, 0, 8 * 32)
ap_args[0] = t.CSizeT(elem_val_i)
self.Gen.CallGenCall._call_method_on_ptr(
pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans)
i += 1
return storage_ptr
File diff suppressed because it is too large. Load diff
+121 -130
View File
@@ -1,130 +1,121 @@
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
import lib.core.Handles.ExprCallCall as ExprCallCall
# ============================================================
# 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) -> 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 = HandlesExpr.translate_constant(builder, pool, mod, node, trans)
return rv
elif k == ast.ASTKind.Name:
return HandlesExpr.translate_name_value(builder, pool, node, trans)
elif k == ast.ASTKind.BinOp:
return HandlesExpr.translate_binop(pool, builder, mod, node, trans)
elif k == ast.ASTKind.Call:
return ExprCallCall.translate_call(pool, builder, mod, node,
funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Compare:
return HandlesExpr.translate_compare(builder, pool, mod, node, trans)
elif k == ast.ASTKind.UnaryOp:
return HandlesExpr.translate_unaryop(builder, pool, mod, node, trans)
elif k == ast.ASTKind.BoolOp:
return HandlesExpr.translate_boolop(builder, pool, mod, node,
funcs_ptr, func_count, trans)
elif k == ast.ASTKind.Subscript:
return HandlesExpr.translate_subscript(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Attribute:
return HandlesExpr.translate_attribute(builder, pool, mod, node, trans)
elif k == ast.ASTKind.List:
return HandlesExpr.translate_list_literal(builder, pool, mod, node, None, trans)
elif k == ast.ASTKind.IfExp:
return HandlesExpr.translate_ifexp(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Lambda:
# 模块级委托:translate_lambda 定义在 FuncGenMixin(跨 Mixin
# 方法不能 self. 直接调用,见 HandlesExpr.translate_lambda)
return HandlesExpr.translate_lambda(builder, pool, mod, node, trans)
elif k == ast.ASTKind.JoinedStr:
return HandlesExpr.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 HandlesExpr.translate_formatted_value(builder, pool, mod, node, trans)
return None
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.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.Gen.ExprGenBase as ExprGenBase
# ============================================================
# 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) -> 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)
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)
return None
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+326 -332
View File
@@ -1,333 +1,327 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
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.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesBody as HandlesBody
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
# ============================================================
# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class FuncGenBase(CallGenBase.CallGenBase):
"""函数属性 / 命名 / mangle / create_function 基础工具"""
# ============================================================
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
#
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
#
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
# ============================================================
def extract_func_attrs(self, pool: memhub.MemBuddy | t.CPtr,
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
imported_modules: str) -> str:
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
if decorator_list is None:
return None
dn: t.CSizeT = len(decorator_list)
if dn == 0:
return None
attrs_buf: str = pool.alloc(256)
if attrs_buf is None:
return None
attrs_buf[0] = '\0'
found_any: int = 0
for di in range(dn):
deco: ast.AST | t.CPtr = decorator_list.get(di)
if deco is None or deco.kind() != ast.ASTKind.Call:
continue
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
continue
# 检测 c.Attribute
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
continue
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
continue
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
continue
if HandlesImports.is_module_imported(imported_modules, "c") == 0:
continue
# 遍历参数提取属性
if call_node.args is None:
continue
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
an: t.CSizeT = len(args_list)
for ai in range(an):
arg_node: ast.AST | t.CPtr = args_list.get(ai)
if arg_node is None:
continue
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
attr_name: str = self._get_attr_name_from_node(arg_node)
if attr_name is None:
continue
# 映射到 LLVM 属性名并追加
if self._append_llvm_attr(attrs_buf, attr_name) != 0:
found_any = 1
# 追加成功后,如果不是最后一个属性,添加空格分隔
# 在下一次追加前由 _append_str 处理
if found_any == 0:
return None
return attrs_buf
def _get_attr_name_from_node(self, node: ast.AST | t.CPtr) -> str:
"""从 AST 节点提取属性名
支持:
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
- Attribute: t.attr.packed -> "packed"
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
"""
if node is None:
return None
k: int = node.kind()
# Call 节点: t.attr.always_inline()
if k == ast.ASTKind.Call:
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
return None
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
return at.attr
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
if k == ast.ASTKind.Attribute:
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
return at2.attr
return None
def _append_llvm_attr(self, attrs_buf: str, attr_name: str) -> int:
"""将属性名映射到 LLVM 属性名并追加到缓冲区
返回 1 表示已追加,0 表示不支持该属性
"""
if attrs_buf is None or attr_name is None:
return 0
# 先确定映射的 LLVM 属性名
llvm_name: str = None
if string.strcmp(attr_name, "always_inline") == 0:
llvm_name = "alwaysinline"
elif string.strcmp(attr_name, "noinline") == 0:
llvm_name = "noinline"
elif string.strcmp(attr_name, "noreturn") == 0:
llvm_name = "noreturn"
elif string.strcmp(attr_name, "pure") == 0:
llvm_name = "readonly"
elif string.strcmp(attr_name, "const") == 0:
llvm_name = "readnone"
elif string.strcmp(attr_name, "nounwind") == 0:
llvm_name = "nounwind"
elif string.strcmp(attr_name, "noredzone") == 0:
llvm_name = "noredzone"
elif string.strcmp(attr_name, "willreturn") == 0:
llvm_name = "willreturn"
elif string.strcmp(attr_name, "mustprogress") == 0:
llvm_name = "mustprogress"
else:
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
return 0
# 支持的属性:如果缓冲区非空,先追加空格分隔
if attrs_buf[0] != '\0':
self._append_str(attrs_buf, " ")
self._append_str(attrs_buf, llvm_name)
return 1
def _append_str(self, buf: str, s: str,
max_len: t.CSizeT = 256) -> None:
"""将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)"""
if buf is None or s is None:
return
cur_len: t.CSizeT = string.strlen(buf)
s_len: t.CSizeT = string.strlen(s)
if cur_len + s_len + 1 > max_len:
return # 无剩余容量:丢弃本次追加,避免越界写
string.strcpy(buf + cur_len, s)
# ============================================================
# _mangle_name - 为名称添加 SHA1 前缀
#
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
# SHA1 前缀(16 hex + '.'),则原样返回。
# ============================================================
def _mangle_name(self, trans: HT.Translator | t.CPtr, name: str) -> str:
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
if trans is None or name is None:
return name
if trans.ModuleSha1 is None:
return name
name_len: t.CSizeT = string.strlen(name)
# 已带 SHA1 前缀(16 hex + '.')则跳过
if name_len > 17:
is_sha1: int = 1
for i in range(16):
c: t.CChar = name[i]
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
is_sha1 = 0
break
if is_sha1 != 0 and name[16] == '.':
return name
sha1: str = trans.ModuleSha1
sha1_len: t.CSizeT = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
return mangled
# ============================================================
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
#
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
# 而非当前模块的 SHA1。
# ============================================================
def _mangle_name_with_sha1(self, sha1: str, name: str) -> str:
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
if sha1 is None or name is None:
return name
name_len: t.CSizeT = string.strlen(name)
# 已带 SHA1 前缀(16 hex + '.')则跳过
if name_len > 17:
is_sha1: int = 1
for i in range(16):
c2: t.CChar = name[i]
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
is_sha1 = 0
break
if is_sha1 != 0 and name[16] == '.':
return name
sha1_len: t.CSizeT = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
return mangled
# ============================================================
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
#
# 规则:
# - main 函数不加前缀(程序入口点)
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
# - 已带 SHA1 前缀的不再加
# - ModuleSha1 为 None 时不加前缀
# ============================================================
def _mangle_func_name(self, trans: HT.Translator | t.CPtr, name: str,
has_export: int) -> str:
"""为函数名添加 SHA1 前缀(检查 main/export)"""
if trans is None or name is None:
return name
if has_export != 0:
return name
if string.strcmp(name, "main") == 0:
return name
return self._mangle_name(trans, name)
# ============================================================
# _body_has_raise - 函数体是否含 raise(非 StopIteration)
#
# 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名
# 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体
# 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。
# ============================================================
def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int:
"""函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否"""
if fd is None or fd.children is None:
return 0
body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children
bn_f: t.CSizeT = len(body_f)
for bi_f in range(bn_f):
stmt_f: ast.AST | t.CPtr = body_f.get(bi_f)
if stmt_f is None:
continue
if stmt_f.kind() != ast.ASTKind.Raise:
continue
rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f)
if rn_f is None or rn_f.exc is None:
continue
ek_f: int = rn_f.exc.kind()
is_stop_f: int = 0
if ek_f == ast.ASTKind.Name:
enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc)
if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0:
is_stop_f = 1
elif ek_f == ast.ASTKind.Call:
ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc)
if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name:
ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func)
if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0:
is_stop_f = 1
if is_stop_f == 0:
return 1
return 0
# ============================================================
# 创建 LLVM 函数(简单版本,仅声明)
# ============================================================
def create_function(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
name: str,
args_node: ast.AST | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
"""创建 LLVM 函数并添加参数"""
if name is None or mod is None:
return None
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
if func is None:
return None
if args_node is not None:
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
if ags.args is not None:
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
an: t.CSizeT = len(alist)
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
for ai in range(an):
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
if arg is not None and arg.arg is not None:
# t.CVoid 表示空参:跳过
if arg.annotation is not None:
if arg.annotation.kind() == ast.ASTKind.Attribute:
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
continue
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
pool, arg.annotation, None, None, None)
if resolved is not None:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# FuncGenBase - FuncGenMixin 拆分(阶段 D):函数属性 / 命名 / mangle / create_function 基础工具
#
# 继承 CallGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesExprCall 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class FuncGenBase(CallGenBase.CallGenBase):
"""函数属性 / 命名 / mangle / create_function 基础工具"""
# ============================================================
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
#
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
#
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
# ============================================================
def extract_func_attrs(self, pool: memhub.MemBuddy | t.CPtr,
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
imported_modules: str) -> str:
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
if decorator_list is None:
return None
dn: t.CSizeT = len(decorator_list)
if dn == 0:
return None
attrs_buf: str = pool.alloc(256)
if attrs_buf is None:
return None
attrs_buf[0] = '\0'
found_any: int = 0
for di in range(dn):
deco: ast.AST | t.CPtr = decorator_list.get(di)
if deco is None or deco.kind() != ast.ASTKind.Call:
continue
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
continue
# 检测 c.Attribute
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
continue
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
continue
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
continue
if self.Gen.ImportsGen.is_module_imported(imported_modules, "c") == 0:
continue
# 遍历参数提取属性
if call_node.args is None:
continue
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
an: t.CSizeT = len(args_list)
for ai in range(an):
arg_node: ast.AST | t.CPtr = args_list.get(ai)
if arg_node is None:
continue
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
attr_name: str = self._get_attr_name_from_node(arg_node)
if attr_name is None:
continue
# 映射到 LLVM 属性名并追加
if self._append_llvm_attr(attrs_buf, attr_name) != 0:
found_any = 1
# 追加成功后,如果不是最后一个属性,添加空格分隔
# 在下一次追加前由 _append_str 处理
if found_any == 0:
return None
return attrs_buf
def _get_attr_name_from_node(self, node: ast.AST | t.CPtr) -> str:
"""从 AST 节点提取属性名
支持:
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
- Attribute: t.attr.packed -> "packed"
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
"""
if node is None:
return None
k: int = node.kind()
# Call 节点: t.attr.always_inline()
if k == ast.ASTKind.Call:
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
return None
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
return at.attr
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
if k == ast.ASTKind.Attribute:
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
return at2.attr
return None
def _append_llvm_attr(self, attrs_buf: str, attr_name: str) -> int:
"""将属性名映射到 LLVM 属性名并追加到缓冲区
返回 1 表示已追加,0 表示不支持该属性
"""
if attrs_buf is None or attr_name is None:
return 0
# 先确定映射的 LLVM 属性名
llvm_name: str = None
if string.strcmp(attr_name, "always_inline") == 0:
llvm_name = "alwaysinline"
elif string.strcmp(attr_name, "noinline") == 0:
llvm_name = "noinline"
elif string.strcmp(attr_name, "noreturn") == 0:
llvm_name = "noreturn"
elif string.strcmp(attr_name, "pure") == 0:
llvm_name = "readonly"
elif string.strcmp(attr_name, "const") == 0:
llvm_name = "readnone"
elif string.strcmp(attr_name, "nounwind") == 0:
llvm_name = "nounwind"
elif string.strcmp(attr_name, "noredzone") == 0:
llvm_name = "noredzone"
elif string.strcmp(attr_name, "willreturn") == 0:
llvm_name = "willreturn"
elif string.strcmp(attr_name, "mustprogress") == 0:
llvm_name = "mustprogress"
else:
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
return 0
# 支持的属性:如果缓冲区非空,先追加空格分隔
if attrs_buf[0] != '\0':
self._append_str(attrs_buf, " ")
self._append_str(attrs_buf, llvm_name)
return 1
def _append_str(self, buf: str, s: str,
max_len: t.CSizeT = 256) -> None:
"""将字符串追加到 buf 末尾(有界,防 strcpy 越界写穿定长缓冲)"""
if buf is None or s is None:
return
cur_len: t.CSizeT = string.strlen(buf)
s_len: t.CSizeT = string.strlen(s)
if cur_len + s_len + 1 > max_len:
return # 无剩余容量:丢弃本次追加,避免越界写
string.strcpy(buf + cur_len, s)
# ============================================================
# _mangle_name - 为名称添加 SHA1 前缀
#
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
# SHA1 前缀(16 hex + '.'),则原样返回。
# ============================================================
def _mangle_name(self, trans: HT.Translator | t.CPtr, name: str) -> str:
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
if trans is None or name is None:
return name
if trans.ModuleSha1 is None:
return name
name_len: t.CSizeT = string.strlen(name)
# 已带 SHA1 前缀(16 hex + '.')则跳过
if name_len > 17:
is_sha1: int = 1
for i in range(16):
c: t.CChar = name[i]
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
is_sha1 = 0
break
if is_sha1 != 0 and name[16] == '.':
return name
sha1: str = trans.ModuleSha1
sha1_len: t.CSizeT = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
return mangled
# ============================================================
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
#
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
# 而非当前模块的 SHA1。
# ============================================================
def _mangle_name_with_sha1(self, sha1: str, name: str) -> str:
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
if sha1 is None or name is None:
return name
name_len: t.CSizeT = string.strlen(name)
# 已带 SHA1 前缀(16 hex + '.')则跳过
if name_len > 17:
is_sha1: int = 1
for i in range(16):
c2: t.CChar = name[i]
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
is_sha1 = 0
break
if is_sha1 != 0 and name[16] == '.':
return name
sha1_len: t.CSizeT = string.strlen(sha1)
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
if mangled is None:
return name
string.strcpy(mangled, sha1)
mangled[sha1_len] = '.'
string.strcpy(mangled + sha1_len + 1, name)
return mangled
# ============================================================
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
#
# 规则:
# - main 函数不加前缀(程序入口点)
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
# - 已带 SHA1 前缀的不再加
# - ModuleSha1 为 None 时不加前缀
# ============================================================
def _mangle_func_name(self, trans: HT.Translator | t.CPtr, name: str,
has_export: int) -> str:
"""为函数名添加 SHA1 前缀(检查 main/export)"""
if trans is None or name is None:
return name
if has_export != 0:
return name
if string.strcmp(name, "main") == 0:
return name
return self._mangle_name(trans, name)
# ============================================================
# _body_has_raise - 函数体是否含 raise(非 StopIteration)
#
# 对齐 TPC HandlesFunctions.py L216-243 _body_contains_raise:函数签名
# 追加 __eh_msg_out__/__eh_code_out__ 输出参数的条件。v1 只扫函数体
# 顶层 raise(嵌套 if/for/try 内的 raise 未覆盖,后续扩展)。
# ============================================================
def _body_has_raise(self, fd: ast.FunctionDef | t.CPtr) -> int:
"""函数体顶层是否含 raise(非 StopIteration),1=是 / 0=否"""
if fd is None or fd.children is None:
return 0
body_f: list[ast.AST | t.CPtr] | t.CPtr = fd.children
bn_f: t.CSizeT = len(body_f)
for bi_f in range(bn_f):
stmt_f: ast.AST | t.CPtr = body_f.get(bi_f)
if stmt_f is None:
continue
if stmt_f.kind() != ast.ASTKind.Raise:
continue
rn_f: ast.Raise | t.CPtr = (ast.Raise | t.CPtr)(stmt_f)
if rn_f is None or rn_f.exc is None:
continue
ek_f: int = rn_f.exc.kind()
is_stop_f: int = 0
if ek_f == ast.ASTKind.Name:
enm_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rn_f.exc)
if enm_f.id is not None and string.strcmp(enm_f.id, "StopIteration") == 0:
is_stop_f = 1
elif ek_f == ast.ASTKind.Call:
ecl_f: ast.Call | t.CPtr = (ast.Call | t.CPtr)(rn_f.exc)
if ecl_f.func is not None and ecl_f.func.kind() == ast.ASTKind.Name:
ecn_f: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ecl_f.func)
if ecn_f.id is not None and string.strcmp(ecn_f.id, "StopIteration") == 0:
is_stop_f = 1
if is_stop_f == 0:
return 1
return 0
# ============================================================
# 创建 LLVM 函数(简单版本,仅声明)
# ============================================================
def create_function(self, pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
name: str,
args_node: ast.AST | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
"""创建 LLVM 函数并添加参数"""
if name is None or mod is None:
return None
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
if func is None:
return None
if args_node is not None:
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
if ags.args is not None:
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
an: t.CSizeT = len(alist)
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
for ai in range(an):
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
if arg is not None and arg.arg is not None:
# t.CVoid 表示空参:跳过
if arg.annotation is not None:
if arg.annotation.kind() == ast.ASTKind.Attribute:
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
continue
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
if arg.annotation is not None:
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.resolve_annotation_type(
pool, arg.annotation, None, None, None)
if resolved is not None:
param_ty = resolved
pname: str = pool.alloc(32)
if pname is not None:
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
llvmlite.add_param(pool, func, param_ty, pname)
return func
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+491
View File
@@ -0,0 +1,491 @@
import t, c
from stdint import *
import ast
import lib.Projectrans.Config as Config
import lib.Projectrans.Utils as Utils
import lib.core.StubMerger as StubMerger
import lib.core.VLogger as VLogger
import llvmlite
import memhub
import stdio
import stdlib
import string
import viperlib
import w32.fileio as fileio
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import lib.core.Handles.HandlesTranslator as HT
# ============================================================
# GenApi - 管线/保留文件访问 Gen 的模块级委托入口(去除 Handles 层)
#
# 由脚本从 Gen 子对象同名方法自动生成:签名取真源方法(含参数类型注解),
# 函数体经 _g_gen 单例调用 gen 子对象。main/BuildPipeline 注入 _g_gen。
# ============================================================
# 全局 gen 单例(main/BuildPipeline 创建 gen 后注入)
_g_gen: Generator.Generator | t.CPtr = None
# ---------------- set_temp_dir(委托 TypeGenBase.set_temp_dir) ----------------
def set_temp_dir(temp_dir: str) -> None:
"""委托到 gen.set_temp_dir(原 Handles 壳)"""
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.TypeGenBase.set_temp_dir(temp_dir)
# ---------------- set_current_file_imports(委托 ImportsGenMixin.set_current_file) ----------------
def set_current_file_imports(file_path: str) -> None:
"""委托到 gen.set_current_file(原 Handles 壳)"""
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.ImportsGen.set_current_file(file_path)
# ---------------- set_current_file_type(委托 TypeGenResolve.set_current_file) ----------------
def set_current_file_type(file_path: str) -> None:
"""委托到 gen.set_current_file(原 Handles 壳)"""
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.TypeGenResolve.set_current_file(file_path)
# ---------------- set_current_module_sha1(委托 TypeGenBase.set_current_module_sha1) ----------------
def set_current_module_sha1(sha1: str) -> None:
"""委托到 gen.set_current_module_sha1(原 Handles 壳)"""
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.TypeGenBase.set_current_module_sha1(sha1)
# ---------------- clear_trace(委托 TypeGenBase.clear_trace) ----------------
def clear_trace() -> None:
"""委托到 gen.clear_trace(原 Handles 壳)"""
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.TypeGenBase.clear_trace()
# ---------------- clear_cdefine_constants(委托 TypeGenCDef.clear_cdefine_constants) ----------------
def clear_cdefine_constants() -> None:
"""委托到 gen.clear_cdefine_constants(原 Handles 壳)"""
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.TypeGenCDef.clear_cdefine_constants()
# ---------------- clear_ctypedefs(委托 TypeGenCType.clear_ctypedefs) ----------------
def clear_ctypedefs() -> None:
"""委托到 gen.clear_ctypedefs(原 Handles 壳)"""
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.TypeGenCType.clear_ctypedefs()
# ---------------- RegisterCTypedefFromSource(委托 TypeGenCType.register_ctypedef_from_source) ----------------
def RegisterCTypedefFromSource(pool: memhub.MemBuddy | t.CPtr, src: str) -> int:
"""委托到 gen.register_ctypedef_from_source(原 Handles 壳)"""
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.TypeGenCType.register_ctypedef_from_source(pool, src)
return 0
# ---------------- dump_parse_traceback(委托 TypeGenErr.dump_parse_traceback) ----------------
def dump_parse_traceback(file_path: str) -> None:
"""委托到 gen.dump_parse_traceback(原 Handles 壳)"""
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.TypeGenErr.dump_parse_traceback(file_path)
# ---------------- map_t_type(委托 TypeGenResolve.map_t_type) ----------------
def map_t_type(pool: memhub.MemBuddy | t.CPtr, type_name: str) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.map_t_type(原 Handles 壳)"""
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.TypeGenResolve.map_t_type(pool, type_name)
return None
# ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ----------------
def get_current_file() -> str:
"""委托到 gen.get_current_file(原 Handles 壳)"""
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.TypeGenResolve.get_current_file()
return None
# ---------------- _is_ctypedef_annotation(委托 TypeGenCType._is_ctypedef_annotation) ----------------
def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int:
"""委托到 gen._is_ctypedef_annotation(原 Handles 壳)"""
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.TypeGenCType._is_ctypedef_annotation(annotation)
return 0
# ---------------- resolve_annotation_type(委托 TypeGenResolve.resolve_annotation_type) ----------------
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr, imported_modules: str, from_imports: str, trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.resolve_annotation_type(原 Handles 壳)"""
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.TypeGenResolve.resolve_annotation_type(pool, node, imported_modules, from_imports, trans)
return None
# ---------------- has_decorator_marker(委托 TypeGenErr.has_decorator_marker) ----------------
def has_decorator_marker(node: ast.AST | t.CPtr, marker_name: str) -> int:
"""委托到 gen.has_decorator_marker(原 Handles 壳)"""
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.TypeGenErr.has_decorator_marker(node, marker_name)
return 0
# ---------------- _get_type_name_from_annotation(委托 TypeGenResolve._get_type_name_from_annotation) ----------------
def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr, node: ast.AST | t.CPtr) -> str:
"""委托到 gen._get_type_name_from_annotation(原 Handles 壳)"""
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.TypeGenResolve._get_type_name_from_annotation(pool, node)
return None
# ---------------- register_ctypedef(委托 TypeGenCType.register_ctypedef) ----------------
def register_ctypedef(pool: memhub.MemBuddy | t.CPtr, name: str, type_str: str) -> None:
"""委托到 gen.register_ctypedef(原 Handles 壳)"""
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.TypeGenCType.register_ctypedef(pool, name, type_str)
# ---------------- lookup_cdefine_constant(委托 TypeGenCDef.lookup_cdefine_constant) ----------------
def lookup_cdefine_constant(name: str) -> t.CInt64T:
"""委托到 gen.lookup_cdefine_constant(原 Handles 壳)"""
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.TypeGenCDef.lookup_cdefine_constant(name)
return 0
# ---------------- is_cdefine_found(委托 TypeGenCDef.is_cdefine_found) ----------------
def is_cdefine_found() -> int:
"""委托到 gen.is_cdefine_found(原 Handles 壳)"""
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.TypeGenCDef.is_cdefine_found()
return 0
# ---------------- push_trace(委托 TypeGenBase.push_trace) ----------------
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0) -> None:
"""委托到 gen.push_trace(原 Handles 壳)"""
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.TypeGenBase.push_trace(file_name, lineno, col_start, col_end)
# ---------------- pop_trace(委托 TypeGenBase.pop_trace) ----------------
def pop_trace() -> None:
"""委托到 gen.pop_trace(原 Handles 壳)"""
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.TypeGenBase.pop_trace()
# ---------------- get_temp_dir(委托 TypeGenBase.get_temp_dir) ----------------
def get_temp_dir() -> str:
"""委托到 gen.get_temp_dir(原 Handles 壳)"""
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.TypeGenBase.get_temp_dir()
return None
# ---------------- reset_visible_structs(委托 StructGenMixin.reset_visible_structs) ----------------
def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int) -> None:
"""委托到 gen.reset_visible_structs(原 Handles 壳)"""
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.StructGen.reset_visible_structs(pool, strict)
# ---------------- set_stdlib_alloc(委托 StructGenMixin.set_stdlib_alloc) ----------------
def set_stdlib_alloc(flag: int) -> None:
"""委托到 gen.set_stdlib_alloc(原 Handles 壳)"""
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.StructGen.set_stdlib_alloc(flag)
# ---------------- get_struct_count(委托 StructGenMixin.get_struct_count) ----------------
def get_struct_count() -> int:
"""委托到 gen.get_struct_count(原 Handles 壳)"""
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.StructGen.get_struct_count()
return 0
# ---------------- reset_module_methods_emitted(委托 StructGenMixin.reset_module_methods_emitted) ----------------
def reset_module_methods_emitted(sha1: str) -> int:
"""委托到 gen.reset_module_methods_emitted(原 Handles 壳)"""
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.StructGen.reset_module_methods_emitted(sha1)
return 0
# ---------------- get_struct_type(委托 StructGenMixin.get_struct_type) ----------------
def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.get_struct_type(原 Handles 壳)"""
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.StructGen.get_struct_type(class_name)
return None
# ---------------- add_visible_struct(委托 StructGenMixin.add_visible_struct) ----------------
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str) -> None:
"""委托到 gen.add_visible_struct(原 Handles 壳)"""
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.StructGen.add_visible_struct(pool, name)
# ---------------- compute_package_from_relpath(委托 ImportsGenMixin.compute_package_from_relpath) ----------------
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr, rel_path: str) -> str:
"""委托到 gen.compute_package_from_relpath(原 Handles 壳)"""
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.ImportsGen.compute_package_from_relpath(pool, rel_path)
return None
# ---------------- is_module_imported(委托 ImportsGenMixin.is_module_imported) ----------------
def is_module_imported(imported_modules: str, name: str) -> int:
"""委托到 gen.is_module_imported(原 Handles 壳)"""
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.ImportsGen.is_module_imported(imported_modules, name)
return 0
# ---------------- add_imported_module(委托 ImportsGenMixin.add_imported_module) ----------------
def add_imported_module(pool: memhub.MemBuddy | t.CPtr, imported_modules: str, name: str) -> str:
"""委托到 gen.add_imported_module(原 Handles 壳)"""
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.ImportsGen.add_imported_module(pool, imported_modules, name)
return None
# ---------------- translate_import(委托 ImportsGenMixin.translate_import) ----------------
def translate_import(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
"""委托到 gen.translate_import(原 Handles 壳)"""
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.ImportsGen.translate_import(trans, node)
return 0
# ---------------- translate_import_from_module(委托 ImportsGenMixin.translate_import_from_module) ----------------
def translate_import_from_module(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
"""委托到 gen.translate_import_from_module(原 Handles 壳)"""
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.ImportsGen.translate_import_from_module(trans, node)
return 0
# ---------------- translate_import_from_names(委托 ImportsGenMixin.translate_import_from_names) ----------------
def translate_import_from_names(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
"""委托到 gen.translate_import_from_names(原 Handles 壳)"""
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.ImportsGen.translate_import_from_names(trans, node)
return 0
# ---------------- _get_parent_class(委托 ClassGenBase._get_parent_class) ----------------
def _get_parent_class(cd: ast.ClassDef | t.CPtr, trans: HT.Translator | t.CPtr = None) -> str:
"""委托到 gen._get_parent_class(原 Handles 壳)"""
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.ClassGenBase._get_parent_class(cd, trans)
return None
# ---------------- _register_generic_template(委托 ClassGenGeneric._register_generic_template) ----------------
def _register_generic_template(pool: memhub.MemBuddy | t.CPtr, cd: ast.ClassDef | t.CPtr, module_sha1: str) -> None:
"""委托到 gen._register_generic_template(原 Handles 壳)"""
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.ClassGenGeneric._register_generic_template(pool, cd, module_sha1)
# ---------------- _mangle_name_with_sha1(委托 FuncGenBase._mangle_name_with_sha1) ----------------
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
"""委托到 gen._mangle_name_with_sha1(原 Handles 壳)"""
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.FuncGenBase._mangle_name_with_sha1(sha1, name)
return None
# ---------------- forward_declare_functions(委托 FuncGenDef.forward_declare_functions) ----------------
def forward_declare_functions(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr) -> int:
"""委托到 gen.forward_declare_functions(原 Handles 壳)"""
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.FuncGenDef.forward_declare_functions(trans, tree)
return 0
# ---------------- create_wrapper_main(委托 TranslatorGenMixin.create_wrapper_main) ----------------
def create_wrapper_main(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr, i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""委托到 gen.create_wrapper_main(原 Handles 壳)"""
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.TranslatorGen.create_wrapper_main(trans, tree, i32_ty)
return 0
# ---------------- handle_module_level_var(委托 TranslatorGenMixin.handle_module_level_var) ----------------
def handle_module_level_var(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int:
"""委托到 gen.handle_module_level_var(原 Handles 壳)"""
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.TranslatorGen.handle_module_level_var(trans, node)
return 0
# ---------------- translate_children(委托 TranslatorGenMixin.translate_children) ----------------
def translate_children(trans: HT.Translator | t.CPtr, tree: ast.AST | t.CPtr) -> int:
"""委托到 gen.translate_children(原 Handles 壳)"""
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.TranslatorGen.translate_children(trans, tree)
return 0
# ---------------- init_symbol_table(委托 VarGenMixin.init_symbol_table) ----------------
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> GenTypes.SymbolTable | t.CPtr:
"""委托到 gen.init_symbol_table(原 Handles 壳)"""
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.VarGen.init_symbol_table(pool)
return None
# ---------------- SetTempDir(委托 CallGenBase.SetTempDir) ----------------
def SetTempDir(temp_dir: str) -> None:
"""委托到 gen.SetTempDir(原 Handles 壳)"""
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.CallGenBase.SetTempDir(temp_dir)
# ---------------- find_func_in_module(委托 CallGenBase.find_func_in_module) ----------------
def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr, name: str) -> llvmlite.Function | t.CPtr:
"""委托到 gen.find_func_in_module(原 Handles 壳)"""
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.CallGenBase.find_func_in_module(mod, name)
return None
# ---------------- add_func_to_table(委托 CallGenLeafKit.add_func_to_table) ----------------
def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr, func_count: int, name: str, func: llvmlite.Function | t.CPtr, max_count: int, defaults: t.CVoid | t.CPtr = None, default_count: int = 0, param_count: int = 0, pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""委托到 gen.add_func_to_table(原 Handles 壳)"""
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.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count, defaults, default_count, param_count, pool)
return 0
# ---------------- init_func_table(委托 CallGenLeafKit.init_func_table) ----------------
def init_func_table(pool: memhub.MemBuddy | t.CPtr, max_count: int) -> GenTypes.FuncEntry | t.CPtr:
"""委托到 gen.init_func_table(原 Handles 壳)"""
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.CallGenLeafKit.init_func_table(pool, max_count)
return None
# ---------------- translate_call(委托 CallGenMixin.translate_call) ----------------
def translate_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, node: ast.AST | t.CPtr, funcs_ptr: t.CPtr, func_count: int, trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""委托到 gen.translate_call(原 Handles 壳)"""
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.CallGen.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
return None
# ---------------- translate_printf_call(委托 CallGenLeafKit.translate_printf_call) ----------------
def translate_printf_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, cl: ast.Call | t.CPtr, trans: HT.Translator | t.CPtr = None) -> None:
"""委托到 gen.translate_printf_call(原 Handles 壳)"""
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.CallGenLeafKit.translate_printf_call(pool, builder, mod, cl, trans)
# ---------------- translate_print_call(委托 CallGenLeafKit.translate_print_call) ----------------
def translate_print_call(pool: memhub.MemBuddy | t.CPtr, builder: llvmlite.IRBuilder | t.CPtr, mod: llvmlite.LLVMModule | t.CPtr, cl: ast.Call | t.CPtr, trans: HT.Translator | t.CPtr = None) -> None:
"""委托到 gen.translate_print_call(原 Handles 壳)"""
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.CallGenLeafKit.translate_print_call(pool, builder, mod, cl, trans)
+193
View File
@@ -0,0 +1,193 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
# ============================================================
# GenTypes - Gen 侧共享数据类型与常量(去除 Handles 层迁移目标)
#
# 原分布于 Handles 目录的数据类与常量集中于此,供 Gen 子对象、
# 管线与保留实体文件引用。删除 Handles 目录后统一经本模块访问。
# ============================================================
# ============================================================
# 类编译期元数据(原 HandlesType.CLASS_META_*)
# ============================================================
CLASS_META_PROVIDES: t.CDefine = 1
CLASS_META_REQUIRES: t.CDefine = 2
CLASS_META_REQUIRE_MUST: t.CDefine = 3
# ============================================================
# 属性/静态/类方法元数据(原 HandlesClassDef.META_*)
# ============================================================
META_STATIC: t.CDefine = 1
META_CLASS: t.CDefine = 2
META_PROP_GETTER: t.CDefine = 4
META_PROP_SETTER: t.CDefine = 8
META_PROP_DELETER: t.CDefine = 16
# ============================================================
# 结构体容量(原 HandlesStruct.FIELD_MAX/FIELD_NAME_MAX/PARENT_MAX/MRO_MAX)
# ============================================================
FIELD_MAX: t.CDefine = 256
FIELD_NAME_MAX: t.CDefine = 64
PARENT_MAX: t.CDefine = 64
MRO_MAX: t.CDefine = 64
# ============================================================
# for 迭代序列种类(原 HandlesFor.SEQ_KIND_*)
# ============================================================
SEQ_KIND_RANGE: t.CDefine = 1
SEQ_KIND_STR: t.CDefine = 2
SEQ_KIND_LIST: t.CDefine = 3
# ============================================================
# TraceFrame - 仿 Python Traceback 调用栈帧(原 HandlesType.TraceFrame)
# ============================================================
class TraceFrame:
"""仿 Python Traceback 调用栈帧(push_trace/pop_trace 使用)"""
file_name: str
lineno: int
col_start: int
col_end: int
# ============================================================
# VarEntry - 变量表条目(原 HandlesVar.VarEntry)
# ============================================================
class VarEntry:
"""变量表条目"""
Name: str
Alloca: llvmlite.Value | t.CPtr
Used: t.CInt
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
# ============================================================
# Scope - 作用域节点(原 HandlesVar.Scope)
# ============================================================
@t.NoVTable
class Scope:
"""作用域节点"""
Parent: Scope | t.CPtr
Vars: VarEntry | t.CPtr
VarCount: t.CInt
Kind: t.CInt
# ============================================================
# SymbolTable - 嵌套作用域符号表(原 HandlesVar.SymbolTable)
# ============================================================
@t.NoVTable
class SymbolTable:
"""嵌套作用域符号表"""
Pool: memhub.MemBuddy | t.CPtr
Root: Scope | t.CPtr
Current: Scope | t.CPtr
# ============================================================
# FieldEntry - 字段信息条目(原 HandlesStruct.FieldEntry)
# ============================================================
class FieldEntry:
Name: str # 字段名(字符串)
Index: int # 字段在结构体中的索引
Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型
DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值)
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
# ============================================================
# StructEntry - 结构体注册条目(原 HandlesStruct.StructEntry)
# ============================================================
@t.NoVTable
class StructEntry:
Name: str # 类名
Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType
FieldCount: int # 字段数量
Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位)
IsUnion: int # 1=联合体 / 0=普通结构体
IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体
HasInit: int # 1=有__init__方法 / 0=无
HasNew: int # 1=有__new__方法 / 0=无
HasVTable: int # 1=有虚表 / 0=无虚表
IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记
ParentName: str # 父类名(None=无父类,多继承时为第一个父类,兼容旧调用)
ParentNames: t.CSizeT | t.CPtr # 多继承父类名数组(每元素 str 指针,ParentCount 个;stdlib 深拷贝)
ParentCount: t.CInt # 父类数量(0=无父类,1=单继承,>1=多继承)
VTableMethodCount: int # 虚表中的方法数量
VTableMethods: str # 虚表方法名数组(每个方法名 str,VTableMethodCount 个)
ModuleSha1: str # 定义该类的模块 SHA1(None=无 SHA1)
MethodsEmitted: int # 1=方法体已翻译 / 0=未译(Phase 1a mark_only 未译,Phase B 据此补译)
SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板
# sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted
# 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译
# → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
# ============================================================
# EnumMember - 枚举成员(原 HandlesEnum.EnumMember)
# ============================================================
class EnumMember:
Name: str # 成员名(字符串)
Value: t.CInt64T # 成员的整数值
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
# ============================================================
# EnumEntry - 枚举类型条目(原 HandlesEnum.EnumEntry)
# ============================================================
@t.NoVTable
class EnumEntry:
Name: str # 枚举类名
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
MemberCount: int # 成员数量
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
# ============================================================
# AsmOperand - 内联汇编操作数条目(原 HandlesExprCall.AsmOperand)
# ============================================================
class AsmOperand:
"""内联汇编操作数条目"""
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
Constraint: str # 约束字符串 (如 "r", "=r")
IsOutput: int # 1=输出, 0=输入
# ============================================================
# FuncEntry - 函数表条目(原 HandlesExprCall.FuncEntry)
# ============================================================
@t.NoVTable
class FuncEntry:
"""函数表条目"""
Name: str
Func: llvmlite.Function | t.CPtr
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量
ParamCount: int # 形参数量(不含 self)
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
TypeStr: str
# ============================================================
# FuncDefaultsEntry - 默认参数表条目(原 HandlesExprCall.FuncDefaultsEntry)
# ============================================================
@t.NoVTable
class FuncDefaultsEntry:
"""默认参数表条目"""
Name: str
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
DefaultCount: int
ParamCount: int # 形参数量(不含 self)
# 常量快照(stdlib 分配,跨文件永久存活):
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
+405 -179
View File
@@ -1,17 +1,21 @@
import string
import lib.core.CompilerFactory as CompilerFactory
import t, c
from stdint import *
import stdio
import stdlib
import memhub
import llvmlite
import lib.core.Gen.BaseGenMixin as BaseGenMixin
import lib.core.Gen.TypeGenMixin as TypeGenMixin
import lib.core.Gen.TypeGenBase as TypeGenBase
import lib.core.Gen.TypeGenMixin as TypeGenMixin
import lib.core.Gen.TypeGenCDef as TypeGenCDef
import lib.core.Gen.TypeGenCType as TypeGenCType
import lib.core.Gen.TypeGenResolve as TypeGenResolve
import lib.core.Gen.TypeGenErr as TypeGenErr
import lib.core.Gen.StructGenMixin as StructGenMixin
import lib.core.Gen.ExprGenMixin as ExprGenMixin
import lib.core.Gen.ExprGenBase as ExprGenBase
import lib.core.Gen.ExprGenMixin as ExprGenMixin
import lib.core.Gen.ExprGenConst as ExprGenConst
import lib.core.Gen.ExprGenFstr as ExprGenFstr
import lib.core.Gen.ExprGenOps as ExprGenOps
@@ -19,215 +23,437 @@ import lib.core.Gen.ExprGenCdef as ExprGenCdef
import lib.core.Gen.ExprGenName as ExprGenName
import lib.core.Gen.ExprGenAttr as ExprGenAttr
import lib.core.Gen.ExprGenCls as ExprGenCls
import lib.core.Gen.CallGenMixin as CallGenMixin
import lib.core.Gen.CallGenBase as CallGenBase
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
import lib.core.Gen.CallGenCBuiltin as CallGenCBuiltin
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
import lib.core.Gen.CallGenCtor as CallGenCtor
import lib.core.Gen.CallGenCall as CallGenCall
import lib.core.Gen.CallGenProp as CallGenProp
import lib.core.Gen.CallGenFd as CallGenFd
import lib.core.Gen.CallGenMixin as CallGenMixin
import lib.core.Gen.CallGenDispatch as CallGenDispatch
import lib.core.Gen.CallGenLib as CallGenLib
import lib.core.Gen.CallGenVt as CallGenVt
import lib.core.Gen.CallGenVa as CallGenVa
import lib.core.Gen.CallGenLib as CallGenLib
import lib.core.Gen.CallGenDispatch as CallGenDispatch
import lib.core.Gen.CallGenProp as CallGenProp
import lib.core.Gen.CallGenFd as CallGenFd
import lib.core.Gen.FuncGenBase as FuncGenBase
import lib.core.Gen.FuncGenDef as FuncGenDef
import lib.core.Gen.FuncGenMixin as FuncGenMixin
import lib.core.Gen.ClassGenMixin as ClassGenMixin
import lib.core.Gen.ClassGenBase as ClassGenBase
import lib.core.Gen.ClassGenMixin as ClassGenMixin
import lib.core.Gen.ClassGenEnum as ClassGenEnum
import lib.core.Gen.ClassGenGeneric as ClassGenGeneric
import lib.core.Gen.ClassGenVTable as ClassGenVTable
import lib.core.Gen.ClassGenDef as ClassGenDef
import lib.core.Gen.ImportsGenMixin as ImportsGenMixin
import lib.core.Gen.StmtGenCifMixin as StmtGenCifMixin
import lib.core.Gen.StmtGenDeclMixin as StmtGenDeclMixin
import lib.core.Gen.StmtGenMixin as StmtGenMixin
import lib.core.Gen.MatchGenMixin as MatchGenMixin
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
# ============================================================
# Generator - 生成器(P1 骨架 + P2 多继承 Mixin 组合)
# Generator - 生成器(双向引用组合架构)
#
# 对象化重构宿主(wiki/14-oo-refactor.md):
# @t.NoVTable + 多继承(BaseGen 状态 + TypeGen 类型映射),方法沿
# MRO 直接调用(Viper 多继承已支持,M1-M4)。后续 P3-P6 追加
# StructGen/ExprGen/CallGen/FuncGen/ClassGen/StmtGen/ImportsGen Mixin。
#
# 注意:Viper NoVTable 继承只合并字段、不转发父类方法符号(子类调
# 父类方法 mangle 成子类名 → undefined reference),因此字段初始化
# 全部内联,不调用父类 Init* 方法。
# 不再 46 路多继承 Mixin;改为组合:Generator 持所有 GenMixin
# 子对象指针(永久池分配,全生命周期),每个 Mixin 持 Gen 回指。
# 跨子对象访问 = self.Gen.<Mixin 字段>.<字段/方法>(链式有风险,
# 统一用中间变量取子对象再访问)。高亮可推导(显式类型注解)。
# ============================================================
@t.NoVTable
class Generator(BaseGenMixin.BaseGenMixin, TypeGenMixin.TypeGenMixin,
TypeGenBase.TypeGenBase, TypeGenCDef.TypeGenCDef,
TypeGenCType.TypeGenCType, TypeGenResolve.TypeGenResolve,
TypeGenErr.TypeGenErr,
StructGenMixin.StructGenMixin, ExprGenMixin.ExprGenMixin,
ExprGenBase.ExprGenBase, ExprGenConst.ExprGenConst,
ExprGenFstr.ExprGenFstr, ExprGenOps.ExprGenOps,
ExprGenCdef.ExprGenCdef, ExprGenName.ExprGenName,
ExprGenAttr.ExprGenAttr, ExprGenCls.ExprGenCls,
CallGenMixin.CallGenMixin, CallGenBase.CallGenBase,
CallGenLeafKit.CallGenLeafKit, CallGenCBuiltin.CallGenCBuiltin,
CallGenCtor.CallGenCtor, CallGenCall.CallGenCall,
CallGenProp.CallGenProp, CallGenFd.CallGenFd,
CallGenVt.CallGenVt, CallGenVa.CallGenVa,
CallGenLib.CallGenLib, CallGenDispatch.CallGenDispatch,
FuncGenBase.FuncGenBase, FuncGenDef.FuncGenDef,
FuncGenMixin.FuncGenMixin,
ClassGenMixin.ClassGenMixin, ClassGenBase.ClassGenBase,
ClassGenEnum.ClassGenEnum, ClassGenGeneric.ClassGenGeneric,
ClassGenVTable.ClassGenVTable, ClassGenDef.ClassGenDef,
ImportsGenMixin.ImportsGenMixin,
StmtGenMixin.StmtGenMixin, MatchGenMixin.MatchGenMixin,
AssignGenMixin.AssignGenMixin,
VarGenMixin.VarGenMixin, TranslatorGenMixin.TranslatorGenMixin):
"""生成器:多继承 Mixin 组合(对象化迁移宿主)"""
class Generator:
"""生成器:持所有 GenMixin 子对象指针(双向引用组合)"""
# ---- 子对象指针(46 个,永久池) ----
BaseGen: BaseGenMixin.BaseGenMixin | t.CPtr
TypeGenBase: TypeGenBase.TypeGenBase | t.CPtr
TypeGen: TypeGenMixin.TypeGenMixin | t.CPtr
TypeGenCDef: TypeGenCDef.TypeGenCDef | t.CPtr
TypeGenCType: TypeGenCType.TypeGenCType | t.CPtr
TypeGenResolve: TypeGenResolve.TypeGenResolve | t.CPtr
TypeGenErr: TypeGenErr.TypeGenErr | t.CPtr
StructGen: StructGenMixin.StructGenMixin | t.CPtr
ExprGenBase: ExprGenBase.ExprGenBase | t.CPtr
ExprGen: ExprGenMixin.ExprGenMixin | t.CPtr
ExprGenConst: ExprGenConst.ExprGenConst | t.CPtr
ExprGenFstr: ExprGenFstr.ExprGenFstr | t.CPtr
ExprGenOps: ExprGenOps.ExprGenOps | t.CPtr
ExprGenCdef: ExprGenCdef.ExprGenCdef | t.CPtr
ExprGenName: ExprGenName.ExprGenName | t.CPtr
ExprGenAttr: ExprGenAttr.ExprGenAttr | t.CPtr
ExprGenCls: ExprGenCls.ExprGenCls | t.CPtr
CallGenBase: CallGenBase.CallGenBase | t.CPtr
CallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin | t.CPtr
CallGenLeafKit: CallGenLeafKit.CallGenLeafKit | t.CPtr
CallGenCtor: CallGenCtor.CallGenCtor | t.CPtr
CallGenCall: CallGenCall.CallGenCall | t.CPtr
CallGen: CallGenMixin.CallGenMixin | t.CPtr
CallGenDispatch: CallGenDispatch.CallGenDispatch | t.CPtr
CallGenLib: CallGenLib.CallGenLib | t.CPtr
CallGenVt: CallGenVt.CallGenVt | t.CPtr
CallGenVa: CallGenVa.CallGenVa | t.CPtr
CallGenProp: CallGenProp.CallGenProp | t.CPtr
CallGenFd: CallGenFd.CallGenFd | t.CPtr
FuncGenBase: FuncGenBase.FuncGenBase | t.CPtr
FuncGenDef: FuncGenDef.FuncGenDef | t.CPtr
FuncGen: FuncGenMixin.FuncGenMixin | t.CPtr
ClassGenBase: ClassGenBase.ClassGenBase | t.CPtr
ClassGen: ClassGenMixin.ClassGenMixin | t.CPtr
ClassGenEnum: ClassGenEnum.ClassGenEnum | t.CPtr
ClassGenGeneric: ClassGenGeneric.ClassGenGeneric | t.CPtr
ClassGenVTable: ClassGenVTable.ClassGenVTable | t.CPtr
ClassGenDef: ClassGenDef.ClassGenDef | t.CPtr
ImportsGen: ImportsGenMixin.ImportsGenMixin | t.CPtr
StmtGenCif: StmtGenCifMixin.StmtGenCifMixin | t.CPtr
StmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin | t.CPtr
StmtGen: StmtGenMixin.StmtGenMixin | t.CPtr
MatchGen: MatchGenMixin.MatchGenMixin | t.CPtr
AssignGen: AssignGenMixin.AssignGenMixin | t.CPtr
VarGen: VarGenMixin.VarGenMixin | t.CPtr
TranslatorGen: TranslatorGenMixin.TranslatorGenMixin | t.CPtr
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
if self is None:
return
# ---- BaseGenMixin 字段 ----
self.Pool = pool
self.Module = None
self.Builder = None
self.SymTab = None
self.Funcs = None
self.FuncCount = 0
self.ImportedModules = None
self.FromImports = None
self.ModuleSha1 = None
self.CurFunc = None
self.CurBuilder = None
self.CurClassName = None
# ---- TypeGenMixin 字段 ----
self.TraceFrames = None
self.TraceCount = 0
self.TempDir = None
self.GenericTpNames = None
self.GenericTypeArgs = None
self.GenericCtxStack = None
self.GenericCtxDepth = 0
self.CDefineNames = None
self.CDefineValues = None
self.CDefineDoubleFlags = None
self.CDefineStrFlags = None
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
self.CDefineFound = 0
# 跨模块 CDefine 查找缓存(perm_pool 永久,跨文件复用)
self.XmodCdefNames = None
self.XmodCdefValues = None
self.XmodCdefDoubleFlags = None
self.XmodCdefStrFlags = None
self.CurrentModuleSha1 = None
self.CTypedefNames = None
self.CTypedefTypeStrs = None
self.CTypedefFound = 0
self.CTypedefResolveDepth = 0
self.CTypedefVisiting = None
self.CurrentFile = None
self.ConstEvalOk = 0
# ---- StructGenMixin 字段 ----
self.StructTable = None
self.StructCount = 0
self.StdlibAlloc = 0
self.VisibleStructs = None
self.StrictVisibility = 0
# OOM 语句级诊断:translate_stmt 限频打印 used(定位单文件翻译暴涨起点)
self.DiagStmtCount = 0
# ---- CallGenMixin 字段 ----
self.CexportSha1Arr = None
self.CexportFuncArr = None
self.CexportCount = 0
self.LLVMIRRegSeq = 0
self.TempDir = None
self.TempDirLen = 0
self.ClosureNames = None
self.ClosureCount = 0
self.FuncptrNames = None
self.FuncptrRets = None
self.FuncptrCount = 0
self.GlobalFuncs = None
self.GlobalFuncCount = 0
self.GlobalDefaults = None
self.GlobalDefaultsCount = 0
# ---- ClassGenMixin 字段 ----
self.MethodMetaKeys = None
self.MethodMetaFlags = None
self.MethodMetaCount = 0
self.RenumClassNames = None
self.RenumClassVariantCounts = None
self.RenumVariantNames = None
self.RenumVariantTags = None
self.RenumClassCount = 0
self.RenumAliasClass = None
self.RenumAliasField = None
self.RenumAliasIndex = None
self.RenumAliasCount = 0
self.SpecKeys = None
self.SpecNames = None
self.SpecCount = 0
self.GenericClassNames = None
self.GenericClassNodes = None
self.GenericClassSha1s = None
self.GenericClassFiles = None
self.GenericClassTpParams = None
self.VtFullNames = None
self.VtMethodNames = None
self.VtParentSha1s = None
self.VtMethodCount = 0
# ---- ClassGenBase 补漏字段(阶段 D 拆分新增,此前未初始化:
# 结构体是 malloc 分配,未初始化字段是内存垃圾——非 null 垃圾
# 指针能通过 `is not None` 检查,导致 is_exception_name 等查询
# 直接 strcmp 越界崩溃;int 垃圾则导致循环次数失控) ----
self.RenumAliasTy = None
self.RenumAliasVariant = None
self.ClassMetaKinds = None
self.ClassMetaClss = None
self.ClassMetaFields = None
self.ClassMetaCount = 0
self.DecoratorFuncCount = 0
self.DecoratorFuncNames = None
self.DecoratorWrapNames = None
self.DecoratorArgs = None
# 异常类注册表(_ensure_exception_tables 仍保留懒分配,但
# ExceptionNames 必须初始化为 null——否则 `is not None` 误判垃圾
# 指针为已初始化,跳过分配直接查表 → strcmp 越界)
self.ExceptionCount = 0
self.ExceptionNames = None
self.ExceptionParents = None
self.ExceptionCodes = None
self.NextExceptionCode = 0
self._exception_codes_tmp_count = 0
self.GenericSpecDepth = 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
# ---- ExprGenMixin docstring 字段(__doc__ 魔法属性支持)----
self.DocKeys = None
self.DocValues = None
self.DocCount = 0
# OOM 诊断计数:跨模块 CDefine 查找调用次数
self.DiagCDefineCount = 0
self.DiagNameValueCount = 0
self.DiagTranslateValueCount = 0
# ---- alloc 46 个子对象 + 回指(永久池,fail-fast) ----
SubBaseGen: BaseGenMixin.BaseGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(BaseGenMixin.BaseGenMixin.__sizeof__())
if SubBaseGen is None:
stdio.printf("FAIL: BaseGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubBaseGen, 0, BaseGenMixin.BaseGenMixin.__sizeof__())
SubBaseGen.Gen = self
self.BaseGen = SubBaseGen
SubTypeGenBase: TypeGenBase.TypeGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenBase.TypeGenBase.__sizeof__())
if SubTypeGenBase is None:
stdio.printf("FAIL: TypeGenBase alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGenBase, 0, TypeGenBase.TypeGenBase.__sizeof__())
SubTypeGenBase.Gen = self
self.TypeGenBase = SubTypeGenBase
SubTypeGen: TypeGenMixin.TypeGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenMixin.TypeGenMixin.__sizeof__())
if SubTypeGen is None:
stdio.printf("FAIL: TypeGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGen, 0, TypeGenMixin.TypeGenMixin.__sizeof__())
SubTypeGen.Gen = self
self.TypeGen = SubTypeGen
SubTypeGenCDef: TypeGenCDef.TypeGenCDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenCDef.TypeGenCDef.__sizeof__())
if SubTypeGenCDef is None:
stdio.printf("FAIL: TypeGenCDef alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGenCDef, 0, TypeGenCDef.TypeGenCDef.__sizeof__())
SubTypeGenCDef.Gen = self
self.TypeGenCDef = SubTypeGenCDef
SubTypeGenCType: TypeGenCType.TypeGenCType | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenCType.TypeGenCType.__sizeof__())
if SubTypeGenCType is None:
stdio.printf("FAIL: TypeGenCType alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGenCType, 0, TypeGenCType.TypeGenCType.__sizeof__())
SubTypeGenCType.Gen = self
self.TypeGenCType = SubTypeGenCType
SubTypeGenResolve: TypeGenResolve.TypeGenResolve | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenResolve.TypeGenResolve.__sizeof__())
if SubTypeGenResolve is None:
stdio.printf("FAIL: TypeGenResolve alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGenResolve, 0, TypeGenResolve.TypeGenResolve.__sizeof__())
SubTypeGenResolve.Gen = self
self.TypeGenResolve = SubTypeGenResolve
SubTypeGenErr: TypeGenErr.TypeGenErr | t.CPtr = CompilerFactory.get_perm_pool().alloc(TypeGenErr.TypeGenErr.__sizeof__())
if SubTypeGenErr is None:
stdio.printf("FAIL: TypeGenErr alloc failed\n")
stdlib.exit(1)
string.memset(SubTypeGenErr, 0, TypeGenErr.TypeGenErr.__sizeof__())
SubTypeGenErr.Gen = self
self.TypeGenErr = SubTypeGenErr
SubStructGen: StructGenMixin.StructGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StructGenMixin.StructGenMixin.__sizeof__())
if SubStructGen is None:
stdio.printf("FAIL: StructGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubStructGen, 0, StructGenMixin.StructGenMixin.__sizeof__())
SubStructGen.Gen = self
self.StructGen = SubStructGen
SubExprGenBase: ExprGenBase.ExprGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenBase.ExprGenBase.__sizeof__())
if SubExprGenBase is None:
stdio.printf("FAIL: ExprGenBase alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenBase, 0, ExprGenBase.ExprGenBase.__sizeof__())
SubExprGenBase.Gen = self
self.ExprGenBase = SubExprGenBase
SubExprGen: ExprGenMixin.ExprGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenMixin.ExprGenMixin.__sizeof__())
if SubExprGen is None:
stdio.printf("FAIL: ExprGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGen, 0, ExprGenMixin.ExprGenMixin.__sizeof__())
SubExprGen.Gen = self
self.ExprGen = SubExprGen
SubExprGenConst: ExprGenConst.ExprGenConst | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenConst.ExprGenConst.__sizeof__())
if SubExprGenConst is None:
stdio.printf("FAIL: ExprGenConst alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenConst, 0, ExprGenConst.ExprGenConst.__sizeof__())
SubExprGenConst.Gen = self
self.ExprGenConst = SubExprGenConst
SubExprGenFstr: ExprGenFstr.ExprGenFstr | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenFstr.ExprGenFstr.__sizeof__())
if SubExprGenFstr is None:
stdio.printf("FAIL: ExprGenFstr alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenFstr, 0, ExprGenFstr.ExprGenFstr.__sizeof__())
SubExprGenFstr.Gen = self
self.ExprGenFstr = SubExprGenFstr
SubExprGenOps: ExprGenOps.ExprGenOps | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenOps.ExprGenOps.__sizeof__())
if SubExprGenOps is None:
stdio.printf("FAIL: ExprGenOps alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenOps, 0, ExprGenOps.ExprGenOps.__sizeof__())
SubExprGenOps.Gen = self
self.ExprGenOps = SubExprGenOps
SubExprGenCdef: ExprGenCdef.ExprGenCdef | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenCdef.ExprGenCdef.__sizeof__())
if SubExprGenCdef is None:
stdio.printf("FAIL: ExprGenCdef alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenCdef, 0, ExprGenCdef.ExprGenCdef.__sizeof__())
SubExprGenCdef.Gen = self
self.ExprGenCdef = SubExprGenCdef
SubExprGenName: ExprGenName.ExprGenName | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenName.ExprGenName.__sizeof__())
if SubExprGenName is None:
stdio.printf("FAIL: ExprGenName alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenName, 0, ExprGenName.ExprGenName.__sizeof__())
SubExprGenName.Gen = self
self.ExprGenName = SubExprGenName
SubExprGenAttr: ExprGenAttr.ExprGenAttr | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenAttr.ExprGenAttr.__sizeof__())
if SubExprGenAttr is None:
stdio.printf("FAIL: ExprGenAttr alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenAttr, 0, ExprGenAttr.ExprGenAttr.__sizeof__())
SubExprGenAttr.Gen = self
self.ExprGenAttr = SubExprGenAttr
SubExprGenCls: ExprGenCls.ExprGenCls | t.CPtr = CompilerFactory.get_perm_pool().alloc(ExprGenCls.ExprGenCls.__sizeof__())
if SubExprGenCls is None:
stdio.printf("FAIL: ExprGenCls alloc failed\n")
stdlib.exit(1)
string.memset(SubExprGenCls, 0, ExprGenCls.ExprGenCls.__sizeof__())
SubExprGenCls.Gen = self
self.ExprGenCls = SubExprGenCls
SubCallGenBase: CallGenBase.CallGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenBase.CallGenBase.__sizeof__())
if SubCallGenBase is None:
stdio.printf("FAIL: CallGenBase alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenBase, 0, CallGenBase.CallGenBase.__sizeof__())
SubCallGenBase.Gen = self
self.CallGenBase = SubCallGenBase
SubCallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
if SubCallGenCBuiltin is None:
stdio.printf("FAIL: CallGenCBuiltin alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenCBuiltin, 0, CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
SubCallGenCBuiltin.Gen = self
self.CallGenCBuiltin = SubCallGenCBuiltin
SubCallGenLeafKit: CallGenLeafKit.CallGenLeafKit | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenLeafKit.CallGenLeafKit.__sizeof__())
if SubCallGenLeafKit is None:
stdio.printf("FAIL: CallGenLeafKit alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenLeafKit, 0, CallGenLeafKit.CallGenLeafKit.__sizeof__())
SubCallGenLeafKit.Gen = self
self.CallGenLeafKit = SubCallGenLeafKit
SubCallGenCtor: CallGenCtor.CallGenCtor | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCtor.CallGenCtor.__sizeof__())
if SubCallGenCtor is None:
stdio.printf("FAIL: CallGenCtor alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenCtor, 0, CallGenCtor.CallGenCtor.__sizeof__())
SubCallGenCtor.Gen = self
self.CallGenCtor = SubCallGenCtor
SubCallGenCall: CallGenCall.CallGenCall | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenCall.CallGenCall.__sizeof__())
if SubCallGenCall is None:
stdio.printf("FAIL: CallGenCall alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenCall, 0, CallGenCall.CallGenCall.__sizeof__())
SubCallGenCall.Gen = self
self.CallGenCall = SubCallGenCall
SubCallGen: CallGenMixin.CallGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenMixin.CallGenMixin.__sizeof__())
if SubCallGen is None:
stdio.printf("FAIL: CallGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGen, 0, CallGenMixin.CallGenMixin.__sizeof__())
SubCallGen.Gen = self
self.CallGen = SubCallGen
SubCallGenDispatch: CallGenDispatch.CallGenDispatch | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenDispatch.CallGenDispatch.__sizeof__())
if SubCallGenDispatch is None:
stdio.printf("FAIL: CallGenDispatch alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenDispatch, 0, CallGenDispatch.CallGenDispatch.__sizeof__())
SubCallGenDispatch.Gen = self
self.CallGenDispatch = SubCallGenDispatch
SubCallGenLib: CallGenLib.CallGenLib | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenLib.CallGenLib.__sizeof__())
if SubCallGenLib is None:
stdio.printf("FAIL: CallGenLib alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenLib, 0, CallGenLib.CallGenLib.__sizeof__())
SubCallGenLib.Gen = self
self.CallGenLib = SubCallGenLib
SubCallGenVt: CallGenVt.CallGenVt | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenVt.CallGenVt.__sizeof__())
if SubCallGenVt is None:
stdio.printf("FAIL: CallGenVt alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenVt, 0, CallGenVt.CallGenVt.__sizeof__())
SubCallGenVt.Gen = self
self.CallGenVt = SubCallGenVt
SubCallGenVa: CallGenVa.CallGenVa | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenVa.CallGenVa.__sizeof__())
if SubCallGenVa is None:
stdio.printf("FAIL: CallGenVa alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenVa, 0, CallGenVa.CallGenVa.__sizeof__())
SubCallGenVa.Gen = self
self.CallGenVa = SubCallGenVa
SubCallGenProp: CallGenProp.CallGenProp | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenProp.CallGenProp.__sizeof__())
if SubCallGenProp is None:
stdio.printf("FAIL: CallGenProp alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenProp, 0, CallGenProp.CallGenProp.__sizeof__())
SubCallGenProp.Gen = self
self.CallGenProp = SubCallGenProp
SubCallGenFd: CallGenFd.CallGenFd | t.CPtr = CompilerFactory.get_perm_pool().alloc(CallGenFd.CallGenFd.__sizeof__())
if SubCallGenFd is None:
stdio.printf("FAIL: CallGenFd alloc failed\n")
stdlib.exit(1)
string.memset(SubCallGenFd, 0, CallGenFd.CallGenFd.__sizeof__())
SubCallGenFd.Gen = self
self.CallGenFd = SubCallGenFd
SubFuncGenBase: FuncGenBase.FuncGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenBase.FuncGenBase.__sizeof__())
if SubFuncGenBase is None:
stdio.printf("FAIL: FuncGenBase alloc failed\n")
stdlib.exit(1)
string.memset(SubFuncGenBase, 0, FuncGenBase.FuncGenBase.__sizeof__())
SubFuncGenBase.Gen = self
self.FuncGenBase = SubFuncGenBase
SubFuncGenDef: FuncGenDef.FuncGenDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenDef.FuncGenDef.__sizeof__())
if SubFuncGenDef is None:
stdio.printf("FAIL: FuncGenDef alloc failed\n")
stdlib.exit(1)
string.memset(SubFuncGenDef, 0, FuncGenDef.FuncGenDef.__sizeof__())
SubFuncGenDef.Gen = self
self.FuncGenDef = SubFuncGenDef
SubFuncGen: FuncGenMixin.FuncGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(FuncGenMixin.FuncGenMixin.__sizeof__())
if SubFuncGen is None:
stdio.printf("FAIL: FuncGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubFuncGen, 0, FuncGenMixin.FuncGenMixin.__sizeof__())
SubFuncGen.Gen = self
self.FuncGen = SubFuncGen
SubClassGenBase: ClassGenBase.ClassGenBase | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenBase.ClassGenBase.__sizeof__())
if SubClassGenBase is None:
stdio.printf("FAIL: ClassGenBase alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGenBase, 0, ClassGenBase.ClassGenBase.__sizeof__())
SubClassGenBase.Gen = self
self.ClassGenBase = SubClassGenBase
SubClassGen: ClassGenMixin.ClassGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenMixin.ClassGenMixin.__sizeof__())
if SubClassGen is None:
stdio.printf("FAIL: ClassGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGen, 0, ClassGenMixin.ClassGenMixin.__sizeof__())
SubClassGen.Gen = self
self.ClassGen = SubClassGen
SubClassGenEnum: ClassGenEnum.ClassGenEnum | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenEnum.ClassGenEnum.__sizeof__())
if SubClassGenEnum is None:
stdio.printf("FAIL: ClassGenEnum alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGenEnum, 0, ClassGenEnum.ClassGenEnum.__sizeof__())
SubClassGenEnum.Gen = self
self.ClassGenEnum = SubClassGenEnum
SubClassGenGeneric: ClassGenGeneric.ClassGenGeneric | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenGeneric.ClassGenGeneric.__sizeof__())
if SubClassGenGeneric is None:
stdio.printf("FAIL: ClassGenGeneric alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGenGeneric, 0, ClassGenGeneric.ClassGenGeneric.__sizeof__())
SubClassGenGeneric.Gen = self
self.ClassGenGeneric = SubClassGenGeneric
SubClassGenVTable: ClassGenVTable.ClassGenVTable | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenVTable.ClassGenVTable.__sizeof__())
if SubClassGenVTable is None:
stdio.printf("FAIL: ClassGenVTable alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGenVTable, 0, ClassGenVTable.ClassGenVTable.__sizeof__())
SubClassGenVTable.Gen = self
self.ClassGenVTable = SubClassGenVTable
SubClassGenDef: ClassGenDef.ClassGenDef | t.CPtr = CompilerFactory.get_perm_pool().alloc(ClassGenDef.ClassGenDef.__sizeof__())
if SubClassGenDef is None:
stdio.printf("FAIL: ClassGenDef alloc failed\n")
stdlib.exit(1)
string.memset(SubClassGenDef, 0, ClassGenDef.ClassGenDef.__sizeof__())
SubClassGenDef.Gen = self
self.ClassGenDef = SubClassGenDef
SubImportsGen: ImportsGenMixin.ImportsGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(ImportsGenMixin.ImportsGenMixin.__sizeof__())
if SubImportsGen is None:
stdio.printf("FAIL: ImportsGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubImportsGen, 0, ImportsGenMixin.ImportsGenMixin.__sizeof__())
SubImportsGen.Gen = self
self.ImportsGen = SubImportsGen
SubStmtGenCif: StmtGenCifMixin.StmtGenCifMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
if SubStmtGenCif is None:
stdio.printf("FAIL: StmtGenCifMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubStmtGenCif, 0, StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
SubStmtGenCif.Gen = self
self.StmtGenCif = SubStmtGenCif
SubStmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
if SubStmtGenDecl is None:
stdio.printf("FAIL: StmtGenDeclMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubStmtGenDecl, 0, StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
SubStmtGenDecl.Gen = self
self.StmtGenDecl = SubStmtGenDecl
SubStmtGen: StmtGenMixin.StmtGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(StmtGenMixin.StmtGenMixin.__sizeof__())
if SubStmtGen is None:
stdio.printf("FAIL: StmtGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubStmtGen, 0, StmtGenMixin.StmtGenMixin.__sizeof__())
SubStmtGen.Gen = self
self.StmtGen = SubStmtGen
SubMatchGen: MatchGenMixin.MatchGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(MatchGenMixin.MatchGenMixin.__sizeof__())
if SubMatchGen is None:
stdio.printf("FAIL: MatchGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubMatchGen, 0, MatchGenMixin.MatchGenMixin.__sizeof__())
SubMatchGen.Gen = self
self.MatchGen = SubMatchGen
SubAssignGen: AssignGenMixin.AssignGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(AssignGenMixin.AssignGenMixin.__sizeof__())
if SubAssignGen is None:
stdio.printf("FAIL: AssignGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubAssignGen, 0, AssignGenMixin.AssignGenMixin.__sizeof__())
SubAssignGen.Gen = self
self.AssignGen = SubAssignGen
SubVarGen: VarGenMixin.VarGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(VarGenMixin.VarGenMixin.__sizeof__())
if SubVarGen is None:
stdio.printf("FAIL: VarGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubVarGen, 0, VarGenMixin.VarGenMixin.__sizeof__())
SubVarGen.Gen = self
self.VarGen = SubVarGen
SubTranslatorGen: TranslatorGenMixin.TranslatorGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
if SubTranslatorGen is None:
stdio.printf("FAIL: TranslatorGenMixin alloc failed\n")
stdlib.exit(1)
string.memset(SubTranslatorGen, 0, TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
SubTranslatorGen.Gen = self
self.TranslatorGen = SubTranslatorGen
# ---- 初始化各子对象字段(Init* 方法内联调用) ----
SubBaseGen.InitBaseGen(pool)
SubTypeGenBase.InitTypeGen()
SubCallGenBase.InitCallGen()
SubStructGen.InitStructGen()
SubClassGenBase.InitClassGen()
SubExprGenBase.InitExprGen()
SubImportsGen.InitImportsGen()
SubStmtGenCif.InitStmtGen()
SubAssignGen.InitAssignGen()
# ============================================================
# 全局生成器单例(对象化 P2 兼容层)
# 全局生成器单例(组合架构兼容层)
# ============================================================
_g_gen: Generator | t.CPtr = None
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
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
File diff suppressed because it is too large. Load diff
+15 -28
View File
@@ -1,3 +1,5 @@
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
@@ -8,18 +10,6 @@ import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
@@ -37,12 +27,10 @@ class TypeGenBase:
"""字段 + InitTypeGen + trace/临时目录/generic 上下文"""
# --- 仿 Python Traceback 调用栈(原 _g_trace_frames/_g_trace_count) ---
TraceFrames: HandlesType.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽)
Gen: Generator.Generator | t.CPtr
TraceFrames: GenTypes.TraceFrame | t.CPtr # malloc 数组(TRACE_MAX 槽)
TraceCount: int
# --- 全局 temp_dir(原 _g_temp_dir) ---
TempDir: str
# --- 全局泛型特化上下文(原 _g_generic_tp_names/_g_generic_type_args) ---
GenericTpNames: list[str] | t.CPtr
GenericTypeArgs: list[str] | t.CPtr
@@ -92,7 +80,6 @@ class TypeGenBase:
return 1
self.TraceFrames = None
self.TraceCount = 0
self.TempDir = None
self.GenericTpNames = None
self.GenericTypeArgs = None
self.GenericCtxStack = None
@@ -126,26 +113,26 @@ class TypeGenBase:
"""确保调用栈已初始化(懒加载,用 malloc 不依赖 pool)"""
if self.TraceFrames is not None:
return 1
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
entry_size: t.CSizeT = GenTypes.TraceFrame.__sizeof__()
self.TraceFrames = CompilerFactory.get_perm_pool().alloc(entry_size * TRACE_MAX)
if self.TraceFrames is None:
return 0
string.memset(self.TraceFrames, 0, entry_size * TRACE_MAX)
return 1
def _get_trace_frame(self, i: int) -> HandlesType.TraceFrame | t.CPtr:
def _get_trace_frame(self, i: int) -> GenTypes.TraceFrame | t.CPtr:
"""获取第 i 个 TraceFrame 槽位"""
if self.TraceFrames is None or i < 0 or i >= TRACE_MAX:
return None
entry_size: t.CSizeT = HandlesType.TraceFrame.__sizeof__()
entry_size: t.CSizeT = GenTypes.TraceFrame.__sizeof__()
addr: t.CUInt64T = t.CUInt64T(self.TraceFrames) + i * entry_size
return (HandlesType.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr))
return (GenTypes.TraceFrame | t.CPtr)(t.CVoid(addr, t.CPtr))
def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
"""压入一个翻译上下文帧(进入新的翻译作用域时调用)"""
if self._ensure_trace_init() == 0:
return
if self.TraceCount >= TRACE_MAX:
return
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
if frame is None:
return
frame.file_name = file_name
@@ -158,7 +145,7 @@ class TypeGenBase:
if self.TraceCount <= 0:
return
self.TraceCount -= 1
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(self.TraceCount)
if frame is not None:
frame.file_name = None
frame.lineno = 0
@@ -168,7 +155,7 @@ class TypeGenBase:
"""清空调用栈(每个文件翻译开始前调用)"""
i: int
for i in range(self.TraceCount):
frame: HandlesType.TraceFrame | t.CPtr = self._get_trace_frame(i)
frame: GenTypes.TraceFrame | t.CPtr = self._get_trace_frame(i)
if frame is not None:
frame.file_name = None
frame.lineno = 0
@@ -176,11 +163,11 @@ class TypeGenBase:
frame.col_end = 0
self.TraceCount = 0
def set_temp_dir(self, temp_dir: str) -> None:
"""设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)"""
self.TempDir = temp_dir
"""设置全局 temp_dir(统一写入 CallGenBase.TempDir,跨子对象经 Gen 指针)"""
self.Gen.CallGenBase.SetTempDir(temp_dir)
def get_temp_dir(self) -> str:
"""获取全局 temp_dir"""
return self.TempDir
"""获取全局 temp_dir(从 CallGenBase 读取)"""
return self.Gen.CallGenBase.TempDir
def set_current_module_sha1(self, sha1: str) -> None:
"""设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)"""
self.CurrentModuleSha1 = sha1
+297 -305
View File
@@ -1,306 +1,298 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenCDef - TypeGenMixin 拆分(阶段 D):CDefine 编译期常量表(register/lookup/is/set/clear)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenCDef(TypeGenBase.TypeGenBase):
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: t.CInt64T) -> None:
"""注册 CDefine 编译期常量到本地表
值以十进制字符串存储(64 位 %lld)。大整数 CDefine(如
sys.maxsize = 9223372036854775807)必须全精度保存,否则 %d 32 位截断
成 -1(0xFFFFFFFF)→ 读回 4294967295(SysLibTest maxsize FAIL 根因)。
0xFFFFFFFF 仍存为 "4294967295",常量生成端 const_int32 内部截断回 -1。
"""
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
val_buf: str = pool.alloc(32)
if val_buf is not None:
viperlib.snprintf(val_buf, 32, "%lld", value)
self.CDefineValues.append(val_buf)
else:
self.CDefineValues.append("0")
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(0)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(0)
def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: double) -> None:
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
"""
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
val_buf: str = pool.alloc(32)
if val_buf is not None:
# 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的
# %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926,
# 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。
stdio.snprintf(val_buf, 32, "%.17g", value)
self.CDefineValues.append(val_buf)
else:
self.CDefineValues.append("0")
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(1)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(0)
# fail-fast:CDefine 值缓冲区分配失败必须终止编译,
if val_buf is None:
VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG")
HandlesType.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError")
def register_cdefine_string(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: str) -> None:
"""注册字符串 CDefine 编译期常量(如 ZLIB_VERSION: t.CDefine = "1.3.2")
字符串值深拷贝到 pool(AST 节点的 str_val 可能被 pool 操作覆写,
与浮点 CDefine 的恢复同理)。
"""
if pool is None or name is None:
return
if value is None:
HandlesType.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError")
return
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
vlen: t.CSizeT = string.strlen(value)
vcopy: str = pool.alloc(vlen + 1)
if vcopy is None:
HandlesType.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError")
return
string.strcpy(vcopy, value)
self.CDefineValues.append(vcopy)
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(0)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(1)
# 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。
# 跨模块字符串 CDefine 读回(_lookup_cross_module_cdefine 字符串分支只调
# 本函数 + 尾部 set_cdefine_found,无 lookup_cdefine_string 回查)→ 若此处
# 不设标志,属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 →
# IR 生成 inttoptr i32 0(NULL)→ 运行时报 (null-) + strlen(NULL-) 崩溃
# (test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)。
self.CDefineIsStr = 1
self.CDefineFound = 1
# ============================================================
# 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用)
# ============================================================
def register_xmod_cdefine(self, name: str, value_str: str,
is_double: int, is_str: int) -> None:
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(跨文件复用)
Args:
name: CDefine 常量名(如 CONST_INT)
value_str: 值文本(十进制/浮点/字符串)
is_double: 1=浮点值
is_str: 1=字符串值
"""
if name is None or value_str is None:
return
# 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定)
if self.XmodCdefNames is not None:
x_n: t.CSizeT = len(self.XmodCdefNames)
x_i: t.CSizeT
for x_i in range(x_n):
x_nm: str = self.XmodCdefNames.get(x_i)
if x_nm is not None and string.strcmp(x_nm, name) == 0:
return
perm: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
if self.XmodCdefNames is None:
self.XmodCdefNames = list[str](perm, 64)
self.XmodCdefValues = list[str](perm, 64)
self.XmodCdefDoubleFlags = list[int](perm, 64)
self.XmodCdefStrFlags = list[int](perm, 64)
# key/value 深拷贝到 perm_pool:入参(pool.alloc 临时缓冲)在
# reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活
klen: t.CSizeT = string.strlen(name)
kcopy: str = perm.alloc(klen + 1)
if kcopy is None:
return
string.strcpy(kcopy, name)
vlen: t.CSizeT = string.strlen(value_str)
vcopy: str = perm.alloc(vlen + 1)
if vcopy is None:
return
string.strcpy(vcopy, value_str)
self.XmodCdefNames.append(kcopy)
self.XmodCdefValues.append(vcopy)
if self.XmodCdefDoubleFlags is not None:
self.XmodCdefDoubleFlags.append(is_double)
if self.XmodCdefStrFlags is not None:
self.XmodCdefStrFlags.append(is_str)
def lookup_xmod_cdefine(self, name: str) -> str:
"""查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志
Returns:
值文本(命中),未命中返回 None
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if name is None or self.XmodCdefNames is None:
return None
n: t.CSizeT = len(self.XmodCdefNames)
i: t.CSizeT
for i in range(n):
nm: str = self.XmodCdefNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.XmodCdefValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1:
self.CDefineIsStr = 1
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
return val_str
return None
def lookup_cdefine_constant(self, name: str) -> t.CInt64T:
"""查找 CDefine 编译期常量
返回找到的值(64 位,大整数 CDefine 如 sys.maxsize 全精度)。
由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
调用方应在调用后检查 _g_cdefine_found。
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return 0
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
# 字符串 CDefine(如 ZLIB_VERSION="1.3.2"):整数查询路径
# 标记 is_str,调用方改用 lookup_cdefine_string 取字符串。
self.CDefineIsStr = 1
return 0
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
return string.atoll(val_str)
return string.atoll(val_str)
return 0
def lookup_cdefine_double(self, name: str) -> double:
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return 0.0
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
self.CDefineIsStr = 1
return 0.0
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
ret_d: double = string.atof(val_str)
return ret_d
ret_i2: double = double(string.atoll(val_str))
return ret_i2
return 0.0
def lookup_cdefine_string(self, name: str) -> str:
"""查找 CDefine 编译期字符串值(found=1 且 is_str=1 时有效)
返回的字符串指针位于 pool 内(当前模块生命周期内有效),
调用方应尽快用于 create_global_string 拷贝到 LLVM 常量。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return None
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
self.CDefineIsStr = 1
return val_str
return val_str
return None
def is_cdefine_str(self) -> int:
"""检查最近一次 CDefine 查找命中的是否是字符串常量"""
return self.CDefineIsStr
def is_cdefine_double(self) -> int:
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
return self.CDefineIsDouble
def is_cdefine_found(self) -> int:
"""检查上次 lookup_cdefine_constant 是否找到值"""
return self.CDefineFound
def set_cdefine_found(self, val: int) -> None:
"""设置 cdefine_found 标志(供跨模块查找函数使用)"""
self.CDefineFound = val
def clear_cdefine_constants(self) -> None:
"""清空 CDefine 常量表(模块切换时调用)"""
self.CDefineNames = None
self.CDefineValues = None
self.CDefineDoubleFlags = None
self.CDefineStrFlags = None
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenCDef - TypeGenMixin 拆分(阶段 D):CDefine 编译期常量表(register/lookup/is/set/clear)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenCDef(TypeGenBase.TypeGenBase):
"""CDefine 编译期常量表(register/lookup/is/set/clear)"""
def register_cdefine_constant(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: t.CInt64T) -> None:
"""注册 CDefine 编译期常量到本地表
值以十进制字符串存储(64 位 %lld)。大整数 CDefine(如
sys.maxsize = 9223372036854775807)必须全精度保存,否则 %d 32 位截断
成 -1(0xFFFFFFFF)→ 读回 4294967295(SysLibTest maxsize FAIL 根因)。
0xFFFFFFFF 仍存为 "4294967295",常量生成端 const_int32 内部截断回 -1。
"""
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
val_buf: str = pool.alloc(32)
if val_buf is not None:
viperlib.snprintf(val_buf, 32, "%lld", value)
self.CDefineValues.append(val_buf)
else:
self.CDefineValues.append("0")
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(0)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(0)
def register_cdefine_double(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: double) -> None:
"""注册浮点 CDefine 编译期常量(如 U_M_PI: t.CDefine = 3.14159...)
值以 %f 文本存储并标记浮点,供 translate_value 返回浮点常量。
"""
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
val_buf: str = pool.alloc(32)
if val_buf is not None:
# 用 CRT stdio.snprintf 而非 viperlib.snprintf:viperlib 自实现格式化器的
# %g 浮点路径有 bug(%.17g 输出错误值,如 pi 显示 3.1397985 而非 3.1415926,
# 位模式 %a 正确),会导致 CDefine 表存错文本 → lookup 生成错 LLVM 常量。
stdio.snprintf(val_buf, 32, "%.17g", value)
self.CDefineValues.append(val_buf)
else:
self.CDefineValues.append("0")
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(1)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(0)
# fail-fast:CDefine 值缓冲区分配失败必须终止编译,
if val_buf is None:
VLogger.error("CDefine 浮点值缓冲区分配失败", "CDEF-DBG")
self.Gen.TypeGenErr.fatal_error(None, "CDefine 浮点值缓冲区分配失败", "MemoryError")
def register_cdefine_string(self, pool: memhub.MemBuddy | t.CPtr,
name: str, value: str) -> None:
"""注册字符串 CDefine 编译期常量(如 ZLIB_VERSION: t.CDefine = "1.3.2")
字符串值深拷贝到 pool(AST 节点的 str_val 可能被 pool 操作覆写,
与浮点 CDefine 的恢复同理)。
"""
if pool is None or name is None:
return
if value is None:
self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值缺失: {name}", "InternalCompilerError")
return
if self.CDefineNames is None:
self.CDefineNames = list[str](pool, 64)
self.CDefineValues = list[str](pool, 64)
self.CDefineDoubleFlags = list[int](pool, 64)
self.CDefineStrFlags = list[int](pool, 64)
self.CDefineNames.append(name)
vlen: t.CSizeT = string.strlen(value)
vcopy: str = pool.alloc(vlen + 1)
if vcopy is None:
self.Gen.TypeGenErr.fatal_error(None, f"CDefine 字符串值分配失败: {name}", "MemoryError")
return
string.strcpy(vcopy, value)
self.CDefineValues.append(vcopy)
if self.CDefineDoubleFlags is not None:
self.CDefineDoubleFlags.append(0)
if self.CDefineStrFlags is not None:
self.CDefineStrFlags.append(1)
# 同步设置"最近注册/查表结果为字符串"标志(is_cdefine_str() 读取)。
# 跨模块字符串 CDefine 读回(_lookup_cross_module_cdefine 字符串分支只调
# 本函数 + 尾部 set_cdefine_found,无 lookup_cdefine_string 回查)→ 若此处
# 不设标志,属性路径 is_cdefine_str()==0 → 退化为整数分支返回 0 →
# IR 生成 inttoptr i32 0(NULL)→ 运行时报 (null-) + strlen(NULL-) 崩溃
# (test_pyzlib.vp pyzlib.ZLIB_VERSION 根因)。
self.CDefineIsStr = 1
self.CDefineFound = 1
# ============================================================
# 跨模块 CDefine 查找缓存(perm_pool 永久分配,跨文件复用)
# ============================================================
def register_xmod_cdefine(self, name: str, value_str: str,
is_double: int, is_str: int) -> None:
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(跨文件复用)
Args:
name: CDefine 常量名(如 CONST_INT)
value_str: 值文本(十进制/浮点/字符串)
is_double: 1=浮点值
is_str: 1=字符串值
"""
if name is None or value_str is None:
return
# 去重:同名已缓存则跳过(首次查找结果为准,CDefine 全局唯一约定)
if self.XmodCdefNames is not None:
x_n: t.CSizeT = len(self.XmodCdefNames)
x_i: t.CSizeT
for x_i in range(x_n):
x_nm: str = self.XmodCdefNames.get(x_i)
if x_nm is not None and string.strcmp(x_nm, name) == 0:
return
perm: memhub.MemBuddy | t.CPtr = CompilerFactory.get_perm_pool()
if self.XmodCdefNames is None:
self.XmodCdefNames = list[str](perm, 64)
self.XmodCdefValues = list[str](perm, 64)
self.XmodCdefDoubleFlags = list[int](perm, 64)
self.XmodCdefStrFlags = list[int](perm, 64)
# key/value 深拷贝到 perm_pool:入参(pool.alloc 临时缓冲)在
# reset_to(mark2) 后悬空,append 只存指针 → 必须深拷贝跨 reset 存活
klen: t.CSizeT = string.strlen(name)
kcopy: str = perm.alloc(klen + 1)
if kcopy is None:
return
string.strcpy(kcopy, name)
vlen: t.CSizeT = string.strlen(value_str)
vcopy: str = perm.alloc(vlen + 1)
if vcopy is None:
return
string.strcpy(vcopy, value_str)
self.XmodCdefNames.append(kcopy)
self.XmodCdefValues.append(vcopy)
if self.XmodCdefDoubleFlags is not None:
self.XmodCdefDoubleFlags.append(is_double)
if self.XmodCdefStrFlags is not None:
self.XmodCdefStrFlags.append(is_str)
def lookup_xmod_cdefine(self, name: str) -> str:
"""查找跨模块 CDefine 缓存,命中设置 found/is_double/is_str 标志
Returns:
值文本(命中),未命中返回 None
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if name is None or self.XmodCdefNames is None:
return None
n: t.CSizeT = len(self.XmodCdefNames)
i: t.CSizeT
for i in range(n):
nm: str = self.XmodCdefNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.XmodCdefValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.XmodCdefStrFlags is not None and self.XmodCdefStrFlags.get(i) == 1:
self.CDefineIsStr = 1
elif self.XmodCdefDoubleFlags is not None and self.XmodCdefDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
return val_str
return None
def lookup_cdefine_constant(self, name: str) -> t.CInt64T:
"""查找 CDefine 编译期常量
返回找到的值(64 位,大整数 CDefine 如 sys.maxsize 全精度)。
由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1),
用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。
调用方应在调用后检查 _g_cdefine_found。
浮点 CDefine 项返回整数部分(与 _g_cdefine_is_double 标志配合)。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return 0
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
# 字符串 CDefine(如 ZLIB_VERSION="1.3.2"):整数查询路径
# 标记 is_str,调用方改用 lookup_cdefine_string 取字符串。
self.CDefineIsStr = 1
return 0
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
return string.atoll(val_str)
return string.atoll(val_str)
return 0
def lookup_cdefine_double(self, name: str) -> double:
"""查找 CDefine 编译期常量,返回 double 值(浮点/整数统一)
与 lookup_cdefine_constant 共享 _g_cdefine_found / _g_cdefine_is_double
(found=1 且 is_double=1 → 浮点 CDefine,应返回浮点常量)。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return 0.0
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
self.CDefineIsStr = 1
return 0.0
if self.CDefineDoubleFlags is not None and self.CDefineDoubleFlags.get(i) == 1:
self.CDefineIsDouble = 1
ret_d: double = string.atof(val_str)
return ret_d
ret_i2: double = double(string.atoll(val_str))
return ret_i2
return 0.0
def lookup_cdefine_string(self, name: str) -> str:
"""查找 CDefine 编译期字符串值(found=1 且 is_str=1 时有效)
返回的字符串指针位于 pool 内(当前模块生命周期内有效),
调用方应尽快用于 create_global_string 拷贝到 LLVM 常量。
"""
self.CDefineFound = 0
self.CDefineIsDouble = 0
self.CDefineIsStr = 0
if self.CDefineNames is None:
return None
n: t.CSizeT = len(self.CDefineNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CDefineNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
val_str: str = self.CDefineValues.get(i)
if val_str is not None:
self.CDefineFound = 1
if self.CDefineStrFlags is not None and self.CDefineStrFlags.get(i) == 1:
self.CDefineIsStr = 1
return val_str
return val_str
return None
def is_cdefine_str(self) -> int:
"""检查最近一次 CDefine 查找命中的是否是字符串常量"""
return self.CDefineIsStr
def is_cdefine_double(self) -> int:
"""检查最近一次 CDefine 查找命中的是否是浮点常量"""
return self.CDefineIsDouble
def is_cdefine_found(self) -> int:
"""检查上次 lookup_cdefine_constant 是否找到值"""
return self.CDefineFound
def set_cdefine_found(self, val: int) -> None:
"""设置 cdefine_found 标志(供跨模块查找函数使用)"""
self.CDefineFound = val
def clear_cdefine_constants(self) -> None:
"""清空 CDefine 常量表(模块切换时调用)"""
self.CDefineNames = None
self.CDefineValues = None
self.CDefineDoubleFlags = None
self.CDefineStrFlags = None
self.CDefineIsStr = 0
+415 -422
View File
@@ -1,422 +1,415 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenCType(TypeGenBase.TypeGenBase):
"""CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)"""
def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr,
name: str, type_str: str) -> None:
"""注册 CTypedef 到本地表
Args:
pool: 内存池
name: CTypedef 名称(如 "HANDLE")
type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr")
"""
if name is None or type_str is None or pool is None:
return
if self.CTypedefNames is None:
self.CTypedefNames = list[str](pool, 64)
self.CTypedefTypeStrs = list[str](pool, 64)
# 去重:若已存在同名 CTypedef,更新其类型字符串
if self.CTypedefNames is not None:
exist_n: t.CSizeT = len(self.CTypedefNames)
ei: t.CSizeT
for ei in range(exist_n):
en: str = self.CTypedefNames.get(ei)
if en is not None and string.strcmp(en, name) == 0:
# 已存在,更新类型字符串
self.CTypedefTypeStrs.set(ei, type_str)
return
self.CTypedefNames.append(name)
self.CTypedefTypeStrs.append(type_str)
def lookup_ctypedef(self, name: str) -> str:
"""查找 CTypedef,返回类型表达式字符串
返回找到的类型表达式字符串,未找到返回 None。
调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。
"""
self.CTypedefFound = 0
if name is None:
return None
if self.CTypedefNames is None:
return None
n: t.CSizeT = len(self.CTypedefNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CTypedefNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
ts: str = self.CTypedefTypeStrs.get(i)
self.CTypedefFound = 1
return ts
return None
def is_ctypedef_found(self) -> int:
"""检查上次 lookup_ctypedef 是否找到值"""
return self.CTypedefFound
def clear_ctypedefs(self) -> None:
"""清空 CTypedef 表(模块切换时调用)"""
self.CTypedefNames = None
self.CTypedefTypeStrs = None
self.CTypedefResolveDepth = 0
self.CTypedefVisiting = None
def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
"""将 CTypedef 名加入正在解析列表(循环检测)
Returns:
0=成功加入(无循环),1=检测到循环
"""
if name is None:
return 0
if self.CTypedefVisiting is None:
self.CTypedefVisiting = list[str](pool, 32)
if self.CTypedefVisiting is None:
return 0
vn: t.CSizeT = len(self.CTypedefVisiting)
vi: t.CSizeT
for vi in range(vn):
vs: str = self.CTypedefVisiting.get(vi)
if vs is not None and string.strcmp(vs, name) == 0:
return 1 # 循环检测
self.CTypedefVisiting.append(name)
return 0
def _ctypedef_pop_visiting(self) -> None:
"""从正在解析列表弹出最后一个 CTypedef 名"""
if self.CTypedefVisiting is None:
return
vn: t.CSizeT = len(self.CTypedefVisiting)
if vn > 0:
self.CTypedefVisiting.pop()
def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int:
"""检测类型注解是否为 t.CTypedef
Args:
annotation: 类型注解 AST 节点
Returns:
1=是 t.CTypedef,0=否
"""
if annotation is None:
return 0
k_v: int = annotation.kind()
if k_v != ast.ASTKind.Attribute:
return 0
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
# 字段访问改用 ast 模块访问器(跨模块 stub 字段访问陷阱防护:
# TypeGenCType 直接访问 at.attr 可能按 stub 类型生成错误 GEP,
# 读垃圾地址 → strcmp 0xC0000005 崩溃,stdint.vp 根因)。
at_attr_v: str = ast.attribute_get_attr(at)
if at_attr_v is None:
return 0
# 限长比较替代 strcmp:attr 是零拷贝引用 src_buf 的 token 字符串,
# 可能无 NUL 结尾("CTypedef" 后紧跟空格/其他字符),strcmp 会
# 无限读穿到页边界 → 0xC0000005(stdint.vp 崩溃根因)。strncmp
# 只读 8 字节,再校验第 9 字节为终止/分隔符(防 "CTypedefXXX" 误匹配)。
if string.strncmp(at_attr_v, "CTypedef", 8) != 0:
return 0
sep_ch_d: t.CChar = at_attr_v[8]
if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' \
and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|':
return 0
at_val_v: ast.AST | t.CPtr = ast.attribute_get_value(at)
if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name:
return 0
mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_val_v)
mod_id_v: str = ast.name_get_id(mod_nm)
if mod_id_v is None:
return 0
# 同样限长比较("t" 无 NUL 结尾时 strcmp 读穿)
if string.strncmp(mod_id_v, "t", 1) != 0:
return 0
sep_ch_m: t.CChar = mod_id_v[1]
if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' \
and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|':
return 0
return 1
def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr,
tree: ast.AST | t.CPtr) -> int:
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明
在 _translate_module_level 中、模块级变量预注册之前调用,
确保 CTypedef 名称在类型解析时可用。
Args:
pool: 内存池
tree: 模块 AST 根节点
Returns:
注册的 CTypedef 数量
"""
if pool is None or tree is None:
return 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is None:
return 0
n: t.CSizeT = len(ch)
count: int = 0
i: t.CSizeT
for i in range(n):
child: ast.AST | t.CPtr = ch.get(i)
if child is None:
continue
if child.kind() != ast.ASTKind.AnnAssign:
continue
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
if aa.annotation is None:
continue
# 检测注解是否为 t.CTypedef
if self._is_ctypedef_annotation(aa.annotation) == 0:
continue
# 提取目标名称(必须是 Name 节点)
if aa.target is None or aa.target.kind() != ast.ASTKind.Name:
continue
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
tgt_id_v: str = ast.name_get_id(tgt)
if tgt_id_v is None:
continue
# 提取类型表达式字符串(从 value AST 节点)
if aa.value is None:
continue
type_str: str = HandlesType._get_type_name_from_annotation(pool, aa.value)
if type_str is None:
continue
# 注册 CTypedef
self.register_ctypedef(pool, tgt_id_v, type_str)
count += 1
return count
def register_ctypedef_from_source(self, pool: memhub.MemBuddy | t.CPtr,
src: str) -> int:
"""从源码文本逐行扫描注册 CTypedef(NAME: t.CTypedef = TYPE)
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
attr 会 0xC0000005。本函数在 src_buf 有效期内(Phase1 1b translate
前)用纯文本匹配注册,不依赖 AST 节点内容。
"""
if pool is None or src is None:
return 0
# 文件边界防护:clear_ctypedefs 只在 translate 前调用(Phase1Main
# L800),文件级 reset_to(mark1) 回收本文件翻译期 pool 分配后,上一
# 文件的 CTypedefNames 表指针悬空(非 None,list 本身也 pool 分配)。
# 本函数去重遍历(register_ctypedef 内 strcmp)读已回收内存 →
# 0xC0000005(1.log: stdint.vp 翻译时 strcmp 读地址 0x4)。先清表
# 重建,杜绝悬空遍历。翻译期 Handle 按需注册不受影响(L800 会再清)。
self.clear_ctypedefs()
src_len: t.CSizeT = string.strlen(src)
count: int = 0
line_start: t.CSizeT = 0
i: t.CSizeT = 0
while i <= src_len:
if i == src_len or src[i] == '\n':
line_len: t.CSizeT = i - line_start
if line_len > 0:
# 找行内第一个 ':'(跳过注释行)
j: t.CSizeT = 0
found_colon: int = 0
while j < line_len:
ch_c: t.CChar = src[line_start + j]
if ch_c == ':':
found_colon = 1
break
if ch_c == '#' or ch_c == '\r':
break
j += 1
if found_colon != 0:
# 左段 NAME(trim 尾随空格)
name_len: t.CSizeT = j
while name_len > 0 and src[line_start + name_len - 1] == ' ':
name_len -= 1
if name_len > 0 and name_len < 128:
# 右段必须含 "t.CTypedef"
rest: str = src + line_start + j + 1
if string.strstr(rest, "t.CTypedef") is not None:
# 提取 "=" 后的类型表达式(trim 空格)
eq_ptr: str = string.strstr(rest, "=")
if eq_ptr is not None:
ty_start: str = eq_ptr + 1
while ty_start[0] == ' ':
ty_start += 1
ty_end: t.CSizeT = string.strlen(ty_start)
while ty_end > 0 and (ty_start[ty_end - 1] == ' '
or ty_start[ty_end - 1] == '\r'):
ty_end -= 1
if ty_end > 0:
name_buf: str = pool.alloc(name_len + 1)
ty_buf: str = pool.alloc(ty_end + 1)
if name_buf is not None and ty_buf is not None:
string.strncpy(name_buf, src + line_start, name_len)
name_buf[name_len] = '\0'
string.strncpy(ty_buf, ty_start, ty_end)
ty_buf[ty_end] = '\0'
self.register_ctypedef(pool, name_buf, ty_buf)
count += 1
line_start = i + 1
i += 1
return count
def _eval_const_int_expr(self, node: ast.AST | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None,
from_imports: str = None,
imported_modules: str = None) -> int:
"""递归计算常量整数表达式
pool/from_imports/imported_modules:跨模块 CDefine 查找上下文
(t.CArray count 引用依赖模块的 CDefine,如 SHA512_BLOCK_LEN 定义在
hashlib/__sha512.vp,本地 CDefine 表每模块清空,需跨模块回退查找)。
"""
if node is None:
self.ConstEvalOk = 0
return 0
k: int = node.kind()
# Constant: 整数字面量
if k == ast.ASTKind.Constant:
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn.const_kind == ast.CONST_INT:
self.ConstEvalOk = 1
return cn.int_val
self.ConstEvalOk = 0
return 0
# Name: CDefine 常量名(本地表优先,未命中走跨模块查找)
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
if nm.id is None:
self.ConstEvalOk = 0
return 0
val: int = HandlesType.lookup_cdefine_constant(nm.id)
if HandlesType.is_cdefine_found() == 0:
# 本地表未命中:跨模块 CDefine 查找
# 用 HandlesExpr 模块级委托(self._lookup_cross_module_cdefine 是
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
if (from_imports is not None or imported_modules is not None) \
and pool is not None:
import lib.core.Handles.HandlesExpr as HandlesExpr
x_val: int = HandlesExpr._lookup_cross_module_cdefine(
pool, nm.id, from_imports, imported_modules)
if HandlesType.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return x_val
# 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景)
fb_cdf: str = VLogger.fmt_buf()
if fb_cdf is not None:
viperlib.snprintf(fb_cdf, 1024,
"[CDEF-MISS] name=%s fi=%s im=%s",
nm.id,
from_imports if from_imports is not None else "(null)",
imported_modules if imported_modules is not None else "(null)")
VLogger.error(fb_cdf, "CDEF")
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return val
# Attribute: 模块限定常量名,如 hashlib.MD5_DIGEST_LEN
# (t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] 的 count 是 Attribute,
# 复用跨模块 CDefine 查找:*:模块 → 源文件提取;re-export 常量由
# _lookup_cross_module_cdefine 的 from-import 递归子模块兜底)
if k == ast.ASTKind.Attribute:
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
if at.attr is None:
self.ConstEvalOk = 0
return 0
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
at_mod: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if at_mod.id is not None:
if (from_imports is not None or imported_modules is not None) \
and pool is not None:
mod_len: t.CSizeT = string.strlen(at_mod.id)
fi_buf: str = pool.alloc(mod_len + 3)
if fi_buf is not None:
fi_buf[0] = '*'
fi_buf[1] = ':'
for mi in range(mod_len):
fi_buf[2 + mi] = at_mod.id[mi]
fi_buf[2 + mod_len] = '\0'
import lib.core.Handles.HandlesExpr as HandlesExpr
av: int = HandlesExpr._lookup_cross_module_cdefine(
pool, at.attr, fi_buf, imported_modules)
if HandlesType.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return av
self.ConstEvalOk = 0
return 0
# BinOp: 算术/位运算
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
# 递归计算左操作数
lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules)
if self.ConstEvalOk == 0:
return 0
# 递归计算右操作数
rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules)
if self.ConstEvalOk == 0:
return 0
# 根据运算符执行计算
if bop.op == ast.OpKind.Add:
self.ConstEvalOk = 1
return lv + rv
if bop.op == ast.OpKind.Sub:
self.ConstEvalOk = 1
return lv - rv
if bop.op == ast.OpKind.Mult:
self.ConstEvalOk = 1
return lv * rv
if bop.op == ast.OpKind.Div:
# 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355)
if rv == 0:
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return lv // rv
if bop.op == ast.OpKind.FloorDiv:
if rv == 0:
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return lv // rv
if bop.op == ast.OpKind.BitOr:
self.ConstEvalOk = 1
return lv | rv
if bop.op == ast.OpKind.BitAnd:
self.ConstEvalOk = 1
return lv & rv
# 不支持的运算符
self.ConstEvalOk = 0
return 0
# 不支持的节点类型
self.ConstEvalOk = 0
return 0
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenCType - TypeGenMixin 拆分(阶段 D):CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)
#
# 继承 TypeGenBase(1 级,TPV self 调用仅支持 1 级父类)。
# 跨 Mixin 调用统一走 HandlesType 委托(经 _g_gen)。
# @t.NoVTable:静态绑定。
# ============================================================
@t.NoVTable
class TypeGenCType(TypeGenBase.TypeGenBase):
"""CTypedef 表(register/lookup/ScanCTypedefDeclarations/_eval_const_int_expr)"""
def register_ctypedef(self, pool: memhub.MemBuddy | t.CPtr,
name: str, type_str: str) -> None:
"""注册 CTypedef 到本地表
Args:
pool: 内存池
name: CTypedef 名称(如 "HANDLE")
type_str: 类型表达式字符串(如 "VOIDPTR" 或 "t.CVoid | t.CPtr")
"""
if name is None or type_str is None or pool is None:
return
if self.CTypedefNames is None:
self.CTypedefNames = list[str](pool, 64)
self.CTypedefTypeStrs = list[str](pool, 64)
# 去重:若已存在同名 CTypedef,更新其类型字符串
if self.CTypedefNames is not None:
exist_n: t.CSizeT = len(self.CTypedefNames)
ei: t.CSizeT
for ei in range(exist_n):
en: str = self.CTypedefNames.get(ei)
if en is not None and string.strcmp(en, name) == 0:
# 已存在,更新类型字符串
self.CTypedefTypeStrs.set(ei, type_str)
return
self.CTypedefNames.append(name)
self.CTypedefTypeStrs.append(type_str)
def lookup_ctypedef(self, name: str) -> str:
"""查找 CTypedef,返回类型表达式字符串
返回找到的类型表达式字符串,未找到返回 None。
调用方应在调用后检查 _g_ctypedef_found 标志区分"未找到"和"空字符串"。
"""
self.CTypedefFound = 0
if name is None:
return None
if self.CTypedefNames is None:
return None
n: t.CSizeT = len(self.CTypedefNames)
i: t.CSizeT
for i in range(n):
nm: str = self.CTypedefNames.get(i)
if nm is not None and string.strcmp(nm, name) == 0:
ts: str = self.CTypedefTypeStrs.get(i)
self.CTypedefFound = 1
return ts
return None
def is_ctypedef_found(self) -> int:
"""检查上次 lookup_ctypedef 是否找到值"""
return self.CTypedefFound
def clear_ctypedefs(self) -> None:
"""清空 CTypedef 表(模块切换时调用)"""
self.CTypedefNames = None
self.CTypedefTypeStrs = None
self.CTypedefResolveDepth = 0
self.CTypedefVisiting = None
def _ctypedef_push_visiting(self, pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
"""将 CTypedef 名加入正在解析列表(循环检测)
Returns:
0=成功加入(无循环),1=检测到循环
"""
if name is None:
return 0
if self.CTypedefVisiting is None:
self.CTypedefVisiting = list[str](pool, 32)
if self.CTypedefVisiting is None:
return 0
vn: t.CSizeT = len(self.CTypedefVisiting)
vi: t.CSizeT
for vi in range(vn):
vs: str = self.CTypedefVisiting.get(vi)
if vs is not None and string.strcmp(vs, name) == 0:
return 1 # 循环检测
self.CTypedefVisiting.append(name)
return 0
def _ctypedef_pop_visiting(self) -> None:
"""从正在解析列表弹出最后一个 CTypedef 名"""
if self.CTypedefVisiting is None:
return
vn: t.CSizeT = len(self.CTypedefVisiting)
if vn > 0:
self.CTypedefVisiting.pop()
def _is_ctypedef_annotation(self, annotation: ast.AST | t.CPtr) -> int:
"""检测类型注解是否为 t.CTypedef
Args:
annotation: 类型注解 AST 节点
Returns:
1=是 t.CTypedef,0=否
"""
if annotation is None:
return 0
k_v: int = annotation.kind()
if k_v != ast.ASTKind.Attribute:
return 0
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation)
# 字段访问改用 ast 模块访问器(跨模块 stub 字段访问陷阱防护:
# TypeGenCType 直接访问 at.attr 可能按 stub 类型生成错误 GEP,
# 读垃圾地址 → strcmp 0xC0000005 崩溃,stdint.vp 根因)。
at_attr_v: str = ast.attribute_get_attr(at)
if at_attr_v is None:
return 0
# 限长比较替代 strcmp:attr 是零拷贝引用 src_buf 的 token 字符串,
# 可能无 NUL 结尾("CTypedef" 后紧跟空格/其他字符),strcmp 会
# 无限读穿到页边界 → 0xC0000005(stdint.vp 崩溃根因)。strncmp
# 只读 8 字节,再校验第 9 字节为终止/分隔符(防 "CTypedefXXX" 误匹配)。
if string.strncmp(at_attr_v, "CTypedef", 8) != 0:
return 0
sep_ch_d: t.CChar = at_attr_v[8]
if sep_ch_d != '\0' and sep_ch_d != ' ' and sep_ch_d != '\n' \
and sep_ch_d != '\r' and sep_ch_d != '\t' and sep_ch_d != '|':
return 0
at_val_v: ast.AST | t.CPtr = ast.attribute_get_value(at)
if at_val_v is None or at_val_v.kind() != ast.ASTKind.Name:
return 0
mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_val_v)
mod_id_v: str = ast.name_get_id(mod_nm)
if mod_id_v is None:
return 0
# 同样限长比较("t" 无 NUL 结尾时 strcmp 读穿)
if string.strncmp(mod_id_v, "t", 1) != 0:
return 0
sep_ch_m: t.CChar = mod_id_v[1]
if sep_ch_m != '\0' and sep_ch_m != ' ' and sep_ch_m != '\n' \
and sep_ch_m != '\r' and sep_ch_m != '\t' and sep_ch_m != '|':
return 0
return 1
def ScanCTypedefDeclarations(self, pool: memhub.MemBuddy | t.CPtr,
tree: ast.AST | t.CPtr) -> int:
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明
在 _translate_module_level 中、模块级变量预注册之前调用,
确保 CTypedef 名称在类型解析时可用。
Args:
pool: 内存池
tree: 模块 AST 根节点
Returns:
注册的 CTypedef 数量
"""
if pool is None or tree is None:
return 0
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
if ch is None:
return 0
n: t.CSizeT = len(ch)
count: int = 0
i: t.CSizeT
for i in range(n):
child: ast.AST | t.CPtr = ch.get(i)
if child is None:
continue
if child.kind() != ast.ASTKind.AnnAssign:
continue
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child)
if aa.annotation is None:
continue
# 检测注解是否为 t.CTypedef
if self._is_ctypedef_annotation(aa.annotation) == 0:
continue
# 提取目标名称(必须是 Name 节点)
if aa.target is None or aa.target.kind() != ast.ASTKind.Name:
continue
tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
tgt_id_v: str = ast.name_get_id(tgt)
if tgt_id_v is None:
continue
# 提取类型表达式字符串(从 value AST 节点)
if aa.value is None:
continue
type_str: str = self.Gen.TypeGenResolve._get_type_name_from_annotation(pool, aa.value)
if type_str is None:
continue
# 注册 CTypedef
self.register_ctypedef(pool, tgt_id_v, type_str)
count += 1
return count
def register_ctypedef_from_source(self, pool: memhub.MemBuddy | t.CPtr,
src: str) -> int:
"""从源码文本逐行扫描注册 CTypedef(NAME: t.CTypedef = TYPE)
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
attr 会 0xC0000005。本函数在 src_buf 有效期内(Phase1 1b translate
前)用纯文本匹配注册,不依赖 AST 节点内容。
"""
if pool is None or src is None:
return 0
# 文件边界防护:clear_ctypedefs 只在 translate 前调用(Phase1Main
# L800),文件级 reset_to(mark1) 回收本文件翻译期 pool 分配后,上一
# 文件的 CTypedefNames 表指针悬空(非 None,list 本身也 pool 分配)。
# 本函数去重遍历(register_ctypedef 内 strcmp)读已回收内存 →
# 0xC0000005(1.log: stdint.vp 翻译时 strcmp 读地址 0x4)。先清表
# 重建,杜绝悬空遍历。翻译期 Handle 按需注册不受影响(L800 会再清)。
self.clear_ctypedefs()
src_len: t.CSizeT = string.strlen(src)
count: int = 0
line_start: t.CSizeT = 0
i: t.CSizeT = 0
while i <= src_len:
if i == src_len or src[i] == '\n':
line_len: t.CSizeT = i - line_start
if line_len > 0:
# 找行内第一个 ':'(跳过注释行)
j: t.CSizeT = 0
found_colon: int = 0
while j < line_len:
ch_c: t.CChar = src[line_start + j]
if ch_c == ':':
found_colon = 1
break
if ch_c == '#' or ch_c == '\r':
break
j += 1
if found_colon != 0:
# 左段 NAME(trim 尾随空格)
name_len: t.CSizeT = j
while name_len > 0 and src[line_start + name_len - 1] == ' ':
name_len -= 1
if name_len > 0 and name_len < 128:
# 右段必须含 "t.CTypedef"
rest: str = src + line_start + j + 1
if string.strstr(rest, "t.CTypedef") is not None:
# 提取 "=" 后的类型表达式(trim 空格)
eq_ptr: str = string.strstr(rest, "=")
if eq_ptr is not None:
ty_start: str = eq_ptr + 1
while ty_start[0] == ' ':
ty_start += 1
ty_end: t.CSizeT = string.strlen(ty_start)
while ty_end > 0 and (ty_start[ty_end - 1] == ' '
or ty_start[ty_end - 1] == '\r'):
ty_end -= 1
if ty_end > 0:
name_buf: str = pool.alloc(name_len + 1)
ty_buf: str = pool.alloc(ty_end + 1)
if name_buf is not None and ty_buf is not None:
string.strncpy(name_buf, src + line_start, name_len)
name_buf[name_len] = '\0'
string.strncpy(ty_buf, ty_start, ty_end)
ty_buf[ty_end] = '\0'
self.register_ctypedef(pool, name_buf, ty_buf)
count += 1
line_start = i + 1
i += 1
return count
def _eval_const_int_expr(self, node: ast.AST | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None,
from_imports: str = None,
imported_modules: str = None) -> int:
"""递归计算常量整数表达式
pool/from_imports/imported_modules:跨模块 CDefine 查找上下文
(t.CArray count 引用依赖模块的 CDefine,如 SHA512_BLOCK_LEN 定义在
hashlib/__sha512.vp,本地 CDefine 表每模块清空,需跨模块回退查找)。
"""
if node is None:
self.ConstEvalOk = 0
return 0
k: int = node.kind()
# Constant: 整数字面量
if k == ast.ASTKind.Constant:
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn.const_kind == ast.CONST_INT:
self.ConstEvalOk = 1
return cn.int_val
self.ConstEvalOk = 0
return 0
# Name: CDefine 常量名(本地表优先,未命中走跨模块查找)
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node)
if nm.id is None:
self.ConstEvalOk = 0
return 0
val: int = self.Gen.TypeGenCDef.lookup_cdefine_constant(nm.id)
if self.Gen.TypeGenCDef.is_cdefine_found() == 0:
# 本地表未命中:跨模块 CDefine 查找
# 用 HandlesExpr 模块级委托(self._lookup_cross_module_cdefine 是
# ExprGenMixin 方法,TypeGenMixin 直接调用会生成未定义引用)
if (from_imports is not None or imported_modules is not None) \
and pool is not None:
import lib.core.Handles.HandlesExpr as HandlesExpr
x_val: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, nm.id, from_imports, imported_modules)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return x_val
# 定位日志:跨模块 CDefine 查找失败(t.CArray count 场景)
fb_cdf: str = VLogger.fmt_buf()
if fb_cdf is not None:
viperlib.snprintf(fb_cdf, 1024,
"[CDEF-MISS] name=%s fi=%s im=%s",
nm.id,
from_imports if from_imports is not None else "(null)",
imported_modules if imported_modules is not None else "(null)")
VLogger.error(fb_cdf, "CDEF")
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return val
# Attribute: 模块限定常量名,如 hashlib.MD5_DIGEST_LEN
# (t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] 的 count 是 Attribute,
# 复用跨模块 CDefine 查找:*:模块 → 源文件提取;re-export 常量由
# _lookup_cross_module_cdefine 的 from-import 递归子模块兜底)
if k == ast.ASTKind.Attribute:
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
if at.attr is None:
self.ConstEvalOk = 0
return 0
if at.value is not None and at.value.kind() == ast.ASTKind.Name:
at_mod: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if at_mod.id is not None:
if (from_imports is not None or imported_modules is not None) \
and pool is not None:
mod_len: t.CSizeT = string.strlen(at_mod.id)
fi_buf: str = pool.alloc(mod_len + 3)
if fi_buf is not None:
fi_buf[0] = '*'
fi_buf[1] = ':'
for mi in range(mod_len):
fi_buf[2 + mi] = at_mod.id[mi]
fi_buf[2 + mod_len] = '\0'
import lib.core.Handles.HandlesExpr as HandlesExpr
av: int = self.Gen.ExprGenCdef._lookup_cross_module_cdefine(
pool, at.attr, fi_buf, imported_modules)
if self.Gen.TypeGenCDef.is_cdefine_found() != 0:
self.ConstEvalOk = 1
return av
self.ConstEvalOk = 0
return 0
# BinOp: 算术/位运算
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
# 递归计算左操作数
lv: int = self._eval_const_int_expr(bop.left, pool, from_imports, imported_modules)
if self.ConstEvalOk == 0:
return 0
# 递归计算右操作数
rv: int = self._eval_const_int_expr(bop.right, pool, from_imports, imported_modules)
if self.ConstEvalOk == 0:
return 0
# 根据运算符执行计算
if bop.op == ast.OpKind.Add:
self.ConstEvalOk = 1
return lv + rv
if bop.op == ast.OpKind.Sub:
self.ConstEvalOk = 1
return lv - rv
if bop.op == ast.OpKind.Mult:
self.ConstEvalOk = 1
return lv * rv
if bop.op == ast.OpKind.Div:
# 整数常量除法:与 FloorDiv 一致(对齐 TPC ConstEvaluator L354-355)
if rv == 0:
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return lv // rv
if bop.op == ast.OpKind.FloorDiv:
if rv == 0:
self.ConstEvalOk = 0
return 0
self.ConstEvalOk = 1
return lv // rv
if bop.op == ast.OpKind.BitOr:
self.ConstEvalOk = 1
return lv | rv
if bop.op == ast.OpKind.BitAnd:
self.ConstEvalOk = 1
return lv & rv
# 不支持的运算符
self.ConstEvalOk = 0
return 0
# 不支持的节点类型
self.ConstEvalOk = 0
return 0
+11 -20
View File
@@ -1,3 +1,5 @@
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import ast
@@ -9,20 +11,9 @@ import stdio
import stdlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.StubMerger as StubMerger
import lib.core.CompilerFactory as CompilerFactory
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.TypeGenBase as TypeGenBase
@@ -123,8 +114,8 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
stdio.printf("Traceback (most recent call last):\n")
# 输出调用栈帧(从底到顶)
i: int
for i in range(self.TraceCount):
frame: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(i)
for i in range(self.Gen.TypeGenBase.TraceCount):
frame: GenTypes.TraceFrame | t.CPtr = self.Gen.TypeGenBase._get_trace_frame(i)
if frame is not None and frame.file_name is not None:
if frame.lineno > 0:
stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno)
@@ -138,16 +129,16 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
lineno: int = 0
if node is not None:
lineno = node.lineno
file_name: str = self.CurrentFile
file_name: str = self.Gen.TypeGenResolve.get_current_file()
if file_name is None:
file_name = "<unknown>"
# 行号兜底:克隆/构造节点 lineno 可能为 0(如泛型特化 _clone_arguments 的
# ast.Arg 构造器硬编码 0,astaux.vp L139)。此时回退到 trace 栈最后一个
# 有效帧(文件+行号)作为出错位置,避免输出误导性的 "line 0"。
if lineno <= 0 and self.TraceCount > 0:
ti_b: int = self.TraceCount - 1
if lineno <= 0 and self.Gen.TypeGenBase.TraceCount > 0:
ti_b: int = self.Gen.TypeGenBase.TraceCount - 1
while ti_b >= 0:
tfb: HandlesType.TraceFrame | t.CPtr = HandlesType._get_trace_frame(ti_b)
tfb: GenTypes.TraceFrame | t.CPtr = self.Gen.TypeGenBase._get_trace_frame(ti_b)
if tfb is not None and tfb.file_name is not None and tfb.lineno > 0:
file_name = tfb.file_name
lineno = tfb.lineno
@@ -213,7 +204,7 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
ret_node_cr: ast.AST | t.CPtr = tp_cr.elts.get(1)
if ret_node_cr is None:
return None
return HandlesType.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans)
return self.Gen.TypeGenResolve.resolve_annotation_type(pool, ret_node_cr, imported_modules, from_imports, trans)
def has_decorator_marker(self, node: ast.AST | t.CPtr,
marker_name: str) -> int:
"""检测类型注解中是否包含指定的装饰器标记"""
@@ -366,7 +357,7 @@ class TypeGenErr(TypeGenBase.TypeGenBase):
if arg.annotation.kind() == ast.ASTKind.Attribute:
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
if at.attr is not None:
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr)
resolved: llvmlite.LLVMType | t.CPtr = self.Gen.TypeGenResolve.map_t_type(pool, at.attr)
if resolved is not None:
param_ty = resolved
bits: int = self.get_llvm_type_bits(param_ty)
+40 -44
View File
@@ -1,44 +1,40 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import sys
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesEnum as HandlesEnum
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenMixin - 类型映射与解析 Mixin(对象化 P2,wiki/14-oo-refactor.md)
#
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
# TypeGenBase/CDef/CType/Resolve/Err,本文件保留类声明(Generator 继承链入口)。
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
# ============================================================
# ============================================================
# 常量(与 HandlesType 保持一致)
# ============================================================
TRACE_MAX: t.CDefine = 32
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
# ============================================================
# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报
# ============================================================
@t.NoVTable
class TypeGenMixin(TypeGenBase.TypeGenBase):
"""类型映射与解析 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import sys
import stdlib
import viperlib
import w32.fileio as fileio
import lib.core.CompilerFactory as CompilerFactory
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.TypeGenBase as TypeGenBase
# ============================================================
# TypeGenMixin - 类型映射与解析 Mixin(对象化 P2,wiki/14-oo-refactor.md)
#
# 500~1500 行/文件架构重构阶段 D:全部方法已拆至
# TypeGenBase/CDef/CType/Resolve/Err,本文件保留类声明(Generator 继承链入口)。
#
# @t.NoVTable:静态绑定(方法沿 MRO 直接调用 + this 调整,无 vtable 开销)。
# ============================================================
# ============================================================
# 常量(与 HandlesType 保持一致)
# ============================================================
TRACE_MAX: t.CDefine = 32
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
# ============================================================
# TypeGenMixin - 类型映射/注解解析/编译期常量表/错误上报
# ============================================================
@t.NoVTable
class TypeGenMixin(TypeGenBase.TypeGenBase):
"""类型映射与解析 Mixin(阶段 D 拆分后顶层,方法全部在子 Mixin)"""
File diff suppressed because it is too large. Load diff
+404 -403
View File
@@ -1,403 +1,404 @@
import t, c
from stdint import *
import llvmlite
import memhub
import string
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
# ============================================================
# 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
# 每个作用域最大变量数
# 256 太小:NewAstTest main() 有 289 个局部变量(几十个测试用例),
# add_var 超限静默失败导致变量未注册,后续使用报"未定义名称"(NameError)。
MAX_VARS: t.CDefine = 1024
# ============================================================
# 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
if self.define_var(symtab, name, alloca) != 0:
# fail-fast: 变量注册失败(如超过 MAX_VARS)必须立即终止。
# 此前静默忽略返回值:alloca 已创建但未入符号表,后续读取该变量
# 报"未定义名称"(NewAstTest main() 289 个局部变量 > MAX_VARS=256
# 的 NameError 根因),误导排查。变量表超限暴露上游规模问题。
HandlesType.fatal_error(
None,
f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)",
"InternalCompilerError")
return alloca
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.Generator as Generator
import t, c
from stdint import *
import llvmlite
import memhub
import string
# ============================================================
# 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
# 每个作用域最大变量数
# 256 太小:NewAstTest main() 有 289 个局部变量(几十个测试用例),
# add_var 超限静默失败导致变量未注册,后续使用报"未定义名称"(NameError)。
MAX_VARS: t.CDefine = 1024
# ============================================================
# VarGenMixin - 变量/作用域符号表 Mixin
# ============================================================
@t.NoVTable
class VarGenMixin:
"""变量/作用域 Mixin(P6 方法化)"""
# 迁移自 HandlesVar 的模块级函数
# ============================================================
# init_vars — 分配并清零 VarEntry 数组
# ============================================================
Gen: Generator.Generator | t.CPtr
def init_vars(self, pool: memhub.MemBuddy | t.CPtr) -> GenTypes.VarEntry | t.CPtr:
"""分配并清零变量表数组"""
size: t.CSizeT = MAX_VARS * GenTypes.VarEntry.__sizeof__()
vars_ptr: GenTypes.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: GenTypes.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 = GenTypes.VarEntry.__sizeof__()
for i in range(var_count):
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.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: GenTypes.VarEntry | t.CPtr,
var_count: int,
name: str) -> GenTypes.VarEntry | t.CPtr:
"""在变量表中按名称查找,返回 VarEntry 或 None"""
if name is None or vars_ptr is None:
return None
entry_size: t.CSizeT = GenTypes.VarEntry.__sizeof__()
for i in range(var_count):
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str) -> GenTypes.VarEntry | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
if symtab is None or name is None:
return None
scope: GenTypes.Scope | t.CPtr = symtab.Current
while scope is not None:
result: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str,
class_name: str) -> int:
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
if symtab is None or name is None:
return 1
entry: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str) -> int:
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
if symtab is None or name is None:
return 1
entry: GenTypes.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: GenTypes.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 = GenTypes.VarEntry.__sizeof__()
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
entry: GenTypes.VarEntry | t.CPtr = (GenTypes.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: GenTypes.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: GenTypes.Scope | t.CPtr,
kind: int) -> GenTypes.Scope | t.CPtr:
"""创建并初始化作用域节点"""
scope: GenTypes.Scope | t.CPtr = pool.alloc(GenTypes.Scope.__sizeof__())
if scope is None:
return None
string.memset(scope, 0, GenTypes.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) -> GenTypes.SymbolTable | t.CPtr:
"""创建并初始化符号表,包含模块级根作用域"""
if pool is None:
return None
symtab: GenTypes.SymbolTable | t.CPtr = pool.alloc(GenTypes.SymbolTable.__sizeof__())
if symtab is None:
return None
string.memset(symtab, 0, GenTypes.SymbolTable.__sizeof__())
symtab.Pool = pool
# 创建根作用域(模块级)
root: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
kind: int) -> GenTypes.Scope | t.CPtr:
"""进入新作用域,返回新创建的作用域"""
if symtab is None:
return None
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
scope: GenTypes.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: GenTypes.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: GenTypes.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: GenTypes.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: GenTypes.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: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
if symtab is None or name is None:
return None
scope: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""仅在当前作用域查找变量"""
if symtab is None or name is None:
return None
scope: GenTypes.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: GenTypes.SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""在模块作用域查找变量"""
if symtab is None or name is None:
return None
scope: GenTypes.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: GenTypes.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: GenTypes.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
if self.define_var(symtab, name, alloca) != 0:
# fail-fast: 变量注册失败(如超过 MAX_VARS)必须立即终止。
# 此前静默忽略返回值:alloca 已创建但未入符号表,后续读取该变量
# 报"未定义名称"(NewAstTest main() 289 个局部变量 > MAX_VARS=256
# 的 NameError 根因),误导排查。变量表超限暴露上游规模问题。
self.Gen.TypeGenErr.fatal_error(
None,
f"变量 '{name}' 注册失败(作用域变量数超过上限 MAX_VARS)",
"InternalCompilerError")
return alloca
-246
View File
@@ -1,246 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallDeref as ExprCallDeref
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.ExprCallHandle as ExprCallHandle
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallBase - HandlesExprCall 拆分(阶段 E):ExprCallBase
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# _lookup_module_sha1 — 按模块名查找 SHA1(委托到 gen._lookup_module_sha1)
# ============================================================
# ============================================================
# 模块 SHA1 查询(委托给 StubMerger 全局存储器)
#
# 翻译时用于跨模块函数调用名混淆:
# string.strchr(...) → call @{sha1_of_string}.strchr(...)
#
# 数据来源是 StubMerger.PopulateSha1MapStore/AppendToSha1MapStore
# 填充的全局存储器,不再维护独立的 SHA1 映射表副本。
# ============================================================
def _lookup_module_sha1(mod_name: str) -> str:
"""查找模块名对应的 SHA1,找不到返回 None(委托到 gen._lookup_module_sha1)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._lookup_module_sha1(mod_name)
return None
def _lookup_module_sha1_suffix(mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1(委托到 gen._lookup_module_sha1_suffix)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._lookup_module_sha1_suffix(mod_suffix)
return None
# ============================================================
# 全局 CExport 函数表(module_sha1 + func_name)
#
# t.CExport 函数定义时不加 SHA1 前缀(如 @strlen),
# 跨模块调用时需要查表确认目标函数是否是 CExport 函数。
# 若是,使用裸名调用(@strlen);否则使用 @{sha1}.func。
# 必须包含模块 SHA1 记录,避免同名跨模块函数冲突
# (一个模块有 CExport 的 strlen→@strlen,另一个没有→@{sha1}.strlen)。
#
# 注:表数据已迁入 gen 字段(CallGenMixin.CexportSha1Arr/CexportFuncArr/
# CexportCount),本模块不再持有(P4 簇 1+2)。
# ============================================================
_CEXPORT_MAX: t.CDefine = 256
def register_cexport_func(sha1: str, func_name: str) -> int:
"""注册 CExport 函数到全局表(委托到 gen.register_cexport_func)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.register_cexport_func(sha1, func_name)
return 0
def is_cexport_func(sha1: str, func_name: str) -> int:
"""检查(sha1, func_name) 是否是 CExport 函数(委托到 gen.is_cexport_func)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.is_cexport_func(sha1, func_name)
return 0
# ============================================================
# _lookup_mod_sha1 - 从 from_imports 查找类所属模块的 SHA1
#
# lookup_from_import 返回指向 from_imports 内部的指针,不是 null 终止
# (如 "namespace_defs Gadget:namespace_defs ...")。此函数手动截断
# 模块名,复制到新缓冲区,再查找 SHA1(精确+后缀匹配)。
# ============================================================
def _lookup_mod_sha1(pool: memhub.MemBuddy | t.CPtr,
from_imports: str, class_name: str,
allow_star_fallback: int = 1) -> str:
"""从 from_imports 查找类所属模块的 SHA1(委托到 gen._lookup_mod_sha1)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._lookup_mod_sha1(pool, from_imports, class_name, allow_star_fallback)
return None
# ============================================================
# _lookup_sha1_from_modname_raw - 原始模块名 → SHA1
#
# 截断模块名(lookup_from_import 返回内部指针,空格/冒号/null 分隔),
# 去掉相对导入前导点,再精确+后缀查找 SHA1。
# 供 _lookup_mod_sha1 与 HandlesExpr._lookup_cross_module_cdefine 复用。
# ============================================================
def _lookup_sha1_from_modname_raw(pool: memhub.MemBuddy | t.CPtr,
mod_name_raw: str) -> str:
"""从原始模块名查找 SHA1(委托到 gen._lookup_sha1_from_modname_raw)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._lookup_sha1_from_modname_raw(pool, mod_name_raw)
return None
# ============================================================
# HandlesExprCall - 函数调用表达式处理(Mixin 继承模式)
#
# 工具函数和 HandlesExprCall.FuncEntry 保留为模块级,HandlesExprCall.ExprCallHandle 提供 trans 接口
# ============================================================
# ============================================================
# 在模块函数链表中按名称查找函数
# ============================================================
def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr,
name: str) -> llvmlite.Function | t.CPtr:
"""在模块的函数链表中按名称查找函数(委托到 gen.find_func_in_module)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.find_func_in_module(mod, name)
return None
# ============================================================
# _ensure_c_lib_declare - 为已知的 C 库函数创建 declare 声明
#
# 对应 TPC 的 _C_LIB_FUNCS 机制。当裸名调用 memset/memmove/memcmp/
# strcmp/strlen 等已知 C 库函数时,自动在当前模块创建 declare,
# 避免报 "裸名调用未定义且未导入" 错误。
# memcpy 不在此处理(已有 _emit_llvm_memcpy_intrinsic 映射到 @llvm.memcpy)。
#
# Args:
# pool: 内存池
# mod: LLVM 模块
# name: 函数名
#
# Returns:
# Function 指针(已创建 declare),或 None 如果不是已知 C 库函数
# ============================================================
def _ensure_c_lib_declare(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
name: str) -> llvmlite.Function | t.CPtr:
"""为已知的 C 库函数创建 declare 声明(委托到 gen._ensure_c_lib_declare)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._ensure_c_lib_declare(pool, mod, name)
return None
# ============================================================
# _infer_external_func_ret_ty - 根据函数名推断外部函数返回类型
#
# stubs 在翻译后才注入 IR,翻译时模块中无 stub 函数声明,
# 因此对 includes 库函数(如 string.strchr 返回 i8*)需根据
# 函数名推断返回类型,避免指针被截断为 i32。
#
# 覆盖 includes/string.py 所有导出函数:
# i8*: strcpy, strncpy, strchr, strrchr, strstr, memset, memset32, memcpy, memmove
# i64: strlen, atoll
# double: atof
# i8: samestr
# i32(默认): strcmp, strncmp, memcmp, strspn, atoi, split
# ============================================================
def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name: str) -> llvmlite.LLVMType | t.CPtr:
"""根据函数名推断外部 includes 函数的返回类型(委托到 gen._infer_external_func_ret_ty)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._infer_external_func_ret_ty(pool, func_name)
return None
# ============================================================
# _get_external_func_param_ty - 获取外部函数第 idx 个参数的期望类型
#
# stubs 翻译时未注入,需推断参数类型以提升字面量(如 i32→i64),
# 避免 declare(i64) 与 call(i32) 类型不匹配。
#
# 注意:stubs 翻译时 ULONG(t.CUnsignedLong) 在 LLVM IR 中被翻译为 i64
# (因为 LLVM 中 long 是 64 位),因此 Win32 API 中所有 ULONG/DWORD/SIZE_T
# 参数在 declare 中都是 i64。call 时必须匹配,否则类型不匹配。
#
# 策略:对 Win32 API 函数的所有非指针参数(字面量)都提升为 i64,
# 以匹配 declare 中 ULONG 被翻译为 i64 的情况。
#
# 指针参数(VOIDPTR/HANDLE)不在此处理,由调用点的 inttoptr 处理。
# ============================================================
def _get_external_func_param_ty(pool: memhub.MemBuddy | t.CPtr,
func_name: str,
param_idx: int) -> llvmlite.LLVMType | t.CPtr:
"""获取外部函数第 param_idx 个参数的期望类型(委托到 gen._get_external_func_param_ty)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._get_external_func_param_ty(pool, func_name, param_idx)
return None
# ============================================================
# _emit_llvm_memcpy_intrinsic — 将 memcpy 调用映射到 @llvm.memcpy 内联函数
#
# 背景: string.memcpy 是 t.CExport 函数,跨模块调用生成 @memcpy 裸名调用。
# 但在 monomorphization 场景下,目标模块的 deps.txt 可能不含 string,
# 导致 @memcpy 声明缺失,链接器报 undefined value。
#
# 解决: 将 memcpy 调用映射到 LLVM 内联函数 @llvm.memcpy,
# 该内联函数在当前模块内声明,无需跨模块依赖。
#
# @llvm.memcpy 签名: void(i8* dst, i8* src, i64 len, i1 isvolatile)
# C memcpy 签名: i8* (i8* dst, i8* src, i64 len) — 返回 dst
#
# Args:
# args_head: 参数链表头(dst, src, num),通过 Value.Next 链接
# arg_count: 参数数量(应为 3)
#
# Returns:
# dst 值(匹配 C memcpy 语义: 返回 dest 指针)
# ============================================================
def _emit_llvm_memcpy_intrinsic(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
dst_val: llvmlite.Value | t.CPtr,
src_val: llvmlite.Value | t.CPtr,
num_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
"""将 memcpy 调用映射到 @llvm.memcpy 内联函数(委托到 gen._emit_llvm_memcpy_intrinsic)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._emit_llvm_memcpy_intrinsic(pool, builder, mod, dst_val, src_val, num_val)
return None
-338
View File
@@ -1,338 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallDeref as ExprCallDeref
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.ExprCallHandle as ExprCallHandle
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallCall - HandlesExprCall 拆分(阶段 E):ExprCallCall
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# 翻译函数调用 Call(func, args) — 模块级版本
# ============================================================
def translate_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译函数调用,返回 call 结果 Value(委托到 gen.translate_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_call(pool, builder, mod, node, funcs_ptr, func_count, trans)
return None
# ============================================================
# 翻译闭包调用 — 通过闭包指针间接调用
#
# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节)
# 调用过程:
# 1. load closure_ptr 从变量 alloca
# 2. load fn_ptr 从 offset 0
# 3. load env_ptr 从 offset 8
# 4. bitcast fn_ptr to i32(i8*)*
# 5. call i32 %fn_typed(i8* %env_ptr)
# ============================================================
def translate_closure_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
closure_alloca: llvmlite.Value | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""通过闭包指针间接调用(委托到 gen.translate_closure_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_closure_call(pool, builder, mod, closure_alloca, cargs, can, trans)
return None
# ============================================================
# _is_func_ptr_alloca - 判断变量 alloca 是否为函数指针变量
#
# 函数指针变量(t.Callable 注解 → i8*)的 alloca 类型是 Ptr(Ptr(i8)) = i8**;
# 闭包变量 alloca 是 i8*(Ptr(i8))。通过类型层级区分。
# ============================================================
def _is_func_ptr_alloca(alloca: llvmlite.Value | t.CPtr) -> int:
"""判断 alloca 是否为函数指针变量(类型 Ptr(Ptr(i8))),1=是 / 0=否(委托到 gen._is_func_ptr_alloca)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._is_func_ptr_alloca(alloca)
return 0
# ============================================================
# 闭包变量名集合(stdlib 分配,懒初始化)
#
# 背景: 嵌套函数提升后闭包变量 alloca 类型是 i8**(alloca i8*),
# 与函数指针变量(t.Callable → i8** alloca)类型完全相同,_is_func_ptr_alloca
# 无法区分,导致 inner() 被误判为函数指针调用(直接 bitcast 闭包对象到函数指针、
# 无 env 参数调用 → 运行时崩溃)。translate_nested_function_def 创建闭包时
# 注册嵌套函数名,调用时优先按闭包调用处理。
# ============================================================
MAX_CLOSURE_NAMES: t.CDefine = 128
def _ensure_closure_names() -> int:
"""确保闭包名表已分配,0 失败(委托到 gen._ensure_closure_names)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._ensure_closure_names()
return 0
def register_closure_name(name: str) -> int:
"""注册嵌套函数(闭包变量)名,0 成功(委托到 gen.register_closure_name)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.register_closure_name(name)
return 0
def is_closure_name(name: str) -> int:
"""检查 name 是否已注册为闭包变量名,1=是 / 0=否(委托到 gen.is_closure_name)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.is_closure_name(name)
return 0
# ============================================================
# 函数指针变量签名表(变量名 → 返回类型)
#
# AnnAssign 处理 t.Callable 注解时注册,函数指针间接调用时
# 按注册的返回类型构造签名(而非默认 i32)。
# ============================================================
MAX_FUNC_PTR_SIGS: t.CDefine = 64
def _ensure_funcptr_sigs() -> int:
"""确保函数指针签名表已分配(stdlib.malloc,懒初始化)(委托到 gen._ensure_funcptr_sigs)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._ensure_funcptr_sigs()
return 0
def register_func_ptr_sig(name: str,
ret_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""注册函数指针变量的返回类型签名,0 成功(委托到 gen.register_func_ptr_sig)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.register_func_ptr_sig(name, ret_ty)
return 0
def lookup_func_ptr_ret(name: str) -> llvmlite.LLVMType | t.CPtr:
"""查函数指针变量的返回类型,None=未注册(调用时默认 i32)(委托到 gen.lookup_func_ptr_ret)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.lookup_func_ptr_ret(name)
return None
# ============================================================
# _translate_func_ptr_call - 函数指针变量间接调用
#
# func_p: t.Callable[[A, B], Ret] 后调用 func_p(a, b):
# 1. load 函数地址(i8*)
# 2. 翻译实参并链接为 Value 链表
# 3. 按实参类型 + 注册的返回类型构造签名(未注册时默认 i32)
# 4. bitcast i8* → 函数指针类型,间接调用
# ============================================================
def _translate_func_ptr_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
fp_alloca: llvmlite.Value | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""函数指针变量间接调用,返回结果 Value(委托到 gen._translate_func_ptr_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_func_ptr_call(pool, builder, mod, fp_alloca, func_name, cargs, can, trans)
return None
# ============================================================
# 翻译 printf 调用 — 模块级版本
# ============================================================
def translate_printf_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None):
"""翻译 printf 调用(特殊处理格式字符串)(委托到 gen.translate_printf_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g.translate_printf_call(pool, builder, mod, cl, trans)
# ============================================================
# 翻译 print 调用 — 类型感知格式化 + 默认换行
#
# 与 printf 不同,print 不需要用户提供格式串:每个参数按 LLVM
# 类型自动选择格式(%s/%d/%f/0x%llx),结尾追加 "\n"(对齐 Python
# print 默认 end="\n",以及 TPC HandlesExprBuiltin._HandlePrintLlvm)。
#
# 类型分派规则:
# i8*(str/bytes) → %s
# 其他指针(struct*/int*) → 0x%llx(ptrtoint 到 i64)
# i1(bool) → %d(zext 到 i32)
# i8/i16/i32 → %d(sext 到 i32,C ABI 整数提升)
# i64 → %lld
# float/double → %f(float fpext 到 double,C ABI 提升)
# 无法识别的类型 → "(unknown)"(不传参)
# ============================================================
def translate_print_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None):
"""翻译 print 调用(类型感知格式化 + 默认换行)(委托到 gen.translate_print_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g.translate_print_call(pool, builder, mod, cl, trans)
# ============================================================
# stdarg 糖函数实现: va_arg / arg / va_start / va_end
#
# 这些函数对应 stdarg.vp 中的 pass 体声明,由编译器在翻译期
# 转换为 LLVM 指令或 intrinsic 调用,不生成函数 call。
#
# va_list 在 TPV 中表示为 i8*(与 stdarg.vp 中 va_list = t.CUnsignedChar | t.CPtr 一致)。
# va_list 对象存储在 alloca 中(i8**),va_arg/va_start/va_end 需要传入 alloca 指针。
# ============================================================
def _va_arg_get_alloca_ptr(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
arg_node: ast.AST | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""获取 va_list 变量的 alloca 指针(不 load)(委托到 gen._va_arg_get_alloca_ptr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._va_arg_get_alloca_ptr(pool, builder, mod, arg_node, funcs_ptr, func_count, trans)
return None
def _resolve_va_arg_type(pool: memhub.MemBuddy | t.CPtr,
type_node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""解析 va_arg/arg 的类型参数为 LLVMType(委托到 gen._resolve_va_arg_type)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._resolve_va_arg_type(pool, type_node, trans)
return None
def _translate_va_arg_sugar(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_arg(ap, type) / va_arg(ap) → %N = va_arg <ap_ty> <ap>, <type>(委托到 gen._translate_va_arg_sugar)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_va_arg_sugar(pool, builder, mod, cl, cargs, can, funcs_ptr, func_count, trans)
return None
def _translate_arg_sugar(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""arg(type) → %N = va_arg <va_list_ty> <trans._va_list_ptr>, <type>(委托到 gen._translate_arg_sugar)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_arg_sugar(pool, builder, mod, cl, cargs, can, funcs_ptr, func_count, trans)
return None
def _translate_va_start_sugar(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_start(ap, last_arg) → call void @llvm.va_start(i8* %ap)(委托到 gen._translate_va_start_sugar)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_va_start_sugar(pool, builder, mod, cargs, can, funcs_ptr, func_count, trans)
return None
def _translate_va_end_sugar(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""va_end(ap) → call void @llvm.va_end(i8* %ap)(委托到 gen._translate_va_end_sugar)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_va_end_sugar(pool, builder, mod, cargs, can, funcs_ptr, func_count, trans)
return None
# ============================================================
# 变长函数调用支持: 检查 IsVarArg + C ABI 参数提升
#
# C ABI 要求变长参数(...部分)进行默认提升:
# 整数提升: i8/i16 → i32(sext/zext)
# 浮点提升: float → double(fpext)
# 固定参数不需要提升(有明确类型签名)。
# ============================================================
def _get_func_fixed_param_count(func: llvmlite.Function | t.CPtr) -> int:
"""获取函数的固定参数数量(遍历 Params 链表)(委托到 gen._get_func_fixed_param_count)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._get_func_fixed_param_count(func)
return 0
def _check_and_promote_variadic_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
call_name: str,
head: llvmlite.Value | t.CPtr,
can: t.CSizeT,
arg_nodes: list[ast.AST | t.CPtr] | t.CPtr = None,
self_offset: int = 0,
trans: HT.Translator | t.CPtr = None) -> int:
"""检查被调用函数是否为变长函数,若是则对变长参数进行 C ABI 提升(委托到 gen._check_and_promote_variadic_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._check_and_promote_variadic_call(pool, builder, mod, call_name, head, can,
arg_nodes, self_offset, trans)
return 0
-622
View File
@@ -1,622 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallDeref as ExprCallDeref
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.ExprCallHandle as ExprCallHandle
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallCtor - HandlesExprCall 拆分(阶段 E):ExprCallCtor
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# _apply_struct_defaults — 应用结构体字段的默认值
#
# 在 zeroinitializer 之后、显式参数之前调用
# 遍历所有字段,对有默认值的字段翻译并 store
# 显式参数(位置/关键字)后续会覆盖默认值
# ============================================================
def _apply_struct_defaults(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
tmp: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr):
"""应用结构体字段的默认值(委托到 gen._apply_struct_defaults)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans)
# ============================================================
# _translate_struct_ctor — 结构体构造函数 Point(10, 20)
#
# 生成:
# %tmp = alloca {i32, i32}
# store {i32, i32} zeroinitializer, {i32, i32}* %tmp
# %f0 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 0
# store i32 10, i32* %f0
# %f1 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 1
# store i32 20, i32* %f1
# %result = load {i32, i32}, {i32, i32}* %tmp
# ============================================================
def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""结构体构造函数:按字段顺序 store 参数值,返回结构体值(委托到 gen._translate_struct_ctor)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_struct_ctor(pool, builder, mod, struct_ty, class_name, cargs, can, trans)
return None
# ============================================================
# _translate_renum_construct — REnum 变体构造函数
#
# 语法: ClassName.VariantName(args...)
# 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体,__tag=0,_p1=1
#
# 生成 IR:
# %tmp = alloca {i32, i32, ...} ; REnum 类型
# store zeroinitializer, %tmp ; 清零
# %tag_ptr = gep %tmp, 0, 0 ; __tag 字段
# store i32 <tag_value>, %tag_ptr ; 写入 tag
# %p1_ptr = gep %tmp, 0, 1 ; _p1 字段
# store <coerced_arg0>, %p1_ptr ; 写入 payload[0]
# ... (更多 payload 字段)
# return %tmp ; 返回指针
#
# 对应 TPC 的 _HandleREnumConstructLlvm
# ============================================================
def _translate_renum_construct(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
variant_name: str,
tag_value: int,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""构造 REnum 变体实例,返回指向 alloca 的指针(委托到 gen._translate_renum_construct)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_renum_construct(pool, builder, mod, class_name, variant_name,
tag_value, cargs, can, trans)
return None
# ============================================================
# _do_virtual_call — 通过虚表间接调用虚方法
#
# IR 模式:
# %1 = getelementptr StructTy, StructTy* %self, i32 0, i32 0 ; i8**
# %2 = load i8*, i8** %1 ; i8* (vtable ptr)
# %3 = bitcast i8* %2 to {i8*, ...}* ; vtable typed ptr
# %4 = getelementptr {i8*, ...}, {i8*, ...}* %3, i32 0, i32 N ; i8**
# %5 = load i8*, i8** %4 ; i8* (func ptr)
# %6 = bitcast i8* %5 to RetTy(Params)* ; func typed ptr
# call RetTy %6(Params %self, ...)
#
# 参数:
# args_head — 已构建好的参数链表头(self_ptr 为首节点)
# args_count — 参数总数(含 self)
# found_func — 方法对应的 Function 对象(用于推断函数签名)
# ret_ty — 返回类型
# ============================================================
def _do_virtual_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
self_ptr: llvmlite.Value | t.CPtr,
args_head: llvmlite.Value | t.CPtr,
args_count: int,
found_func: llvmlite.Function | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr,
vtable_base: llvmlite.Value | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""通过虚表间接调用虚方法,返回 call 结果(void 方法返回 None)(委托到 gen._do_virtual_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._do_virtual_call(pool, builder, mod, class_name, method_name,
self_ptr, args_head, args_count, found_func, ret_ty, vtable_base)
return None
# ============================================================
# _call_method_on_ptr — 在结构体指针上调用方法
#
# 辅助函数:构造 ClassName.method_name 调用,self 指针为首个参数
# 如果该方法在虚表中,则走虚方法分发路径(间接调用)
# ============================================================
def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
self_ptr: llvmlite.Value | t.CPtr,
extra_args: t.CSizeT | t.CPtr,
extra_count: int,
trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""在结构体指针上调用方法,返回 call 结果(void 方法返回 None)(委托到 gen._call_method_on_ptr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._call_method_on_ptr(pool, builder, mod, class_name, method_name,
self_ptr, extra_args, extra_count, trans, node)
return None
# ============================================================
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
#
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
# ============================================================
def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
call_name: str,
ret_ty: llvmlite.LLVMType | t.CPtr,
param_head: llvmlite.ParamNode | t.CPtr,
param_count: int):
"""为跨模块方法调用创建 declare 声明(委托到 gen._ensure_method_declare)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g._ensure_method_declare(pool, mod, call_name, ret_ty, param_head, param_count)
# ============================================================
# _lookup_method_ret_ty_via_vpi - 从 vpi stub 返回注解缓存精确获取方法返回类型
#
# 方法定义处(.vpi stub)的返回注解(如 json.JsonValue._pool_alloc →
# "str")在 stub 注入时由 VpiReader 缓存(_cache_vpi_return_annots_text)。
# 此函数按 模块SHA1 + 类名 + 方法名 查缓存并纯字符串解析为 LLVMType。
# 无需硬编码白名单——返回类型始终来自方法定义处。
# ============================================================
def _lookup_method_ret_ty_via_vpi(pool: memhub.MemBuddy | t.CPtr,
cls_sha1: str,
cls_name: str,
method_name: str) -> llvmlite.LLVMType | t.CPtr:
"""从 vpi stub 返回注解缓存获取方法返回类型,未命中返回 None(委托到 gen._lookup_method_ret_ty_via_vpi)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._lookup_method_ret_ty_via_vpi(pool, cls_sha1, cls_name, method_name)
return None
# ============================================================
# _special_method_ret_ty - 编译器内置特殊方法的固定返回类型
#
# __before_init__ / __init__:编译器生成/约定返回 void
# __new__:返回 Ptr(StructTy)(存储空间指针)
#
# 这些方法不存在于源码(vpi stub 无条目),跨模块调用时
# found_func/text.ll/vpi 缓存必然未命中,但返回类型是编译器
# 确定性语义(与 HandlesClassDef._translate_method 3543-3548 一致),
# 在此直接固定,不触发 fail-fast 误报。非特殊方法返回 None。
# ============================================================
def _special_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
class_name: str,
method_name: str) -> llvmlite.LLVMType | t.CPtr:
"""编译器内置特殊方法的固定返回类型;非特殊返回 None(委托到 gen._special_method_ret_ty)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._special_method_ret_ty(pool, class_name, method_name)
return None
# ============================================================
# _fail_method_ret_ty - 方法返回类型无法精确获取时 fail-fast
#
# 返回类型来源(按序):当前模块函数 → text.ll define → vpi stub 返回注解缓存。
# 全部未命中时立即 ERROR + 错误堆栈终止,绝不按名推断白名单/静默默认 i32。
#
# node: 调用点 AST 节点(可选,用于 ERROR 堆栈定位)
# ============================================================
def _fail_method_ret_ty(method_name: str,
node: ast.AST | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
"""方法返回类型无法精确获取时 fail-fast(ERROR + 错误堆栈)(委托到 gen._fail_method_ret_ty)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._fail_method_ret_ty(method_name, node)
return None
# ============================================================
# 跨模块方法返回类型查找(从 text.ll)
#
# Phase A 翻译每个源文件后生成 text.ll,其中 define 行包含
# 方法的实际返回类型。当 Phase A 翻译后续文件调用跨模块方法时,
# 方法调用默认返回 i32,导致指针返回值被截断。
# _LookupMethodRetTyFromTextLL 读取依赖模块的 text.ll,从 define
# 行提取实际返回类型,避免指针截断(未命中时回退 vpi stub 缓存)。
# ============================================================
# ============================================================
# SetTempDir - 设置 temp 目录路径
#
# 在 Phase2.py 的 Phase A 翻译前调用,使 CallGenMixin
# 能够读取依赖模块的 text.ll 文件。
# ============================================================
def SetTempDir(temp_dir: str):
"""设置 temp 目录路径(供跨模块方法返回类型查找使用)(委托到 gen.SetTempDir)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g.SetTempDir(temp_dir)
# ============================================================
# _ParseLLVMRetTyStr - 将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType
#
# 从 define 行中提取的返回类型字符串(define 与 @ 之间的内容),
# 转换为 llvmlite.LLVMType 对象。
#
# 支持的类型:
# void → Void
# i8/i16/i32/i64 → Int8/Int16/Int32/Int64
# double → Double, float → Float
# 任何含 * 的类型 → Ptr(Int8)(通用指针,保留 64 位地址)
#
# Args:
# pool: 内存池
# buf: 包含类型字符串的缓冲区
# start: 类型字符串起始位置
# end: 类型字符串结束位置(不含)
#
# Returns:
# LLVM 类型对象,或 None(无法解析)
# ============================================================
def _ParseLLVMRetTyStr(pool: memhub.MemBuddy | t.CPtr,
buf: bytes,
start: t.CSizeT,
end: t.CSizeT) -> llvmlite.LLVMType | t.CPtr:
"""将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType(委托到 gen._ParseLLVMRetTyStr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._ParseLLVMRetTyStr(pool, buf, start, end)
return None
# ============================================================
# _LookupMethodRetTyFromTextLL - 从依赖模块的 text.ll 查找方法返回类型
#
# 读取 {temp_dir}/{sha1[0:2]}/{sha1}.text.ll(level=1),搜索
# define 行中包含 "{sha1}.{class_name}.{method_name}" 的函数,
# 提取返回类型并转换为 llvmlite.LLVMType。
#
# 解决问题: 旧实现 _infer_method_ret_ty(已移除)默认返回 i32,导致指针返回值
# 被 inttoptr 截断为 32 位(coerce_to_type line 238-239)。
# 本函数从 text.ll 获取实际返回类型,避免截断。
#
# Args:
# pool: 内存池
# class_sha1: 类所属模块的 SHA1
# class_name: 类名
# method_name: 方法名
#
# Returns:
# LLVM 类型对象,或 None(未找到/text.ll 不存在)
# ============================================================
def _LookupMethodRetTyFromTextLL(pool: memhub.MemBuddy | t.CPtr,
class_sha1: str,
class_name: str,
method_name: str,
use_bare: int = 0) -> llvmlite.LLVMType | t.CPtr:
"""从依赖模块的 text.ll 中查找方法返回类型(委托到 gen._LookupMethodRetTyFromTextLL)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._LookupMethodRetTyFromTextLL(pool, class_sha1, class_name, method_name, use_bare)
return None
# ============================================================
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
#
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
# ============================================================
# ============================================================
# _translate_property_call — 翻译属性方法调用
#
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
#
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
# ============================================================
def _translate_property_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
call_head: llvmlite.Value | t.CPtr,
call_count: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译属性/静态方法调用,返回 call 结果 Value(委托到 gen._translate_property_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_property_call(pool, builder, mod, class_name, method_name,
call_head, call_count, trans)
return None
# ============================================================
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
#
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
# 供属性访问/赋值/删除识别 property 时使用。
# ============================================================
def _resolve_obj_class_name(pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr,
obj_node: ast.AST | t.CPtr) -> str:
"""解析对象表达式的类名(短名),失败返回 None(委托到 gen._resolve_obj_class_name)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._resolve_obj_class_name(pool, trans, obj_node)
return None
# ============================================================
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
#
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
# ============================================================
def _try_property_getter_attr(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
at_node: ast.Attribute | t.CPtr,
obj_ptr: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr,
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None(委托到 gen._try_property_getter_attr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._try_property_getter_attr(pool, builder, mod, at_node, obj_ptr,
trans, fallback_class_name)
return None
# ============================================================
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
#
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
# ============================================================
def _try_property_setter(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
rhs_val: llvmlite.Value | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property setter 赋值,返回 1=已处理(生成调用)(委托到 gen._try_property_setter)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._try_property_setter(pool, builder, mod, target_attr, rhs_val, trans)
return 0
# ============================================================
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
#
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
# ============================================================
def _try_property_deleter(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
target_attr: ast.Attribute | t.CPtr,
trans: HT.Translator | t.CPtr) -> int:
"""尝试 property deleter 删除,返回 1=已处理(生成调用)(委托到 gen._try_property_deleter)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._try_property_deleter(pool, builder, mod, target_attr, trans)
return 0
# ============================================================
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
#
# @staticmethod: 直接 call Class.method(args...),无 self
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
# ============================================================
def _translate_static_class_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None(委托到 gen._translate_static_class_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_static_class_call(pool, builder, mod, class_name, method_name, cl, trans)
return None
# ============================================================
# _translate_method_call - 翻译方法调用 obj.method(args)
#
# 生成: call <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %obj, args...)
#
# obj_ptr 是对象变量的 alloca(Ptr(StructTy)),作为 self 参数传入
# ============================================================
def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
method_name: str,
obj_ptr: llvmlite.Value | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译方法调用,返回 call 结果 Value(委托到 gen._translate_method_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_method_call(pool, builder, mod, class_name, method_name,
obj_ptr, cl, trans)
return None
# ============================================================
# _kwarg_name_matches — 检查关键字参数名是否匹配函数参数名
#
# 函数参数名在 LLVM IR 中带 % 前缀(如 "%a"),关键字参数名无前缀(如 "a")
# 跳过 % 前缀后逐字符比较
# ============================================================
def _kwarg_name_matches(kw_arg: str,
param_name: str) -> int:
"""检查关键字参数名 kw_arg 是否匹配参数名 param_name(跳过 % 前缀)(委托到 gen._kwarg_name_matches)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._kwarg_name_matches(kw_arg, param_name)
return 0
# ============================================================
# _translate_struct_ctor_kw — 结构体构造函数(关键字参数)
#
# 支持两种语法:
# Point(x=10, y=20) — 全关键字
# Point(10, y=20) — 混合(位置 + 关键字)
#
# 位置参数按字段索引赋值,关键字参数按字段名查找赋值
# ============================================================
def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr,
class_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
keywords: list[ast.AST | t.CPtr] | t.CPtr,
kw_count: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""结构体构造函数(关键字参数版本)(委托到 gen._translate_struct_ctor_kw)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_struct_ctor_kw(pool, builder, mod, struct_ty, class_name,
cargs, can, keywords, kw_count, trans)
return None
# ============================================================
# _translate_call_with_kwargs — 带关键字参数的函数调用
#
# 支持两种语法:
# add(b=4, a=3) — 全关键字乱序
# greet("Hello", name="World") — 位置 + 关键字混合
#
# 策略: 遍历 found_func.Params 链表,对每个参数:
# 1. 若位置参数仍有剩余(param_idx < can),取位置参数
# 2. 否则按参数名匹配关键字参数
# 3. 按参数顺序构建调用参数链表
# ============================================================
def _translate_call_with_kwargs(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
func_name: str,
found_func: llvmlite.Function | t.CPtr,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
keywords: list[ast.AST | t.CPtr] | t.CPtr,
kw_count: t.CSizeT,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""带关键字参数的函数调用,按参数顺序构建调用链表(委托到 gen._translate_call_with_kwargs)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_call_with_kwargs(pool, builder, mod, func_name, found_func,
cargs, can, keywords, kw_count, trans)
return None
# ============================================================
# _translate_t_type_cast - 翻译 t.XXX(value) 类型转换
#
# 当 func 是 t.XXX 形式且 XXX 是已知类型名(map_t_type 能映射)时,
# 将 value 转换为目标类型:
# - 指针 → 整数: ptrtoint(如 t.CUInt64T(ptr) → i64)
# - 整数 → 指针: inttoptr(如 t.CPtr(int_val) → i8*)
# - 整数 → 整数: trunc/zext(如 t.CInt8T(i32_val) → i8)
# - 指针 → 指针: bitcast(如 t.CPtr(ptr_val) → i8*)
# - 整数 → 浮点: sitofp(如 t.CDouble(i32_val) → double)
# - 浮点 → 整数: fptosi(如 t.CInt(double_val) → i32)
# - 浮点 → 浮点: fpext/fptrunc(如 t.CFloat(double_val) → float)
# ============================================================
def _translate_t_type_cast(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
val: llvmlite.Value | t.CPtr,
target_ty: llvmlite.LLVMType | t.CPtr,
target_name: str = None,
src_node: ast.AST | t.CPtr = None,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""类型转换:根据参数类型和目标类型选择转换方式(委托到 gen._translate_t_type_cast)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_t_type_cast(pool, builder, val, target_ty,
target_name, src_node, trans)
return None
# ============================================================
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
# ============================================================
# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute)
# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用
def _extract_type_args_from_slice(pool: memhub.MemBuddy | t.CPtr,
slice_node: ast.AST | t.CPtr) -> list[str] | t.CPtr:
"""从 Subscript.slice 提取类型实参名列表(委托到 gen._extract_type_args_from_slice)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._extract_type_args_from_slice(pool, slice_node)
return None
# ============================================================
# 泛型类构造调用辅助: list[str](pool, 8) → __new__ + __before_init__ + __init__
#
# 复用 translate_list_literal 的构造逻辑:
# 1. alloca tmp(特化类临时空间,作为 __new__ 的 self)
# 2. 翻译 cl.args 为参数指针数组
# 3. call __new__(tmp, *args) → storage_ptr
# 4. call __before_init__(storage_ptr)
# 5. call __init__(storage_ptr, *args)
# 6. return storage_ptr
#
# 必须独立于 translate_call 的普通函数路径:spec_name 是类名不是函数名,
# 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1
# 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。
# ============================================================
def _infer_generic_ctor_type_arg(pool: memhub.MemBuddy | t.CPtr,
arg_node: ast.AST | t.CPtr,
class_name: str) -> str:
"""从构造实参 AST 推断泛型类型实参名;无法推断时默认 "int"(与 TPC 一致)(委托到 gen._infer_generic_ctor_type_arg)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._infer_generic_ctor_type_arg(pool, arg_node, class_name)
return "int"
def _translate_generic_ctor_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
spec_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__(委托到 gen._translate_generic_ctor_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_generic_ctor_call(pool, builder, mod, spec_name, cl, trans)
return None
-291
View File
@@ -1,291 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.ExprCallHandle as ExprCallHandle
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallDeref - HandlesExprCall 拆分(阶段 E):ExprCallDeref
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# c.Deref(ptr) — 解引用指针,按指针 pointee 类型读取
#
# 生成: %N = load <pointee_ty>, <pointee_ty>* %ptr
# 返回 pointee 类型的值
#
# 注意: 必须按 ptr 的 pointee 类型决定读取宽度。
# - i8* (str/bytes/字符遍历) → load i8
# - i64* (t.CUInt64T, 块头部) → load i64(memhub 的 free list 链表读 8 字节头部)
# 之前固定 load i8 导致 memhub 读块头部只读到低 8 位,
# free list 的 next 指针被截断成 0x88 等垃圾值,alloc 崩溃。
# ============================================================
def translate_c_deref(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Deref(ptr) → load 按 ptr 的 pointee 类型(委托到 gen.translate_c_deref)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_deref(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.DerefAs(ptr, val) — 解引用写入,*ptr = val
#
# 生成: %pc = bitcast i8* %ptr to <val_ty>*
# store <val_ty> %val, <val_ty>* %pc
# ============================================================
def translate_c_derefas(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store)(委托到 gen.translate_c_derefas)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_derefas(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.Set(a, b) — 赋值语义 a = b(与 c.DerefAs 的指针语义不同)
#
# c.DerefAs(ptr, val) 是 *ptr = val(指针解引用写);
# c.Set(a, b) 是 a = b(a 为左值),a 支持三种形态:
# 1. c.Deref(ptr) → *ptr = b(zlib/vipermath 的 c.Set(c.Deref(p), v) 用法)
# 2. Name 变量 → 变量赋值(含 global/nonlocal/局部)
# 3. Attribute → 字段赋值(GEP + store)
# ============================================================
def translate_c_set(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Set(a, b) → a = b(赋值语义,a 为左值)(委托到 gen.translate_c_set)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_set(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.Addr(var) — 取变量地址,返回 alloca 指针(不 load)
#
# 用于获取栈变量的可写地址,配合 c.DerefAs 使用
# ============================================================
def translate_c_addr(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Addr(var) → 返回变量的 alloca 指针(不 load)(委托到 gen.translate_c_addr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_addr(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.Load(a, b) — 指针间复制: *a = *b
#
# 加载 b 指向的值,存储到 a 指向的地址。
# 生成: %pc_src = bitcast i8* %src to <ty>*
# %loaded = load <ty>, <ty>* %pc_src
# %pc_dst = bitcast i8* %dst to <ty>*
# store <ty> %loaded, <ty>* %pc_dst
# ============================================================
def translate_c_load(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Load(a, b) → *a = *b(加载 b 的值,存储到 a)(委托到 gen.translate_c_load)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_load(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.Asm — 内联汇编支持
#
# 生成: %N = call <ret_ty> asm sideeffect "<asm>", "<constraints>"(<args>)
# 或: call void asm sideeffect "<asm>", "<constraints>"(<args>)
#
# 操作数按出现顺序编号 $0, $1, ...(用户需按输出在前写 f-string)
# ============================================================
ASM_MAX_OPERANDS: t.CDefine = 16
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
ASM_CONST_BUF_SIZE: t.CDefine = 512
ASM_ARGS_BUF_SIZE: t.CDefine = 512
ASM_LINE_BUF_SIZE: t.CDefine = 4096
# ============================================================
# _asm_append_cstr — 将 C 字符串 src 追加到 dst 末尾
# ============================================================
def _asm_append_cstr(dst: str, dst_size: t.CSizeT,
src: str):
"""将 C 字符串 src 追加到 dst 末尾(委托到 gen._asm_append_cstr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
g._asm_append_cstr(dst, dst_size, src)
# ============================================================
# _asm_escape_for_ir — 将汇编文本转义为 LLVM IR 字符串内容
#
# \n → \0A, " → \22, \ → \5C
# ============================================================
def _asm_escape_for_ir(pool: memhub.MemBuddy | t.CPtr,
src: str) -> str:
"""转义汇编文本用于 LLVM IR 字符串字面量(委托到 gen._asm_escape_for_ir)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._asm_escape_for_ir(pool, src)
return None
# ============================================================
# _resolve_register — 将 ASM_DESCR 属性名映射到约束字符串
# ============================================================
def _resolve_register(attr_name: str) -> str:
"""将 t.ASM_DESCR.XXX 的属性名映射到约束字符串值(委托到 gen._resolve_register)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._resolve_register(attr_name)
return ""
# ============================================================
# _resolve_asm_descr — 递归解析约束表达式
#
# 支持:
# t.ASM_DESCR.XXX → _resolve_register(XXX)
# expr | expr(BinOp BitOr) → 拼接
# "string" (Constant) → 直接返回
# ============================================================
def _resolve_asm_descr(pool: memhub.MemBuddy | t.CPtr,
node: ast.AST | t.CPtr) -> str:
"""递归解析约束表达式,返回约束字符串(委托到 gen._resolve_asm_descr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._resolve_asm_descr(pool, node)
return ""
# ============================================================
# _asm_get_operand — 获取操作数数组中第 idx 个元素的指针
# ============================================================
def _asm_get_operand(base: HandlesExprCall.AsmOperand | t.CPtr,
idx: int) -> HandlesExprCall.AsmOperand | t.CPtr:
"""获取操作数数组中第 idx 个元素的指针(委托到 gen._asm_get_operand)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._asm_get_operand(base, idx)
return None
# ============================================================
# _asm_is_c_call — 检查 Call 节点是否是 c.XXX 调用
#
# 返回 attr_name(如 "AsmInp"/"AsmOut"),不是则返回 None
# ============================================================
def _asm_is_c_call(node: ast.Call | t.CPtr) -> str:
"""检查 Call 节点是否是 c.XXX 调用,返回属性名或 None(委托到 gen._asm_is_c_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._asm_is_c_call(node)
return None
# ============================================================
# _asm_add_operand — 添加操作数到数组
#
# 返回 1 成功, 0 失败(数组已满)
# ============================================================
def _asm_add_operand(operands: HandlesExprCall.AsmOperand | t.CPtr,
count: int,
val: llvmlite.Value | t.CPtr,
constraint: str,
is_output: int) -> int:
"""添加操作数到数组,返回新计数(失败返回原计数)(委托到 gen._asm_add_operand)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._asm_add_operand(operands, count, val, constraint, is_output)
return 0
# ============================================================
# translate_c_asm — 翻译 c.Asm 内联汇编
#
# 语法:
# c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY])
# c.Asm(f"mov rax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)}", op=[...])
# c.Asm(f"...", out=[c.AsmOut(var, t.ASM_DESCR.OUTPUT_REG)], op=[...])
# ============================================================
def translate_c_asm(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译 c.Asm 内联汇编,返回结果 Value(委托到 gen.translate_c_asm)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_asm(pool, builder, mod, cl, trans)
return None
# ============================================================
# c.LLVMIR — 内联 LLVM IR(无返回值,直接嵌入原始 IR 文本)
#
# 语法:
# c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}")
# c.LLVMIR(f"{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}")
#
# c.LInp(expr) - 输入操作数,替换为 expr 的 LLVM 值引用文本(SSA 名 "%x" 或常量 "42")
# c.LOut(expr) - 输出操作数:为 expr 变量分配唯一 SSA 寄存器 %llvmirN,
# 模板嵌入后自动追加 store <ty> %llvmirN, <ty>* %expr 写回变量
#
# 语义(2026-08-08 用户决策):不做指令解析,模板文本直接嵌入当前基本块,
# 返回 None(无返回值)。ret_ty 第二参数已废弃(兼容忽略)。
# ============================================================
LLVMIR_MAX_OPS: t.CDefine = 16
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
# 注:LOut 唯一 SSA 寄存器名计数器已迁入 gen 字段(CallGenMixin.LLVMIRRegSeq),
# 本模块不再持有(P4 簇 1+2)。
# ============================================================
# translate_c_llvmir — 翻译 c.LLVMIR 内联 LLVM IR
# ============================================================
def translate_c_llvmir(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.LLVMIR 内联 LLVM IR:无返回值,直接嵌入原始 IR 文本(委托到 gen.translate_c_llvmir)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.translate_c_llvmir(pool, builder, mod, cl, trans)
return None
-287
View File
@@ -1,287 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallDeref as ExprCallDeref
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallTable as ExprCallTable
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallHandle - HandlesExprCall 拆分(阶段 E):ExprCallHandle
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# NewExprCallHandle - 工厂函数
# ============================================================
def NewExprCallHandle(pool: memhub.MemBuddy | t.CPtr,
trans: HT.Translator | t.CPtr) -> HandlesExprCall.ExprCallHandle | t.CPtr:
"""新建 HandlesExprCall.ExprCallHandle 工厂(委托到 gen.NewExprCallHandle)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.NewExprCallHandle(pool, trans)
return None
# ============================================================
# _make_vtable_ref_i8 / _emit_eh_guarded_call / _translate_isinstance
# (追加91:CallGenMixin 拆分后顶层经委托调用 CallGenLeafKit 方法——
# TPV self 调用仅支持 1 级父类,跨 Mixin 统一走 HandlesExprCall._g_gen 委托)
# ============================================================
def _make_vtable_ref_i8(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
class_name: str,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""构造类 vtable 地址引用(i8*)(委托到 gen._make_vtable_ref_i8)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._make_vtable_ref_i8(pool, builder, mod, class_name, trans)
return None
def _emit_eh_guarded_call(builder: llvmlite.IRBuilder | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
trans: HT.Translator | t.CPtr,
func: llvmlite.Function | t.CPtr,
call_name: str,
head: llvmlite.Value | t.CPtr,
count: int,
ret_ty: llvmlite.LLVMType | t.CPtr,
is_variadic: int) -> llvmlite.Value | t.CPtr:
"""带 try-except EH 检测的函数调用(委托到 gen._emit_eh_guarded_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._emit_eh_guarded_call(builder, pool, mod, trans, func, call_name, head, count, ret_ty, is_variadic)
return None
def _translate_isinstance(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
obj_node: ast.AST | t.CPtr,
cls_node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译 isinstance()(委托到 gen._translate_isinstance)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_isinstance(pool, builder, mod, obj_node, cls_node, trans)
return None
# ============================================================
# _is_sha1_mangled_call / _is_list_builtin_method / _translate_fakeduck_call /
# _translate_super_call(阶段 B:CallGenMixin 拆分后顶层经委托调用这些方法)
# ============================================================
def _is_sha1_mangled_call(call_name: str) -> int:
"""判断 call_name 是否为跨模块 Viper 函数(委托到 gen._is_sha1_mangled_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._is_sha1_mangled_call(call_name)
return 0
def _is_list_builtin_method(class_name: str, method_name: str) -> int:
"""判断(class_name, method_name) 是否是 list 泛型内置方法(委托到 gen._is_list_builtin_method)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._is_list_builtin_method(class_name, method_name)
return 0
def _translate_fakeduck_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cls_name: str,
method_name: str,
cl: ast.Call | t.CPtr,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""FakeDuck: str 变量方法调用(委托到 gen._translate_fakeduck_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_fakeduck_call(pool, builder, mod, cls_name, method_name, cl, trans)
return None
def _translate_super_call(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
method_name: str,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""super().method(args) → 父类方法静态调用(委托到 gen._translate_super_call)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._translate_super_call(pool, builder, mod, cl, method_name, trans)
return None
# ============================================================
# translate_call 前置检测 helper(阶段 C:CallGenMixin 拆分后顶层经委托
# 调用 CallGenDispatch 方法。每个返回 Value|CPtr,None = 未命中继续主路径)
# ============================================================
def _tc_h1_super_ctraits(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""super()/ctraits 编译期检测(委托到 gen._tc_h1_super_ctraits)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h1_super_ctraits(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
return None
def _tc_h2_c_special(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""c.Deref/Asm/LLVMIR 等特殊调用(委托到 gen._tc_h2_c_special)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h2_c_special(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
return None
def _tc_h3_stdarg_cast(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
"""stdarg 糖 + str/int/bool 内置强转(委托到 gen._tc_h3_stdarg_cast)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h3_stdarg_cast(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
return None
def _tc_h4_type_casts(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
"""t.XXX / typedef 类型转换(委托到 gen._tc_h4_type_casts)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h4_type_casts(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
return None
def _tc_h5_sizeof_len_isinst(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT) -> llvmlite.Value | t.CPtr:
"""__sizeof__/len/isinstance 内置(委托到 gen._tc_h5_sizeof_len_isinst)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h5_sizeof_len_isinst(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can)
return None
def _tc_h6_method_dispatch(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
cl: ast.Call | t.CPtr,
funcs_ptr: t.CPtr,
func_count: int,
trans: HT.Translator | t.CPtr,
func_name: str,
cargs: list[ast.AST | t.CPtr] | t.CPtr,
can: t.CSizeT,
hit_box: t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""静态类/方法调用/表达式接收者/self.field/list 内置(委托到 gen._tc_h6_method_dispatch)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._tc_h6_method_dispatch(pool, builder, mod, cl, funcs_ptr, func_count, trans, func_name, cargs, can, hit_box)
return None
# ============================================================
# FuncGen 跨 Mixin 委托(阶段 D:FuncGenMixin 拆 Base/Def 后顶层经
# 此调用这些方法。参数与目标方法一致,去 self)
# ============================================================
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
imported_modules: str) -> str:
"""从 decorator_list 提取 c.Attribute 属性(委托到 gen.extract_func_attrs)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.extract_func_attrs(pool, decorator_list, imported_modules)
return None
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
"""为任意名称添加 SHA1 前缀(委托到 gen._mangle_name)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._mangle_name(trans, name)
return name
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
has_export: int) -> str:
"""为函数名添加 SHA1 前缀(委托到 gen._mangle_func_name)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._mangle_func_name(trans, name, has_export)
return name
def _body_has_raise(fd: ast.FunctionDef | t.CPtr) -> int:
"""函数体顶层是否含 raise(委托到 gen._body_has_raise)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._body_has_raise(fd)
return 0
def _prepare_chain_nonlocals(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
i8_ty: llvmlite.LLVMType | t.CPtr,
i8_ptr_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""准备嵌套函数 nonlocals 链(委托到 gen._prepare_chain_nonlocals)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._prepare_chain_nonlocals(trans, node, pool, builder, mod, i8_ty, i8_ptr_ty)
return 0
+197 -206
View File
@@ -1,206 +1,197 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallDeref as ExprCallDeref
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallHandle as ExprCallHandle
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallTable - HandlesExprCall 拆分(阶段 E):ExprCallTable
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# 初始化函数表
# ============================================================
def init_func_table(pool: memhub.MemBuddy | t.CPtr,
max_count: int) -> HandlesExprCall.FuncEntry | t.CPtr:
"""分配并清零函数表数组(委托到 gen.init_func_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.init_func_table(pool, max_count)
return None
# ============================================================
# 查找函数
# ============================================================
def find_func_in_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
func_count: int,
name: str) -> llvmlite.Function | t.CPtr:
"""在函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_in_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.find_func_in_table(funcs, func_count, name)
return None
# ============================================================
# 添加函数到函数表
# ============================================================
def add_func_to_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
func_count: int,
name: str,
func: llvmlite.Function | t.CPtr,
max_count: int,
defaults: t.CVoid | t.CPtr = None,
default_count: int = 0,
param_count: int = 0,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""添加函数到函数表,返回 0 成功(委托到 gen.add_func_to_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.add_func_to_table(funcs, func_count, name, func, max_count,
defaults, default_count, param_count, pool)
return 0
# ============================================================
# 全局函数注册表(跨模块函数查找)
#
# 所有模块翻译的函数都会注册到此表(通过 add_func_to_table 自动注册)。
# 主要用途: vtable 初始化时查找跨模块继承方法的 Function 对象,
# 以获取函数类型信息构造 bitcast 字符串。
# ============================================================
GLOBAL_FUNC_MAX: t.CDefine = 8192
def _init_global_func_table() -> int:
"""初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)(委托到 gen._init_global_func_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._init_global_func_table()
return 0
# _build_func_type_str — 从 Function 对象生成函数类型文本(stdlib 存储)
#
# 格式: ret_ty(param1_ty, param2_ty, ...),与 vtable bitcast 需要一致。
# 用 stdlib.malloc 分配返回,跨文件永久存活(1b reset 不回收)。
# 返回 None 表示失败。
def _build_func_type_str(pool: memhub.MemBuddy | t.CPtr,
func: llvmlite.Function | t.CPtr) -> str:
"""生成函数类型文本(stdlib 分配)(委托到 gen._build_func_type_str)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._build_func_type_str(pool, func)
return None
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""注册函数到全局表(已存在则跳过),返回 0 成功(委托到 gen._register_global_func)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._register_global_func(name, func, pool)
return 0
def update_global_func_typestr(pool: memhub.MemBuddy | t.CPtr,
name: str,
func: llvmlite.Function | t.CPtr) -> int:
"""更新全局函数表的 TypeStr(在函数参数全部添加完成后调用)(委托到 gen.update_global_func_typestr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.update_global_func_typestr(pool, name, func)
return 0
def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
"""在全局函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_global)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.find_func_global(name)
return None
def find_func_entry_global(name: str) -> HandlesExprCall.FuncEntry | t.CPtr:
"""在全局函数表中按名称查找,返回完整 HandlesExprCall.FuncEntry(含 TypeStr)或 None(委托到 gen.find_func_entry_global)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.find_func_entry_global(name)
return None
# ============================================================
# 全局默认参数注册表(跨模块默认参数填充)
#
# 独立于 _global_funcs,因为 _register_global_func 可能在
# add_func_to_table 之前被调用(如 stub 注入),此时 defaults 还不可用。
# ============================================================
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
def _init_global_defaults_table() -> int:
"""初始化全局默认参数表(委托到 gen._init_global_defaults_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._init_global_defaults_table()
return 0
def _register_global_defaults(name: str,
defaults: t.CVoid | t.CPtr,
default_count: int,
param_count: int) -> int:
"""注册函数默认参数到全局表,返回 0 成功(委托到 gen._register_global_defaults)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._register_global_defaults(name, defaults, default_count, param_count)
return 0
def find_func_defaults(name: str) -> HandlesExprCall.FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 HandlesExprCall.FuncDefaultsEntry 或 None(委托到 gen.find_func_defaults)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.find_func_defaults(name)
return None
# _build_const_from_snapshot — 从常量快照重建常量 IR 值
#
# 用于跨模块默认参数填充:gd_entry.Defaults(pool 内 AST)可能已被 reset 回收,
# 改用注册时提取的 stdlib 常量快照(ConstKinds/ConstInts/ConstStrs)重建常量 IR。
# 返回 llvmlite.Value*,失败返回 None。
def _build_const_from_snapshot(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
gd_entry: HandlesExprCall.FuncDefaultsEntry | t.CPtr,
di: int,
trans: HT.Translator | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr) -> llvmlite.Value | t.CPtr:
"""从快照重建第 di 个默认值常量 IR(委托到 gen._build_const_from_snapshot)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g._build_const_from_snapshot(pool, mod, gd_entry, di, trans, builder)
return None
def find_func_entry_in_table(funcs: HandlesExprCall.FuncEntry | t.CPtr,
func_count: int,
name: str) -> HandlesExprCall.FuncEntry | t.CPtr:
"""在函数表中按名称查找,返回完整 HandlesExprCall.FuncEntry 或 None"""
if name is None or funcs is None:
return None
entry_size: t.CSizeT = HandlesExprCall.FuncEntry.__sizeof__()
i: int = 0
while i < func_count:
entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size
entry: HandlesExprCall.FuncEntry | t.CPtr = (HandlesExprCall.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0:
return entry
i += 1
return None
import lib.core.Gen.GenTypes as GenTypes
import lib.core.Gen.CallGenLeafKit as CallGenLeafKit
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Handles.HandlesExprCall as HandlesExprCall
# ============================================================
# ExprCallTable - HandlesExprCall 拆分(阶段 E):ExprCallTable
#
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
# ============================================================
# ============================================================
# 初始化函数表
# ============================================================
def init_func_table(pool: memhub.MemBuddy | t.CPtr,
max_count: int) -> GenTypes.FuncEntry | t.CPtr:
"""分配并清零函数表数组(委托到 gen.init_func_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.init_func_table(pool, max_count)
return None
# ============================================================
# 查找函数
# ============================================================
def find_func_in_table(funcs: GenTypes.FuncEntry | t.CPtr,
func_count: int,
name: str) -> llvmlite.Function | t.CPtr:
"""在函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_in_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.find_func_in_table(funcs, func_count, name)
return None
# ============================================================
# 添加函数到函数表
# ============================================================
def add_func_to_table(funcs: GenTypes.FuncEntry | t.CPtr,
func_count: int,
name: str,
func: llvmlite.Function | t.CPtr,
max_count: int,
defaults: t.CVoid | t.CPtr = None,
default_count: int = 0,
param_count: int = 0,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""添加函数到函数表,返回 0 成功(委托到 gen.add_func_to_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.add_func_to_table(funcs, func_count, name, func, max_count,
defaults, default_count, param_count, pool)
return 0
# ============================================================
# 全局函数注册表(跨模块函数查找)
#
# 所有模块翻译的函数都会注册到此表(通过 add_func_to_table 自动注册)。
# 主要用途: vtable 初始化时查找跨模块继承方法的 Function 对象,
# 以获取函数类型信息构造 bitcast 字符串。
# ============================================================
GLOBAL_FUNC_MAX: t.CDefine = 8192
def _init_global_func_table() -> int:
"""初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)(委托到 gen._init_global_func_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._init_global_func_table()
return 0
# _build_func_type_str — 从 Function 对象生成函数类型文本(stdlib 存储)
#
# 格式: ret_ty(param1_ty, param2_ty, ...),与 vtable bitcast 需要一致。
# 用 stdlib.malloc 分配返回,跨文件永久存活(1b reset 不回收)。
# 返回 None 表示失败。
def _build_func_type_str(pool: memhub.MemBuddy | t.CPtr,
func: llvmlite.Function | t.CPtr) -> str:
"""生成函数类型文本(stdlib 分配)(委托到 gen._build_func_type_str)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._build_func_type_str(pool, func)
return None
def _register_global_func(name: str, func: llvmlite.Function | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None) -> int:
"""注册函数到全局表(已存在则跳过),返回 0 成功(委托到 gen._register_global_func)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._register_global_func(name, func, pool)
return 0
def update_global_func_typestr(pool: memhub.MemBuddy | t.CPtr,
name: str,
func: llvmlite.Function | t.CPtr) -> int:
"""更新全局函数表的 TypeStr(在函数参数全部添加完成后调用)(委托到 gen.update_global_func_typestr)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.update_global_func_typestr(pool, name, func)
return 0
def find_func_global(name: str) -> llvmlite.Function | t.CPtr:
"""在全局函数表中按名称查找,返回 Function 指针或 None(委托到 gen.find_func_global)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.find_func_global(name)
return None
def find_func_entry_global(name: str) -> GenTypes.FuncEntry | t.CPtr:
"""在全局函数表中按名称查找,返回完整 GenTypes.FuncEntry(含 TypeStr)或 None(委托到 gen.find_func_entry_global)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.find_func_entry_global(name)
return None
# ============================================================
# 全局默认参数注册表(跨模块默认参数填充)
#
# 独立于 _global_funcs,因为 _register_global_func 可能在
# add_func_to_table 之前被调用(如 stub 注入),此时 defaults 还不可用。
# ============================================================
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
def _init_global_defaults_table() -> int:
"""初始化全局默认参数表(委托到 gen._init_global_defaults_table)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._init_global_defaults_table()
return 0
def _register_global_defaults(name: str,
defaults: t.CVoid | t.CPtr,
default_count: int,
param_count: int) -> int:
"""注册函数默认参数到全局表,返回 0 成功(委托到 gen._register_global_defaults)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._register_global_defaults(name, defaults, default_count, param_count)
return 0
def find_func_defaults(name: str) -> GenTypes.FuncDefaultsEntry | t.CPtr:
"""按函数名查找默认参数信息,返回 GenTypes.FuncDefaultsEntry 或 None(委托到 gen.find_func_defaults)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit.find_func_defaults(name)
return None
# _build_const_from_snapshot — 从常量快照重建常量 IR 值
#
# 用于跨模块默认参数填充:gd_entry.Defaults(pool 内 AST)可能已被 reset 回收,
# 改用注册时提取的 stdlib 常量快照(ConstKinds/ConstInts/ConstStrs)重建常量 IR。
# 返回 llvmlite.Value*,失败返回 None。
def _build_const_from_snapshot(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
gd_entry: GenTypes.FuncDefaultsEntry | t.CPtr,
di: int,
trans: HT.Translator | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr) -> llvmlite.Value | t.CPtr:
"""从快照重建第 di 个默认值常量 IR(委托到 gen._build_const_from_snapshot)"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
if g is not None:
return g.CallGenLeafKit._build_const_from_snapshot(pool, mod, gd_entry, di, trans, builder)
return None
def find_func_entry_in_table(funcs: GenTypes.FuncEntry | t.CPtr,
func_count: int,
name: str) -> GenTypes.FuncEntry | t.CPtr:
"""在函数表中按名称查找,返回完整 GenTypes.FuncEntry 或 None"""
if name is None or funcs is None:
return None
entry_size: t.CSizeT = GenTypes.FuncEntry.__sizeof__()
i: int = 0
while i < func_count:
entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size
entry: GenTypes.FuncEntry | t.CPtr = (GenTypes.FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry.Name is not None:
if string.strcmp(entry.Name, name) == 0:
return entry
i += 1
return None
-18
View File
@@ -1,18 +0,0 @@
import t, c
from stdint import *
import lib.core.Gen.Generator as Generator
# ============================================================
# ForHandleBase - HandlesFor 拆分(迁移完成,仅保留 _g_gen 单例)
#
# P6 机械化迁移:ForHandleBase 全部方法(_extract_tuple_names/
# _seq_kind/_build_seq_loop)→ StmtGenCifMixin 方法。
# main/BuildPipeline 仍注入 _g_gen,不可删。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
-20
View File
@@ -1,20 +0,0 @@
import t, c
from stdint import *
import lib.core.Gen.Generator as Generator
# ============================================================
# ForHandleIter - HandlesFor 拆分(迁移完成,仅保留 _g_gen 单例)
#
# P6 机械化迁移:ForHandleIter 全部方法(_handle_ptr_iter/
# _handle_array_iter/_handle_list_literal_iter/_handle_list_iter/
# _handle_dict_iter/_handle_oop_iter/_handle_enumerate_iter/
# _handle_zip_iter)→ StmtGenCifMixin 方法。
# main/BuildPipeline 仍注入 _g_gen,不可删。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
-234
View File
@@ -1,234 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import w32.fileio as fileio
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.VLogger as VLogger
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesAnnAssign - AnnAssign 语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:AnnAssignHandle 类 → AssignGenMixin.translate_annassign /
# translate_annassign_prescan。分派中枢(StmtGenMixin/StmtGenDeclMixin)经
# 本壳跨链调用(Viper @t.NoVTable 静态绑定下跨 Mixin self. 调用 mangle
# 失败,须经模块级委托壳桥回 gen 单例)。迁移收尾后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数)
#
# 支持两种形式:
# 1. Attribute(Name('t'), 'CDefine')
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
# ============================================================
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否(委托到 gen.is_cdefine_annotation)"""
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
def is_ctypedef_annotation(annot: ast.AST | t.CPtr) -> int:
"""检测注解是否为 t.CTypedef,返回 1 表示是,0 表示否(委托到 gen._is_ctypedef_annotation)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._is_ctypedef_annotation(annot)
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(val_node: ast.AST | t.CPtr) -> t.CInt64T:
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp,委托到 gen.extract_cdefine_int_value)"""
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
# ============================================================
# _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(pool: memhub.MemBuddy | t.CPtr,
name: str, val_node: ast.AST | t.CPtr) -> None:
"""注册 CDefine 常量(浮点字面量 → register_cdefine_double,否则整数,委托到 gen._register_cdefine_from_value)"""
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)
# ============================================================
# 源文件重读恢复 CDefine 浮点值
#
# 背景:AST 节点的 float_val/str_val 字段可能被 pool 分配操作覆写
# (MemBuddy 内存冲突),导致注册的浮点 CDefine 值错误(llc ret i32 0)。
# 本函数直接读源文件找 "NAME: t.CDefine = value" 行,atof 解析 value——
# 源文件文本不受 pool 影响,是最可靠的恢复路径。
# 原模块级 _g_recover_found 全局已迁移为 gen 字段(RecoverFound)。
# ============================================================
def _recover_found() -> int:
"""检查最近一次 _recover_cdefine_float 是否成功(委托到 gen._recover_found)"""
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)
"""
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
# ============================================================
# _annotation_contains_name - 递归检查注解中是否包含指定名称
#
# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。
# ============================================================
def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int:
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含(委托到 gen._annotation_contains_name)"""
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
# ============================================================
# _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(annot: ast.AST | t.CPtr) -> int:
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式(委托到 gen._is_ptr_element_annotation)"""
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
# ============================================================
# _infer_static_array_ty_from_literal - 单参 CArray + 列表字面量 → 静态数组
#
# 单参 t.CArray[elem_ty] 解析为 Ptr(elem_ty),但当 RHS 是列表字面量时,
# 按 TPC 语义应推断为 [len x elem_ty](对齐 TPC ParseListAnnotation):
# 避免误走动态 list 构造(_find_pool_var 兜底引用外部 @_mbuddy → 链接期
# undefined)。PreScan 与 Handle 都调用(PreScan 预创建 alloca 的类型必须
# 与 Handle 一致,否则 get_or_create_sym 复用旧 alloca 使推断失效)。
# 真实实现已迁移至 gen._infer_static_array_ty_from_literal,本壳保留供
# ClassGenDef(Gen 侧字段类型推断)等跨模块调用方使用。
# ============================================================
def _infer_static_array_ty_from_literal(pool: memhub.MemBuddy | t.CPtr,
annot: ast.AST | t.CPtr,
value: ast.AST | t.CPtr,
resolved_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""单参 CArray + 列表字面量 → Array(elem_ty, len);否则返回原类型(委托到 gen._infer_static_array_ty_from_literal)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._infer_static_array_ty_from_literal(pool, annot, value, resolved_ty)
return resolved_ty
# ============================================================
# _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(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(委托到 gen._init_global_array_from_list)"""
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
# ============================================================
# translate_annassign - AnnAssign 语句翻译(委托到 gen.translate_annassign)
# ============================================================
def translate_annassign(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 AnnAssign 语句,返回新增变量数(委托到 gen.translate_annassign)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_annassign(trans, node)
return 0
# ============================================================
# translate_annassign_prescan - AnnAssign 预扫描(委托到 gen.translate_annassign_prescan)
# ============================================================
def translate_annassign_prescan(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部(委托到 gen.translate_annassign_prescan)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_annassign_prescan(trans, node)
return 0
-51
View File
@@ -1,51 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import viperlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.StubMerger as StubMerger
import lib.core.StubMergerStore as StubMergerStore
import lib.core.Handles.ExprCallBase as ExprCallBase
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesAssign - Assign 语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:AssignHandle 类 → AssignGenMixin.translate_assign
# (lib.core.Gen.AssignGenMixin)。分派中枢(StmtGenMixin)经本壳跨链
# 调用(Viper @t.NoVTable 静态绑定下跨 Mixin self. 调用 mangle 失败,
# 须经模块级委托壳桥回 gen 单例)。迁移收尾后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_assign - Assign 语句翻译(委托到 gen.translate_assign)
# ============================================================
def translate_assign(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译赋值语句,返回新增变量数(委托到 gen.translate_assign)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_assign(trans, node)
return 0
-34
View File
@@ -1,34 +0,0 @@
import t, c
from stdint import *
import ast
import memhub
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesAugAssign - 增强赋值语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:AugAssignHandle 类 → AssignGenMixin.translate_augassign。
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_augassign - 增强赋值翻译(委托到 gen.translate_augassign)
# ============================================================
def translate_augassign(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译增强赋值语句,返回新增变量数(委托到 gen.translate_augassign)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_augassign(trans, node)
return 0
-168
View File
@@ -1,168 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import viperlib
import lib.core.Handles.HandlesTranslator as HT
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.HandlesVar as HandlesVar
import lib.core.Gen.Generator as Generator
# ============================================================
# 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 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 语句翻译分派
# ============================================================
def translate_stmt(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译单条语句,返回新增的变量数(委托到 gen.translate_stmt)"""
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
# ============================================================
# 翻译 Delete 语句: del obj.attr
#
# 支持 property deleter: 当目标 attr 是 @x.deleter 方法时,
# 生成 call Class.attr$del(obj)。其余目标暂不生成代码。
# ============================================================
def translate_delete(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 del 语句,返回 0(委托到 gen.translate_delete)"""
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
# ============================================================
# 翻译 Global 语句: global x, y
#
# 将 names 中的变量名加入 _global_names 集合
# ============================================================
def translate_global(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 global 语句:记录 global 变量名(委托到 gen.translate_global)"""
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
# ============================================================
# 翻译 Nonlocal 语句: nonlocal x, y
#
# 将 names 中的变量名加入 _nonlocal_names 集合
# ============================================================
def translate_nonlocal(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 nonlocal 语句:记录 nonlocal 变量名及其类型(委托到 gen.translate_nonlocal)
类型信息通过查找父作用域的 alloca 获取(用于 env 指针数组方案的类型恢复)。
"""
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
# ============================================================
# 翻译表达式语句 Expr(value=Call(...))
# ============================================================
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译表达式语句(printf 调用等)(委托到 gen.translate_expr_stmt)"""
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
# ============================================================
# 预扫描:为局部变量提前创建 alloca
# ============================================================
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""预扫描语句中的 AnnAssign,提前创建 alloca(委托到 gen.pre_scan_allocas)
返回新增的变量数
"""
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
# ============================================================
# 预扫描:Global/Nonlocal 声明(Python 作用域语义)
#
# Python 中 global/nonlocal 声明对整个函数作用域生效,与声明
# 位置无关。必须在翻译任何赋值之前注册 global/nonlocal 名称,
# 否则 global 声明前的赋值会错误创建局部变量遮蔽全局。
# ============================================================
def pre_scan_scope_decls(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""预扫描 Global/Nonlocal 声明,提前注册作用域名称(委托到 gen.pre_scan_scope_decls)"""
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
# ============================================================
# 翻译 break 语句
# ============================================================
def translate_break(trans: HT.Translator | t.CPtr) -> int:
"""翻译 break 语句:跳转到循环 end 块(委托到 gen.translate_break)"""
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
# ============================================================
# 翻译 continue 语句
# ============================================================
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
"""翻译 continue 语句:跳转到循环 cond/incr 块(委托到 gen.translate_continue)"""
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
# ============================================================
# 获取语句类型名(调试用)
# ============================================================
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
"""获取语句类型名(委托到 gen.get_stmt_kind_name)"""
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
File diff suppressed because it is too large. Load diff
-166
View File
@@ -1,166 +0,0 @@
import t, c
from stdint import *
import memhub
import string
import llvmlite
import stdio
import viperlib
import lib.core.VLogger as VLogger
import lib.core.Gen.Generator as Generator
# ============================================================
# 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(值、类型)
#
# 使用全局数组存储,线性查找(枚举数量通常很少)
# ============================================================
ENUM_MAX: t.CDefine = 64
ENUM_MEMBER_MAX: t.CDefine = 128
# ============================================================
# EnumMember - 枚举成员条目
# ============================================================
@t.NoVTable
class EnumMember:
Name: str # 成员名(字符串)
Value: t.CInt64T # 成员的整数值
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
# ============================================================
# EnumEntry - 枚举类型条目
# ============================================================
@t.NoVTable
class EnumEntry:
Name: str # 枚举类名
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
MemberCount: int # 成员数量
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# init_enum_table — 初始化枚举注册表
# ============================================================
def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int:
"""初始化枚举注册表,返回 1 成功(委托到 gen.init_enum_table)"""
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 个枚举条目(委托到 gen._get_enum_entry)"""
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 个成员条目(委托到 gen._get_enum_member)"""
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
# ============================================================
# register_enum — 注册枚举类型
#
# 返回 EnumEntry 指针,可用于添加成员
# ============================================================
def register_enum(pool: memhub.MemBuddy | t.CPtr,
name: str,
base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr:
"""注册枚举类型,返回 EnumEntry 指针(委托到 gen.register_enum)"""
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
# ============================================================
# add_enum_member — 向枚举添加成员
# ============================================================
def add_enum_member(pool: memhub.MemBuddy | t.CPtr,
enum_entry: EnumEntry | t.CPtr,
member_name: str,
member_val: t.CInt64T,
member_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""向枚举添加成员,返回成员索引(-1 失败,委托到 gen.add_enum_member)"""
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(委托到 gen.find_enum)"""
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
# ============================================================
# lookup_enum_member — 按枚举类名和成员名查找
# ============================================================
def lookup_enum_member(enum_name: str,
member_name: str) -> EnumMember | t.CPtr:
"""按枚举类名和成员名查找,返回 EnumMember 或 None(委托到 gen.lookup_enum_member)"""
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
# ============================================================
# is_enum_class — 检查类名是否为已注册枚举
# ============================================================
def is_enum_class(name: str) -> int:
"""检查类名是否为已注册枚举,返回 1=是 / 0=否(委托到 gen.is_enum_class)"""
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
# ============================================================
# get_enum_base_type — 按枚举类名获取基准类型
# ============================================================
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
"""按枚举类名获取基准类型(委托到 gen.get_enum_base_type)"""
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
File diff suppressed because it is too large. Load diff
+137 -143
View File
@@ -1,143 +1,137 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
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.HandlesVar as HandlesVar
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.StubMerger as StubMerger
import lib.core.Handles.ExprCallCall as ExprCallCall
import lib.core.Gen.Generator as Generator
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 本地常量(阶段 E 拆分时随函数块误删,补回;子模块经 HandlesExprCall.常量 引用)
# ============================================================
_CEXPORT_MAX: t.CDefine = 256
ASM_MAX_OPERANDS: t.CDefine = 16
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
ASM_CONST_BUF_SIZE: t.CDefine = 512
ASM_ARGS_BUF_SIZE: t.CDefine = 512
ASM_LINE_BUF_SIZE: t.CDefine = 4096
LLVMIR_MAX_OPS: t.CDefine = 16
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
MAX_CLOSURE_NAMES: t.CDefine = 128
MAX_FUNC_PTR_SIGS: t.CDefine = 64
GLOBAL_FUNC_MAX: t.CDefine = 8192
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
# ============================================================
# AsmOperand - 内联汇编操作数条目
# ============================================================
@t.NoVTable
class AsmOperand:
"""内联汇编操作数条目"""
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
Constraint: str # 约束字符串 (如 "r", "=r")
IsOutput: int # 1=输出, 0=输入
# ============================================================
# FuncEntry 结构体(用于函数表)
# ============================================================
@t.NoVTable
class FuncEntry:
"""函数表条目"""
Name: str
Func: llvmlite.Function | t.CPtr
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量
ParamCount: int # 形参数量(不含 self)
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
TypeStr: str
@t.NoVTable
class FuncDefaultsEntry:
"""默认参数表条目"""
Name: str
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
DefaultCount: int
ParamCount: int # 形参数量(不含 self)
# 常量快照(stdlib 分配,跨文件永久存活):
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
# ============================================================
# ExprCallHandle - 函数调用处理器(Mixin 继承模式)
#
# HandleCall / HandlePrintfCall 提供 trans 接口
# ============================================================
@t.NoVTable
class ExprCallHandle(HandlesBase.Mixin):
"""函数调用处理器:继承 Mixin 获得 Trans 回指针"""
def __init__(self, trans: HT.Translator | t.CPtr):
self.Trans = trans
# ============================================================
# HandleCall - 翻译函数调用,返回 call 结果 Value
# ============================================================
def HandleCall(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译函数调用,从 self.Trans 获取共享状态"""
return ExprCallCall.translate_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
node,
self.Trans._funcs, self.Trans._func_count, self.Trans)
# ============================================================
# HandlePrintfCall - 翻译 printf 调用
# ============================================================
def HandlePrintfCall(self, cl: ast.Call | t.CPtr):
"""翻译 printf 调用,从 self.Trans 获取共享状态"""
ExprCallCall.translate_printf_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
cl, self.Trans)
# ============================================================
# HandlePrintCall - 翻译 print 调用
# ============================================================
def HandlePrintCall(self, cl: ast.Call | t.CPtr):
"""翻译 print 调用(类型感知格式化 + 默认换行)"""
ExprCallCall.translate_print_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
cl, self.Trans)
import lib.core.Gen.GenApi as GenApi
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import stdlib
import sys
import viperlib
import w32.fileio as fileio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as Generator
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 本地常量(阶段 E 拆分时随函数块误删,补回;子模块经 HandlesExprCall.常量 引用)
# ============================================================
_CEXPORT_MAX: t.CDefine = 256
ASM_MAX_OPERANDS: t.CDefine = 16
ASM_TEXT_BUF_SIZE: t.CDefine = 2048
ASM_CONST_BUF_SIZE: t.CDefine = 512
ASM_ARGS_BUF_SIZE: t.CDefine = 512
ASM_LINE_BUF_SIZE: t.CDefine = 4096
LLVMIR_MAX_OPS: t.CDefine = 16
LLVMIR_TEMPLATE_BUF: t.CDefine = 512
MAX_CLOSURE_NAMES: t.CDefine = 128
MAX_FUNC_PTR_SIGS: t.CDefine = 64
GLOBAL_FUNC_MAX: t.CDefine = 8192
GLOBAL_DEFAULTS_MAX: t.CDefine = 4096
# ============================================================
# AsmOperand - 内联汇编操作数条目
# ============================================================
@t.NoVTable
class AsmOperand:
"""内联汇编操作数条目"""
Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca
Constraint: str # 约束字符串 (如 "r", "=r")
IsOutput: int # 1=输出, 0=输入
# ============================================================
# FuncEntry 结构体(用于函数表)
# ============================================================
@t.NoVTable
class FuncEntry:
"""函数表条目"""
Name: str
Func: llvmlite.Function | t.CPtr
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值
DefaultCount: int # 默认值数量
ParamCount: int # 形参数量(不含 self)
# TypeStr: 函数类型文本(stdlib 深拷贝,跨文件安全)
# 1b 每文件 reset_to(mark1) 回收 pool 内 Function 对象后,
# vtable 生成 find_func_global 读类型改用此文本,避免悬空。
TypeStr: str
@t.NoVTable
class FuncDefaultsEntry:
"""默认参数表条目"""
Name: str
Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr])(pool 内,可能被 reset)
DefaultCount: int
ParamCount: int # 形参数量(不含 self)
# 常量快照(stdlib 分配,跨文件永久存活):
# 注册时提取每个默认值 Constant 的值,跨模块调用时优先用快照重建常量 IR,
# 避免读取已被 1b reset_to(mark1) 回收的 pool 内 AST。
ConstKinds: t.CInt | t.CPtr # const_kind 数组(DefaultCount 个 i32)
ConstInts: t.CInt64T | t.CPtr # int_val 数组(DefaultCount 个 i64)
ConstStrs: t.CSizeT | t.CPtr # str_val 指针数组(DefaultCount 个 i8*)
# ============================================================
# ExprCallHandle - 函数调用处理器(Mixin 继承模式)
#
# HandleCall / HandlePrintfCall 提供 trans 接口
# ============================================================
@t.NoVTable
class ExprCallHandle(HandlesBase.Mixin):
"""函数调用处理器:继承 Mixin 获得 Trans 回指针"""
def __init__(self, trans: HT.Translator | t.CPtr):
self.Trans = trans
# ============================================================
# HandleCall - 翻译函数调用,返回 call 结果 Value
# ============================================================
def HandleCall(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr:
"""翻译函数调用,从 self.Trans 获取共享状态"""
return GenApi.translate_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
node,
self.Trans._funcs, self.Trans._func_count, self.Trans)
# ============================================================
# HandlePrintfCall - 翻译 printf 调用
# ============================================================
def HandlePrintfCall(self, cl: ast.Call | t.CPtr):
"""翻译 printf 调用,从 self.Trans 获取共享状态"""
GenApi.translate_printf_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
cl, self.Trans)
# ============================================================
# HandlePrintCall - 翻译 print 调用
# ============================================================
def HandlePrintCall(self, cl: ast.Call | t.CPtr):
"""翻译 print 调用(类型感知格式化 + 默认换行)"""
GenApi.translate_print_call(
self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module,
cl, self.Trans)
-116
View File
@@ -1,116 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesExprOps - 二元运算处理(P3 对象化后的委托层)
#
# 全部函数已迁移为 lib.core.Gen.ExprGenMixin 的方法,本模块保留
# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen
# 的对应方法。签名与旧函数完全一致,调用方零改动。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
# ============================================================
# BinOp 运算符 → dunder 方法名
def _binop_to_dunder(op: int) -> str:
"""将 BinOp 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._binop_to_dunder)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._binop_to_dunder(op)
return None
# Compare 运算符 → dunder 方法名
def _cmpop_to_dunder(op: int) -> str:
"""将 Compare 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._cmpop_to_dunder)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._cmpop_to_dunder(op)
return None
# UnaryOp 运算符 → dunder 方法名
def _unaryop_to_dunder(op: int) -> str:
"""将 UnaryOp 运算符映射到 dunder 方法名,无映射时返回 None(委托到 gen._unaryop_to_dunder)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._unaryop_to_dunder(op)
return None
# ============================================================
# try_operator_overload - 尝试运算符重载
#
# 检查 lhs 是否为结构体指针,并在该类(含继承链)中查找对应的
# dunder 方法。找到则生成方法调用 lhs.__dunder__(rhs),返回
# 调用结果;未找到返回 None,调用方回退到原生运算。
# ============================================================
def try_operator_overload(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
lhs: llvmlite.Value | t.CPtr,
rhs: llvmlite.Value | t.CPtr,
op: int,
trans: HT.Translator | t.CPtr,
is_compare: int) -> llvmlite.Value | t.CPtr:
"""尝试运算符重载:lhs 是结构体指针时调用 dunder 方法,否则返回 None(委托到 gen.try_operator_overload)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.try_operator_overload(pool, builder, mod, lhs, rhs, op, trans, is_compare)
return None
# ============================================================
# try_unary_operator_overload - 尝试一元运算符重载
#
# 检查 operand 是否为结构体指针,并在该类(含继承链)中查找对应的
# dunder 方法(__neg__/__pos__/__invert__)。找到则生成方法调用
# operand.__dunder__(),返回调用结果;未找到返回 None,调用方回退到原生运算。
# ============================================================
def try_unary_operator_overload(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
operand: llvmlite.Value | t.CPtr,
op: int,
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
"""尝试一元运算符重载:operand 是结构体指针时调用 dunder 方法,否则返回 None(委托到 gen.try_unary_operator_overload)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.try_unary_operator_overload(pool, builder, mod, operand, op, trans)
return None
# ============================================================
# 翻译二元运算(自动类型提升)
# ============================================================
def translate_binop(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
node: ast.AST | t.CPtr,
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
"""翻译二元运算(自动类型提升)(委托到 gen.translate_binop)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_binop(pool, builder, mod, node, trans)
return None
-55
View File
@@ -1,55 +0,0 @@
import t, c
from stdint import *
import ast
import memhub
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesFor - for 循环语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:ForHandle/ForHandleBase/ForHandleIter 全部方法 →
# StmtGenCifMixin.translate_for 及辅助方法(_handle_ptr_iter/
# _handle_array_iter/_handle_list_literal_iter/_handle_list_iter/
# _handle_dict_iter/_handle_oop_iter/_handle_enumerate_iter/
# _handle_zip_iter/_extract_tuple_names/_seq_kind/_build_seq_loop)。
# SEQ_KIND_* 常量保留:StmtGenCifMixin._seq_kind/_build_seq_loop 经
# HandlesFor.SEQ_KIND_* 访问。
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 序列迭代源类型码(for x in ... / enumerate / zip 迭代源分类)
# RANGE: range(start, stop, step)
# STR: 字符串(常量或 str 变量)
# LIST: list[T] 容器(按 __count__ + __data__ 迭代)
# ============================================================
SEQ_KIND_RANGE: t.CDefine = 1
SEQ_KIND_STR: t.CDefine = 2
SEQ_KIND_LIST: t.CDefine = 3
# ============================================================
# translate_for - for 循环语句翻译(委托到 gen.translate_for)
# ============================================================
def translate_for(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 for 循环语句(委托到 gen.translate_for)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_for(trans, node)
return 0
-143
View File
@@ -1,143 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
import stdio
import stdlib
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesBody as HandlesBody
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesFunctions - 函数定义处理(P5-1 对象化后的委托层)
#
# P5-1 对象化重构(wiki/14-oo-refactor.md):
# 全部函数已迁移为 lib.core.Gen.FuncGenMixin 的方法,本模块保留
# 同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen
# 的对应方法。签名与旧函数完全一致,调用方零改动。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug)
SCOPE_FUNCTION: t.CDefine = 1
# ============================================================
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
# ============================================================
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
imported_modules: str) -> str:
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串(委托到 gen.extract_func_attrs)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.extract_func_attrs(pool, decorator_list, imported_modules)
return None
def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str:
"""从 AST 节点提取属性名(委托到 gen._get_attr_name_from_node)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._get_attr_name_from_node(node)
return None
def _append_llvm_attr(attrs_buf: str, attr_name: str) -> int:
"""将属性名映射到 LLVM 属性名并追加到缓冲区(委托到 gen._append_llvm_attr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._append_llvm_attr(attrs_buf, attr_name)
return 0
def _append_str(buf: str, s: str) -> None:
"""将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)(委托到 gen._append_str)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g._append_str(buf, s)
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)(委托到 gen._mangle_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._mangle_name(trans, name)
return None
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)(委托到 gen._mangle_name_with_sha1)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._mangle_name_with_sha1(sha1, name)
return None
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
has_export: int) -> str:
"""为函数名添加 SHA1 前缀(检查 main/export)(委托到 gen._mangle_func_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._mangle_func_name(trans, name, has_export)
return None
def forward_declare_functions(trans: HT.Translator | t.CPtr,
tree: ast.AST | t.CPtr) -> int:
"""预扫描所有顶层 FunctionDef,创建前向声明(委托到 gen.forward_declare_functions)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.forward_declare_functions(trans, tree)
return 0
def translate_function_def(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)(委托到 gen.translate_function_def)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_function_def(trans, node)
return 0
def translate_nested_function_def(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译嵌套函数定义:提升为顶层函数 + 创建闭包(委托到 gen.translate_nested_function_def)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_nested_function_def(trans, node)
return 0
def create_function(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
name: str,
args_node: ast.AST | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
"""创建 LLVM 函数并添加参数(委托到 gen.create_function)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.create_function(pool, mod, name, args_node, ret_ty)
return None
-42
View File
@@ -1,42 +0,0 @@
import t, c
from stdint import *
import ast
import memhub
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesIf - if/elif/else 语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:IfHandle 类 → StmtGenCifMixin.translate_if。
# CIf 编译期求值(_is_cif_attr/_is_cif_call/_get_platform_macro_value/
# _cif_name_value/_cif_attr_value/_cif_eval_node/_evaluate_cif_test 及
# 模块级 _g_cif_eval_ok)已迁移为 StmtGenCifMixin 的方法/字段
# (CifEvalOk)。
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_if - if/elif/else 语句翻译(委托到 gen.translate_if)
# ============================================================
def translate_if(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 if/elif/else 语句(委托到 gen.translate_if)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_if(trans, node)
return 0
-326
View File
@@ -1,326 +0,0 @@
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.VLogger as VLogger
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesImports - 导入语句处理(P6-D 对象化后的委托层)
#
# 管理 _imported_modules 和 _from_imports 字符串
# 注意:str = bytes = str = 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 工厂已删除(P6 机械化迁移:
# HandleImport/HandleImportFromModule/HandleImportFromNames → 本模块
# 新增的 translate_import/translate_import_from_module/
# translate_import_from_names 模块级委托壳,路由到 gen 方法)。
# ============================================================
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: Generator.Generator | t.CPtr = None
# ============================================================
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
# ============================================================
# ============================================================
# 添加已导入模块名
# ============================================================
def add_imported_module(pool: memhub.MemBuddy | t.CPtr,
imported_modules: str,
name: str) -> str:
"""记录已导入的模块名,返回新的 imported_modules 字符串指针(委托到 gen.add_imported_module)"""
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:
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配,委托到 gen.is_module_imported)"""
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
# ============================================================
# 添加 from-import 名称映射
# ============================================================
def add_from_import(pool: memhub.MemBuddy | t.CPtr,
from_imports: str,
local_name: str,
module_name: str,
original_name: str = None) -> str:
"""添加 from-import 映射,返回新的 from_imports 字符串(委托到 gen.add_from_import)
格式:
无别名: "local_name:module_name"
有别名: "local_name:module_name:original_name"
(original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰)
"""
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
# ============================================================
# 查找 from-import 名称 → 返回原始函数名(别名场景)
#
# 对于 from X import Y as Z,返回 Y(源模块中的真实函数名)。
# 无别名时返回 None(local_name 即为原始名)。
# ============================================================
def lookup_from_import_original(from_imports: str,
local_name: str) -> str:
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到(委托到 gen.lookup_from_import_original)"""
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
# ============================================================
# 查找 from-import 名称 → 返回模块名或 None
#
# allow_star_fallback: 是否允许 star import 回退(默认 1=允许)。
# 当查询明确模块名(如 "BuildPipeline")时,应传 0 禁用回退,
# 避免被 star import 模块名误导(如 from stdint import * 后
# 查询 "BuildPipeline" 错误回退到 "stdint")。
# ============================================================
def lookup_from_import(from_imports: str, name: str,
allow_star_fallback: int = 1) -> str:
"""查找 from-import 名称,返回模块名或 None(委托到 gen.lookup_from_import)
支持 star import: 如果 from_imports 中有 "*:module" 条目,
且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。
"""
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
# ============================================================
# register_reexport - 注册 re-export 映射
#
# 在 HandleImportFromNames 中调用:当处理 from .X import Y 时,
# 记录当前模块(通过 ModuleSha1)re-export 了函数 Y,源模块为 X。
#
# 幂等:重复注册相同映射不会增加条目。
# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。
# ============================================================
def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int:
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败(委托到 gen.register_reexport)"""
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
# ============================================================
# lookup_reexport - 查找 re-export 映射
#
# 给定模块 SHA1 和函数名,返回源模块名(如 "ast.lexer")或 None。
# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。
# ============================================================
def lookup_reexport(mod_sha1: str, func_name: str) -> str:
"""查找 re-export 映射,返回源模块名或 None(委托到 gen.lookup_reexport)"""
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
# ============================================================
# _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(pool: memhub.MemBuddy | t.CPtr,
current_package: str,
level: t.CInt,
module: str) -> str:
"""解析相对导入为完整模块名(委托到 gen._resolve_relative_module)"""
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
# ============================================================
# 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(pool: memhub.MemBuddy | t.CPtr,
rel_path: str) -> str:
"""从相对路径计算包名(目录部分,分隔符替换为 .,委托到 gen.compute_package_from_relpath)"""
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
# ============================================================
# set_current_file - 设置当前编译的文件名
#
# 与 HandlesType.set_current_file 同步调用,写入 gen.CurrentFile
# (委托到 gen.set_current_file)。
# ============================================================
def set_current_file(file_path: str) -> None:
"""设置当前正在编译的文件名(与 HandlesType.set_current_file 同步调用,委托到 gen.set_current_file)"""
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)
# ============================================================
# _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(node: ast.AST | t.CPtr, msg: str) -> None:
"""以 Python 风格报错并退出(本地实现,避免循环依赖,委托到 gen._report_import_error)"""
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)"""
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
# ============================================================
# _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(node: ast.AST | t.CPtr, mod_name: str) -> int:
"""导入时校验模块 SHA1 是否已注册,未注册则立即报错退出(委托到 gen._check_import_sha1)
Args:
node: Import/ImportFrom AST 节点(提供行号)
mod_name: 导入的模块名(如 "memhub"、"w32.fileio")
Returns:
1=检查通过;模块未注册时直接报错退出(不会返回 0)
"""
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
# ============================================================
# translate_import - 处理 import 语句(委托到 gen.translate_import)
# ============================================================
def translate_import(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""处理 import 语句,返回 0(委托到 gen.translate_import)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_import(trans, node)
return 0
# ============================================================
# translate_import_from_module - 处理 from X import Y 的模块部分
# (委托到 gen.translate_import_from_module)
# ============================================================
def translate_import_from_module(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""处理 from X import Y 的模块部分(委托到 gen.translate_import_from_module)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_import_from_module(trans, node)
return 0
# ============================================================
# translate_import_from_names - 处理 from X import Y 的名称部分
# (委托到 gen.translate_import_from_names)
# ============================================================
def translate_import_from_names(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""处理 from X import Y 的名称部分(委托到 gen.translate_import_from_names)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_import_from_names(trans, node)
return 0
-172
View File
@@ -1,172 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
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
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesMain - 模块级翻译入口 + wrapper main 创建
#
# 从 translator.py 拆分出来,负责:
# 1. create_wrapper_main() - 无用户 main 时创建包装 main
# 2. translate_children() - 遍历 AST 子节点并分派翻译
#
# trans 单参模式:所有共享状态从 trans 获取,无需 11 个参数
# 注意: str = bytes = str = i8*
#
# P6-E 对象化重构:全部函数已迁移为 lib.core.Gen.TranslatorGenMixin
# 的方法,本模块保留同名模块级函数作为"一行委托"(同 P2-P5 模式):
# 延迟 import Gen 取全局单例,再调用 gen 的对应方法。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数
#
# 解决翻译顺序依赖问题:Phase 1b 按字母序翻译,后翻译的模块的
# CExport 函数无法被先翻译的模块正确识别为裸名调用。
# Phase 1a 预注册所有 CExport/State 函数名到全局表。
# ============================================================
def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)(委托到 gen._register_cexport_from_funcdef)"""
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
# ============================================================
# translate_children - 遍历 AST 子节点并分派翻译
#
# 对应 TransPyC translator._translate_children()
# 共享状态从 trans 获取,imported_modules/from_imports 更新到 trans
# ============================================================
def translate_children(trans: HT.Translator | t.CPtr,
tree: ast.AST | t.CPtr) -> int:
"""遍历 tree.children 并翻译每个子节点(委托到 gen.translate_children)
Args:
trans: 翻译器(含所有共享状态)
tree: AST 模块节点
Returns:
t.CInt: 新增的变量数
"""
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
# ============================================================
# _prescan_funcdef_signatures - 1a 阶段预解析模块级函数签名
#
# 触发泛型类特化(如 numpy 的 _empty_like 签名 ndarray[t.CDouble]),
# 使特化结构体在 mark1 前注册(Ty/Fields 不被 1b 的 mark/reset 回收),
# 避免 Phase2 翻译 App 文件时访问悬空结构体(UAF)。
# 仅解析类型触发特化,不验证结果(1b 全量翻译时重新解析)。
# ============================================================
def _prescan_funcdef_signatures(trans: HT.Translator | t.CPtr,
fd: ast.FunctionDef | t.CPtr) -> None:
"""预解析模块级函数签名的返回/参数类型,触发泛型类特化(委托到 gen._prescan_funcdef_signatures)"""
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)
# ============================================================
# _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(pool: memhub.MemBuddy | t.CPtr,
var_ty: llvmlite.LLVMType | t.CPtr,
list_node: ast.List | t.CPtr) -> str:
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败(委托到 gen._build_array_initializer_text)"""
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
# ============================================================
# _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(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
var_name: str,
str_val: str) -> str:
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败(委托到 gen._build_string_ptr_initializer)"""
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
# ============================================================
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
#
# 当用户已定义 main(无 wrapper main builder)时,模块级
# AnnAssign/Assign 创建全局变量 @var_name 并注册到 SymTab 模块作用域
# 支持整数、列表字面量、字符串字面量初始值
# ============================================================
def handle_module_level_var(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""处理模块级变量声明,创建全局变量(委托到 gen.handle_module_level_var)"""
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
# ============================================================
# create_wrapper_main - 创建包装 main 函数
#
# 当用户未定义 main 函数时调用。
# 创建 main() -> i32 函数 → 设置 trans._cur_func/_cur_builder →
# 预扫描 alloca → 翻译子节点 → ret 0
# ============================================================
def create_wrapper_main(trans: HT.Translator | t.CPtr,
tree: ast.AST | t.CPtr,
i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""创建包装 main 函数并翻译所有顶层语句(委托到 gen.create_wrapper_main)
Args:
trans: 翻译器(含所有共享状态)
tree: AST 模块节点
i32_ty: i32 LLVMType
Returns:
t.CInt: 新增的变量数
"""
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
-74
View File
@@ -1,74 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import viperlib
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.HandlesBody as HandlesBody
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesMatch - match 语句处理(P6 对象化后的委托层)
#
# P6 机械化迁移:MatchHandle 类 → lib.core.Gen.MatchGenMixin
# (Handle → translate_match,方法体 self.Trans → trans 首参;
# 类内辅助方法 + 模块级 _case_tail_unreachable 一并搬入成方法)。
# 本模块保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
# 对应方法。签名与旧函数完全一致,调用方零改动。
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
#
# 逻辑移植自 TPC 的 HandlesMatch.py,用 Viper 语法重写。
# 两条路径:
# 1. REnum 路径:bitcast subject 到 i32* 读 __tag + switch 分派
# 2. 非 REnum 路径:subject ptrtoint 到 i32 + switch 分派
#
# IR 模式(REnum):
# %tag_ptr = bitcast <struct>* %subj to i32*
# %tag = load i32, i32* %tag_ptr
# switch i32 %tag, label %default [ i32 <tag1>, label %case1 ... ]
# case1:
# ... body ...
# br label %end (若无 c.NoBreak)
# end:
# ============================================================
# match case 数量上限
MAX_MATCH_CASES: t.CDefine = 32
# 作用域种类常量(与 HandlesVar 的 Scope.Kind 区分)
SCOPE_MATCH: t.CDefine = 6
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# MatchGenMixin 方法,避免函数体 import 包模块与 Generator
# 类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_match - match 语句翻译(委托到 gen.translate_match)
# ============================================================
def translate_match(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 match 语句,返回 0(委托到 gen.translate_match)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_match(trans, node)
return 0
-126
View File
@@ -1,126 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)(P6 对象化后的委托层)
#
# 全部模块级函数已迁移为 lib.core.Gen.StmtGenMixin 的方法,本模块
# 保留同名模块级函数作为"一行委托":延迟 import Gen 取全局单例
# (BuildPipeline/main 创建后 set_global_gen 注册),再调用 gen 的
# 对应方法。签名与旧函数完全一致,调用方零改动。
#
# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针)
# 指针指向父函数中变量的 alloca(原始存储位置),父与子共享同一存储,
# 子函数修改对父函数可见(符合 Python nonlocal 语义)。
#
# 在提升的嵌套函数中:
# 1. 函数签名: define i32 @__closure_{name}(i8* %env)
# 2. 入口处: %env_alloca = alloca i8*; store i8* %env, i8** %env_alloca
# 3. 访问 nonlocal var:
# a. %env_ptr = load i8*, i8** %env_alloca
# b. %addr = gep i8, i8* %env_ptr, i32 (index * 8)
# c. %ptr_addr = bitcast i8* %addr to i8**
# d. %var_ptr_raw = load i8*, i8** %ptr_addr
# e. %var_ptr = bitcast i8* %var_ptr_raw to <var_ty>*
# f. read: %val = load <var_ty>, <var_ty>* %var_ptr
# write: store <var_ty> %new, <var_ty>* %var_ptr
#
# 变量类型通过 HT.get_nonlocal_type() 获取(注册 nonlocal 时记录)。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# StmtGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# _is_void_type — 判断是否为 Void 类型(非法用作变量类型)
#
# 由于某些路径(如 c.DerefAs 设置的 Pointee 字段访问异常)可能导致
# 类型被设为 Void 而非 None,这里显式检测 Void 类型并视为无效,
# 回退为 i32,避免生成 "bitcast ... to void*" / "load void, void*" 的非法 IR。
# ============================================================
def _is_void_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""判断是否为 Void 类型,是则返回 1,否则 0(委托到 gen._is_void_type)"""
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 指针)(委托到 gen.get_env_ptr_var)"""
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
# ============================================================
# 从 env 加载原始变量指针(i8*)→ 调用方 bitcast 为具体类型
#
# env 存储指针数组(8 字节/槽),每个指针指向父函数的 alloca。
# ============================================================
def _load_raw_var_ptr(trans: HT.Translator | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""从闭包 env 加载 nonlocal 变量的原始指针(i8*)(委托到 gen._load_raw_var_ptr)
返回 i8* 类型的 Value,调用方需 bitcast 为具体类型指针后 load/store。
"""
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
# ============================================================
# 加载 nonlocal 变量值 → 返回具体类型的 Value
#
# env 存储指向父函数 alloca 的指针,通过类型恢复 load 正确类型的值。
# ============================================================
def load_nonlocal_var(trans: HT.Translator | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""从闭包 env 加载 nonlocal 变量值(委托到 gen.load_nonlocal_var)
通过 HT.get_nonlocal_type 获取变量类型,bitcast 原始指针后 load。
"""
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
# ============================================================
# 获取 nonlocal 变量指针(用于 store)
#
# 返回具体类型指针(var_ty*),用于直接 store。
# ============================================================
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""获取 nonlocal 变量的存储指针(var_ty*),用于 store 操作(委托到 gen.get_nonlocal_var_ptr)
返回的指针指向父函数的 alloca,store 操作对父函数可见。
"""
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
-33
View File
@@ -1,33 +0,0 @@
import t, c
from stdint import *
import ast
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesReturn - Return 语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:ReturnHandle 类 → StmtGenCifMixin.translate_return。
# 分派中枢(StmtGenMixin)经本壳跨类调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_return - Return 语句翻译(委托到 gen.translate_return)
# ============================================================
def translate_return(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 Return 语句,返回 0(委托到 gen.translate_return)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_return(trans, node)
return 0
-544
View File
@@ -1,544 +0,0 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import stdio
import ast
import hashtable
import viperlib
import lib.core.VLogger as VLogger
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesStruct - 结构体类型注册和字段查找(P2-2 对象化后的委托层)
#
# 管理 class 定义的结构体类型信息:
# - 类名 → LLVM StructType
# - 字段名 → 字段索引和类型
#
# P2-2 对象化重构(wiki/14-oo-refactor.md):
# 全部函数已迁移为 lib.core.Gen.StructGenMixin 的方法(全局状态迁入
# gen 字段),本模块保留同名模块级函数作为"一行委托":延迟 import
# Gen 取全局单例(BuildPipeline/main 创建后 set_global_gen 注册),
# 再调用 gen 的对应方法。签名与旧函数完全一致,调用方零改动。
#
# FieldEntry/StructEntry 类型与常量保留在本模块(gen 字段类型引用)。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType 模式)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
STRUCT_MAX: t.CDefine = 512
# 字段槽位上限制(Generator 43 Mixin 展平 ~120 字段;2026-08-16 追加78:64
# 截断导致第 9+ 父类字段丢失 → __init__ 写 self.DiagStmtCount "属性写入失败"。
# 拆分重构使 Generator 父类数增至 43,FIELD_MAX 提至 256 防静默截断)
FIELD_MAX: t.CDefine = 256
FIELD_NAME_MAX: t.CDefine = 64
# 多继承(MRO)支持:单类最大父类数 / MRO 链最大长度(Generator 43 父类;
# PARENT_MAX=16 时 _collect_parents/set_parent_names 只收前 16 个 → 第 17+
# 父类字段丢失 → __init__ 写 self.DiagStmtCount "属性写入失败" 根因)
PARENT_MAX: t.CDefine = 64
MRO_MAX: t.CDefine = 64
# ============================================================
# FieldEntry - 字段信息条目
# ============================================================
@t.NoVTable
class FieldEntry:
Name: str # 字段名(字符串)
Index: int # 字段在结构体中的索引
Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型
DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值)
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
# ============================================================
# StructEntry - 结构体注册条目
# ============================================================
@t.NoVTable
class StructEntry:
Name: str # 类名
Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType
FieldCount: int # 字段数量
Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位)
IsUnion: int # 1=联合体 / 0=普通结构体
IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体
HasInit: int # 1=有__init__方法 / 0=无
HasNew: int # 1=有__new__方法 / 0=无
HasVTable: int # 1=有虚表 / 0=无虚表
IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记
ParentName: str # 父类名(None=无父类,多继承时为第一个父类,兼容旧调用)
ParentNames: t.CSizeT | t.CPtr # 多继承父类名数组(每元素 str 指针,ParentCount 个;stdlib 深拷贝)
ParentCount: t.CInt # 父类数量(0=无父类,1=单继承,>1=多继承)
VTableMethodCount: int # 虚表中的方法数量
VTableMethods: str # 虚表方法名数组(每个方法名 str,VTableMethodCount 个)
ModuleSha1: str # 定义该类的模块 SHA1(None=无 SHA1)
MethodsEmitted: int # 1=方法体已翻译 / 0=未译(Phase 1a mark_only 未译,Phase B 据此补译)
SpecTriggerSha1: str # 泛型特化类的触发文件 SHA1(None=非特化类)。特化类 ModuleSha1=模板
# sha1(方法名带模板前缀),作废重译时 reset_module_methods_emitted
# 按触发文件 sha1 精确重置 MethodsEmitted,防特化方法体残留 1 不补译
# → 链接 undefined symbol(list[ast.ClassDef|t.CPtr].* 根因)
def set_stdlib_alloc(flag: int):
"""设置 OOM 回收分配模式(委托到 gen.set_stdlib_alloc)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.set_stdlib_alloc(flag)
def get_stdlib_alloc() -> int:
"""读取 OOM 回收分配模式(委托到 gen.get_stdlib_alloc)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_stdlib_alloc()
return 0
def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int):
"""重置可见性状态(每个文件翻译前调用,委托到 gen.reset_visible_structs)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.reset_visible_structs(pool, strict)
def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str):
"""添加可见结构体名(类定义时和 from-import 时调用,委托到 gen.add_visible_struct)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.add_visible_struct(pool, name)
def is_struct_visible(name: str) -> int:
"""检查结构体是否可见,返回 1=可见 / 0=不可见(委托到 gen.is_struct_visible)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_struct_visible(name)
return 0
def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int:
"""初始化结构体注册表,返回 1 成功(委托到 gen.init_struct_table)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.init_struct_table(pool)
return 0
def _get_struct_entry(i: int) -> StructEntry | t.CPtr:
"""获取第 i 个结构体条目(委托到 gen._get_struct_entry)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._get_struct_entry(i)
return None
def _get_field_entry(struct_entry: StructEntry | t.CPtr, i: int) -> FieldEntry | t.CPtr:
"""获取结构体中第 i 个字段条目(委托到 gen._get_field_entry)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._get_field_entry(struct_entry, i)
return None
def register_struct(pool: memhub.MemBuddy | t.CPtr,
name: str,
struct_ty: llvmlite.LLVMType | t.CPtr,
sha1: str = None) -> StructEntry | t.CPtr:
"""注册结构体类型,返回 StructEntry 指针(委托到 gen.register_struct)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.register_struct(pool, name, struct_ty, sha1)
return None
def set_struct_sha1(pool: memhub.MemBuddy | t.CPtr,
class_name: str, sha1: str) -> int:
"""设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败(委托到 gen.set_struct_sha1)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_struct_sha1(pool, class_name, sha1)
return 0
def get_struct_sha1(class_name: str) -> str:
"""获取结构体所属模块的 SHA1,返回 None=无 SHA1(委托到 gen.get_struct_sha1)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_struct_sha1(class_name)
return None
def add_field(pool: memhub.MemBuddy | t.CPtr,
struct_entry: StructEntry | t.CPtr,
field_name: str,
field_ty: llvmlite.LLVMType | t.CPtr,
default_val: ast.AST | t.CPtr = None,
annot_class_name: str = None) -> int:
"""向结构体添加字段,返回字段索引(-1 失败,委托到 gen.add_field)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.add_field(pool, struct_entry, field_name, field_ty,
default_val, annot_class_name)
return 0
def get_struct_count() -> int:
"""返回当前已注册的结构体数量(委托到 gen.get_struct_count)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_struct_count()
return 0
def reset_module_methods_emitted(sha1: str) -> int:
"""回滚指定模块注册类的 MethodsEmitted 标志(Phase A _deps_pending 重试
前调用,防 MethodsEmitted 跨遍残留导致类方法缺失——追加87,委托到 gen.reset_module_methods_emitted)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.reset_module_methods_emitted(sha1)
return 0
def find_struct(name: str) -> StructEntry | t.CPtr:
"""按类名查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.find_struct(name)
return None
def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr:
"""按类名 + SHA1 查找结构体,返回 StructEntry 或 None(委托到 gen.find_struct_by_module)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.find_struct_by_module(name, sha1)
return None
def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr:
"""按类型指针查找结构体(指针值比较),返回 StructEntry 或 None(委托到 gen.find_struct_by_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.find_struct_by_type(struct_ty)
return None
def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr,
field_name: str) -> FieldEntry | t.CPtr:
"""按结构体类型和字段名查找字段信息(委托到 gen.lookup_field)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_field(struct_ty, field_name)
return None
def lookup_field_by_class(class_name: str,
field_name: str,
sha1: str = None) -> FieldEntry | t.CPtr:
"""按类名和字段名查找字段信息(委托到 gen.lookup_field_by_class)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_field_by_class(class_name, field_name, sha1)
return None
def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr:
"""按类名获取结构体的 LLVM 类型(委托到 gen.get_struct_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_struct_type(class_name)
return None
def get_field_by_index(class_name: str,
idx: int) -> FieldEntry | t.CPtr:
"""按类名和字段索引获取字段信息(委托到 gen.get_field_by_index)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_by_index(class_name, idx)
return None
def struct_has_defaults(class_name: str) -> int:
"""检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无(委托到 gen.struct_has_defaults)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.struct_has_defaults(class_name)
return 0
def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""从 Value 的类型推断结构体类型(委托到 gen.get_struct_type_from_value)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_struct_type_from_value(val)
return None
def mark_as_union(name: str) -> int:
"""标记已注册的结构体为联合体,返回 1=成功 / 0=失败(委托到 gen.mark_as_union)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_as_union(name)
return 0
def is_union_by_name(name: str) -> int:
"""按类名检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_union_by_name(name)
return 0
def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int:
"""按类型指针检查是否为联合体,返回 1=是 / 0=否(委托到 gen.is_union_by_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_union_by_type(struct_ty)
return 0
def mark_as_oop(name: str) -> int:
"""标记已注册的结构体为 OOP,返回 1=成功 / 0=失败(委托到 gen.mark_as_oop)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_as_oop(name)
return 0
def is_oop_by_name(name: str) -> int:
"""按类名检查是否为 OOP 结构体,返回 1=是 / 0=否(委托到 gen.is_oop_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_oop_by_name(name)
return 0
def mark_has_init(name: str) -> int:
"""标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_init)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_has_init(name)
return 0
def has_init_by_name(name: str) -> int:
"""按类名检查是否有 __init__ 方法,返回 1=有 / 0=无(委托到 gen.has_init_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.has_init_by_name(name)
return 0
def mark_has_new(name: str) -> int:
"""标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败(委托到 gen.mark_has_new)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_has_new(name)
return 0
def has_new_by_name(name: str) -> int:
"""按类名检查是否有 __new__ 方法,返回 1=有 / 0=无(委托到 gen.has_new_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.has_new_by_name(name)
return 0
def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr,
struct_ty: llvmlite.LLVMType | t.CPtr) -> str:
"""按类型指针查找类名,返回类名字符串或 None(委托到 gen.get_class_name_by_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_class_name_by_type(pool, struct_ty)
return None
def _extract_struct_name(ty: llvmlite.LLVMType | t.CPtr) -> str:
"""从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct(委托到 gen._extract_struct_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._extract_struct_name(ty)
return None
def mark_has_vtable(name: str) -> int:
"""标记结构体拥有虚表,返回 1=成功 / 0=失败(委托到 gen.mark_has_vtable)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_has_vtable(name)
return 0
def has_vtable_by_name(name: str) -> int:
"""按类名检查是否有虚表,返回 1=有 / 0=无(委托到 gen.has_vtable_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.has_vtable_by_name(name)
return 0
def mark_novtable(name: str) -> int:
"""标记结构体为 NoVTable,返回 1=成功 / 0=失败(委托到 gen.mark_novtable)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.mark_novtable(name)
return 0
def is_novtable_by_name(name: str) -> int:
"""按类名检查是否为 NoVTable,返回 1=是 / 0=否(委托到 gen.is_novtable_by_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_novtable_by_name(name)
return 0
def set_parent_name(name: str, parent_name: str) -> int:
"""设置结构体的父类名,返回 1=成功 / 0=失败(委托到 gen.set_parent_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_parent_name(name, parent_name)
return 0
def set_parent_names(pool: memhub.MemBuddy | t.CPtr,
name: str, names_ptr: t.CSizeT | t.CPtr,
count: int) -> int:
"""设置结构体的父类名数组(永久池深拷贝,委托到 gen.set_parent_names)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_parent_names(pool, name, names_ptr, count)
return 0
def get_parent_count(name: str) -> int:
"""获取父类数量(0=无父类,1=单继承,>1=多继承,委托到 gen.get_parent_count)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_parent_count(name)
return 0
def get_parent_name_at(name: str, idx: int) -> str:
"""获取第 idx 个父类名,越界返回 None(委托到 gen.get_parent_name_at)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_parent_name_at(name, idx)
return None
def get_mro_chain(pool: memhub.MemBuddy | t.CPtr,
name: str) -> t.CSizeT | t.CPtr:
"""MRO 线性化类名数组(深度优先 + 声明顺序 + 去重,含自身,委托到 gen.get_mro_chain)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_mro_chain(pool, name)
return None
def get_parent_name(name: str) -> str:
"""获取结构体的父类名,返回 None=无父类(委托到 gen.get_parent_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_parent_name(name)
return None
def set_vtable_methods(name: str, methods: str, count: int) -> int:
"""设置虚表方法名数组,返回 1=成功 / 0=失败(委托到 gen.set_vtable_methods)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.set_vtable_methods(name, methods, count)
return 0
def get_vtable_method_index(name: str, method_name: str) -> int:
"""获取方法在虚表中的索引,返回 -1=未找到(委托到 gen.get_vtable_method_index)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_vtable_method_index(name, method_name)
return 0
def get_vtable_method_count(name: str) -> int:
"""获取虚表方法数量(委托到 gen.get_vtable_method_count)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_vtable_method_count(name)
return 0
def get_vtable_method_name(name: str, idx: int) -> str:
"""获取虚表中第 idx 个方法名,返回 None=越界(委托到 gen.get_vtable_method_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_vtable_method_name(name, idx)
return None
def get_field_count(name: str) -> int:
"""获取结构体字段数量,返回 -1=未找到(委托到 gen.get_field_count)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_count(name)
return 0
def ensure_struct_def_in_module(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
ty: llvmlite.LLVMType | t.CPtr):
"""确保跨模块结构体的完整定义在当前模块中可用(委托到 gen.ensure_struct_def_in_module)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.ensure_struct_def_in_module(pool, mod, ty)
def _ensure_field_types_in_module(pool: memhub.MemBuddy | t.CPtr,
mod: llvmlite.LLVMModule | t.CPtr,
ty: llvmlite.LLVMType | t.CPtr):
"""递归扫描类型树,确保值类型子结构体有完整定义(委托到 gen._ensure_field_types_in_module)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g._ensure_field_types_in_module(pool, mod, ty)
def get_field_name_ptr(fe: FieldEntry | t.CPtr) -> str:
"""获取 FieldEntry 的字段名,返回 None=未设置(委托到 gen.get_field_name_ptr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_name_ptr(fe)
return None
def get_field_type_ptr(fe: FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""获取 FieldEntry 的字段类型,返回 None=未设置(委托到 gen.get_field_type_ptr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_type_ptr(fe)
return None
def get_field_default_ptr(fe: FieldEntry | t.CPtr) -> ast.AST | t.CPtr:
"""获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值(委托到 gen.get_field_default_ptr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_default_ptr(fe)
return None
def get_field_annot_class_name(fe: FieldEntry | t.CPtr) -> str:
"""获取 FieldEntry 的原始类型注解类名,返回 None=未设置(委托到 gen.get_field_annot_class_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_field_annot_class_name(fe)
return None
File diff suppressed because it is too large. Load diff
-598
View File
@@ -1,598 +0,0 @@
import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import sys
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.HandlesImports as HandlesImports
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesVar as HandlesVar
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesType - 类型映射与解析(P2 对象化后的委托层)
# ============================================================
# ============================================================
# 常量(保留,供 TraceFrame 相关使用)
# ============================================================
TRACE_MAX: t.CDefine = 32
MAX_CTYPEDEF_DEPTH: t.CDefine = 10
@t.NoVTable
class TraceFrame:
file_name: str # 文件名
lineno: int # 行号
col_start: int # 列起始(1-based,0=不指定)
col_end: int # 列结束(1-based,0=不指定)
# ============================================================
# 全局 gen 单例(模块级镜像)
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 类编译期元数据(__provides__/__requires__/__require_must__)
#
# _fakeduck.vp 的 _str 用 __requires__ = ['__mbuddy__'] 声明 with 上下文
# 依赖字段;with 提供者用 __provides__ 声明注入字段。这些是编译期
# 元数据,不生成运行字段(FakeDuck 移植点 1)。
# ============================================================
CLASS_META_PROVIDES: t.CDefine = 1
CLASS_META_REQUIRES: t.CDefine = 2
CLASS_META_REQUIRE_MUST: t.CDefine = 3
def register_class_meta(pool: memhub.MemBuddy | t.CPtr,
kind: int, cls: str, field: str) -> int:
"""注册类编译期元数据字段(委托到 gen.register_class_meta),0=成功"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.register_class_meta(pool, kind, cls, field)
return 1
def class_meta_count(kind: int, cls: str) -> int:
"""返回某类某元数据类型的字段数(委托到 gen.class_meta_count)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.class_meta_count(kind, cls)
return 0
def class_meta_field_at(kind: int, cls: str, idx: int) -> str:
"""返回某类某元数据类型的第 idx 个字段名(委托到 gen.class_meta_field_at)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.class_meta_field_at(kind, cls, idx)
return None
def _ensure_trace_init() -> int:
"""确保调用栈已初始化(委托到 gen._ensure_trace_init)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._ensure_trace_init()
return 0
def _get_trace_frame(i: int) -> TraceFrame | t.CPtr:
"""获取第 i 个 TraceFrame 槽位(委托到 gen._get_trace_frame)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._get_trace_frame(i)
return None
def push_trace(file_name: str, lineno: int, col_start: int = 0, col_end: int = 0):
"""压入一个翻译上下文帧(委托到 gen.push_trace)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.push_trace(file_name, lineno, col_start, col_end)
def pop_trace():
"""弹出栈顶帧(委托到 gen.pop_trace)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.pop_trace()
def clear_trace():
"""清空调用栈(委托到 gen.clear_trace)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.clear_trace()
def set_temp_dir(temp_dir: str) -> None:
"""设置全局 temp_dir(委托到 gen.set_temp_dir)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.set_temp_dir(temp_dir)
def get_temp_dir() -> str:
"""获取全局 temp_dir(委托到 gen.get_temp_dir)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_temp_dir()
return None
def set_current_module_sha1(sha1: str) -> None:
"""设置当前正在编译的模块 SHA1(委托到 gen.set_current_module_sha1)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.set_current_module_sha1(sha1)
def _dbg_check_ast_floats(mb: memhub.MemBuddy | t.CPtr,
tree: ast.AST | t.CPtr, tag: str):
"""已移除调试插桩(占位保留签名,避免外部调用引用失败)"""
pass
def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
name: str, value: t.CInt64T) -> None:
"""注册 CDefine 编译期常量到本地表(委托到 gen.register_cdefine_constant)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.register_cdefine_constant(pool, name, value)
def register_cdefine_double(pool: memhub.MemBuddy | t.CPtr,
name: str, value: double) -> None:
"""注册浮点 CDefine 编译期常量(委托到 gen.register_cdefine_double)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.register_cdefine_double(pool, name, value)
def register_cdefine_string(pool: memhub.MemBuddy | t.CPtr,
name: str, value: str) -> None:
"""注册字符串 CDefine 编译期常量(委托到 gen.register_cdefine_string)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.register_cdefine_string(pool, name, value)
def lookup_cdefine_constant(name: str) -> t.CInt64T:
"""查找 CDefine 编译期常量(委托到 gen.lookup_cdefine_constant)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_cdefine_constant(name)
return 0
def lookup_cdefine_double(name: str) -> double:
"""查找 CDefine 编译期常量,返回 double 值(委托到 gen.lookup_cdefine_double)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_cdefine_double(name)
return 0.0
def lookup_cdefine_string(name: str) -> str:
"""查找 CDefine 编译期字符串值(委托到 gen.lookup_cdefine_string)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_cdefine_string(name)
return None
def is_cdefine_str() -> int:
"""检查最近一次 CDefine 查找命中的是否是字符串常量(委托到 gen.is_cdefine_str)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_cdefine_str()
return 0
def eval_ctraits_isptr(symtab: HandlesVar.SymbolTable | t.CPtr,
name: str) -> int:
"""ctraits.isptr(name) 编译期求值(委托到 gen._eval_ctraits_isptr)。
返回: 1=指针 0=非指针 -1=无法求值。
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._eval_ctraits_isptr(symtab, name)
return -1
def is_cdefine_double() -> int:
"""检查最近一次 CDefine 查找命中的是否是浮点常量(委托到 gen.is_cdefine_double)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_cdefine_double()
return 0
def is_cdefine_found() -> int:
"""检查上次 lookup_cdefine_constant 是否找到值(委托到 gen.is_cdefine_found)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_cdefine_found()
return 0
def set_cdefine_found(val: int) -> None:
"""设置 cdefine_found 标志(委托到 gen.set_cdefine_found)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.set_cdefine_found(val)
def clear_cdefine_constants() -> None:
"""清空 CDefine 常量表(委托到 gen.clear_cdefine_constants)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.clear_cdefine_constants()
def register_xmod_cdefine(name: str, value_str: str,
is_double: int, is_str: int) -> None:
"""注册跨模块 CDefine 查找结果到 perm_pool 全局缓存(委托到 gen.register_xmod_cdefine)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.register_xmod_cdefine(name, value_str, is_double, is_str)
def lookup_xmod_cdefine(name: str) -> str:
"""查找跨模块 CDefine 缓存(委托到 gen.lookup_xmod_cdefine)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_xmod_cdefine(name)
return None
def register_ctypedef(pool: memhub.MemBuddy | t.CPtr,
name: str, type_str: str) -> None:
"""注册 CTypedef 到本地表(委托到 gen.register_ctypedef)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.register_ctypedef(pool, name, type_str)
def lookup_ctypedef(name: str) -> str:
"""查找 CTypedef,返回类型表达式字符串(委托到 gen.lookup_ctypedef)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.lookup_ctypedef(name)
return None
def is_ctypedef_found() -> int:
"""检查上次 lookup_ctypedef 是否找到值(委托到 gen.is_ctypedef_found)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_ctypedef_found()
return 0
def clear_ctypedefs() -> None:
"""清空 CTypedef 表(委托到 gen.clear_ctypedefs)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.clear_ctypedefs()
def _ctypedef_push_visiting(pool: memhub.MemBuddy | t.CPtr, name: str) -> int:
"""将 CTypedef 名加入正在解析列表(委托到 gen._ctypedef_push_visiting)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._ctypedef_push_visiting(pool, name)
return 0
def _ctypedef_pop_visiting() -> None:
"""从正在解析列表弹出最后一个 CTypedef 名(委托到 gen._ctypedef_pop_visiting)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g._ctypedef_pop_visiting()
def _is_ctypedef_annotation(annotation: ast.AST | t.CPtr) -> int:
"""检测类型注解是否为 t.CTypedef(委托到 gen._is_ctypedef_annotation)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._is_ctypedef_annotation(annotation)
return 0
def ScanCTypedefDeclarations(pool: memhub.MemBuddy | t.CPtr,
tree: ast.AST | t.CPtr) -> int:
"""扫描 AST 顶层节点,注册所有 NAME: t.CTypedef = Type 声明(委托到 gen.ScanCTypedefDeclarations)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.ScanCTypedefDeclarations(pool, tree)
return 0
def RegisterCTypedefFromSource(pool: memhub.MemBuddy | t.CPtr,
src: str) -> int:
"""从源码文本逐行注册 CTypedef 声明(委托到 gen.register_ctypedef_from_source)
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读 attr
会 0xC0000005。改用文本匹配 "NAME: t.CTypedef = TYPE"。
"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.register_ctypedef_from_source(pool, src)
return 0
def _eval_const_int_expr(node: ast.AST | t.CPtr,
pool: memhub.MemBuddy | t.CPtr = None,
from_imports: str = None,
imported_modules: str = None) -> int:
"""递归计算常量整数表达式(委托到 gen._eval_const_int_expr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._eval_const_int_expr(node, pool, from_imports, imported_modules)
return 0
def set_generic_context(tp_names: list[str] | t.CPtr,
type_args: list[str] | t.CPtr):
"""设置泛型特化上下文(委托到 gen.set_generic_context)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.set_generic_context(tp_names, type_args)
def clear_generic_context():
"""清除泛型特化上下文(委托到 gen.clear_generic_context)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.clear_generic_context()
def resolve_generic_type_name(name: str) -> str:
"""如果 name 是泛型类型参数,返回对应的具体类型名(委托到 gen.resolve_generic_type_name)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.resolve_generic_type_name(name)
return name
def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr,
node: ast.AST | t.CPtr) -> str:
"""从类型注解节点提取类型名(委托到 gen._get_type_name_from_annotation)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._get_type_name_from_annotation(pool, node)
return None
def _parse_type_string(pool: memhub.MemBuddy | t.CPtr,
type_str: str,
ctx: t.CInt) -> ast.AST | t.CPtr:
"""将类型名字符串解析为 AST 节点(委托到 gen._parse_type_string)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._parse_type_string(pool, type_str, ctx)
return None
def set_current_file(file_path: str):
"""设置当前编译的文件名(委托到 gen.set_current_file)"""
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)
def get_current_file() -> str:
"""获取当前编译的文件名(委托到 gen.get_current_file)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_current_file()
return None
def _read_source_line(file_path: str, lineno: int) -> str:
"""从源文件读取第 lineno 行内容(委托到 gen._read_source_line)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._read_source_line(file_path, lineno)
return None
def read_source_line(file_path: str, lineno: int) -> str:
"""公开包装:从源文件读取第 lineno 行内容(委托到 gen.read_source_line)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.read_source_line(file_path, lineno)
return None
def dump_parse_traceback(file_path: str):
"""解析失败时以 Python 风格输出 traceback(委托到 gen.dump_parse_traceback)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.dump_parse_traceback(file_path)
def fatal_error(node: ast.AST | t.CPtr, msg: str,
err_type: str = "SyntaxError",
col_start: int = 0, col_end: int = 0):
"""以 Python 风格报错并退出(委托到 gen.fatal_error)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.fatal_error(node, msg, err_type, col_start, col_end)
def fatal_type_error(node: ast.AST | t.CPtr, msg: str,
col_start: int = 0, col_end: int = 0):
"""以 Python 风格报错并退出(TypeError 版本,委托到 gen.fatal_type_error)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.fatal_type_error(node, msg, col_start, col_end)
def try_extract_callable_ret(pool: memhub.MemBuddy | t.CPtr,
annot: ast.AST | t.CPtr,
imported_modules: str,
from_imports: str,
trans: HT.Translator | t.CPtr) -> llvmlite.LLVMType | t.CPtr:
"""提取 t.Callable 注解的返回类型 LLVMType(委托到 gen.try_extract_callable_ret)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.try_extract_callable_ret(pool, annot, imported_modules, from_imports, trans)
return None
def map_t_type(pool: memhub.MemBuddy | t.CPtr,
type_name: str) -> llvmlite.LLVMType | t.CPtr:
"""将 t.CXxx / c.CXxx 类型名映射到 LLVMType(委托到 gen.map_t_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.map_t_type(pool, type_name)
return None
def _is_t_attr(node: ast.AST | t.CPtr,
attr_name: str,
imported_modules: str) -> int:
"""检测节点是否是 t.attr_name 形式(委托到 gen._is_t_attr)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._is_t_attr(node, attr_name, imported_modules)
return 0
def _is_cptr_marker(node: ast.AST | t.CPtr,
imported_modules: str) -> int:
"""检测节点是否为 CPtr 指针标记(委托到 gen._is_cptr_marker)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._is_cptr_marker(node, imported_modules)
return 0
def _is_cvoid_marker(node: ast.AST | t.CPtr,
imported_modules: str) -> int:
"""检测节点是否为 CVoid 指针标记(委托到 gen._is_cvoid_marker)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._is_cvoid_marker(node, imported_modules)
return 0
def annotation_to_str(annot: ast.AST | t.CPtr) -> str:
"""将类型注解 AST 转换为可读字符串(委托到 gen.annotation_to_str)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.annotation_to_str(annot)
return None
def extract_class_name_from_annotation(node: ast.AST | t.CPtr,
imported_modules: str,
pool: memhub.MemBuddy | t.CPtr = None) -> str:
"""从类型注解 AST 中提取类名(委托到 gen.extract_class_name_from_annotation)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.extract_class_name_from_annotation(node, imported_modules, pool)
return None
def _resolve_generic_subscript_ty(pool: memhub.MemBuddy | t.CPtr,
sub: ast.Subscript | t.CPtr,
gen_cls_name: str,
trans: HT.Translator | t.CPtr,
imported_modules: str,
from_imports: str) -> llvmlite.LLVMType | t.CPtr:
"""解析泛型类类型注解(委托到 gen._resolve_generic_subscript_ty)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g._resolve_generic_subscript_ty(pool, sub, gen_cls_name, trans,
imported_modules, from_imports)
return None
def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr,
node: ast.AST | t.CPtr,
imported_modules: str,
from_imports: str,
trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
"""解析类型注解节点为 LLVMType(委托到 gen.resolve_annotation_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.resolve_annotation_type(pool, node, imported_modules, from_imports, trans)
return None
def has_decorator_marker(node: ast.AST | t.CPtr,
marker_name: str) -> int:
"""检测类型注解中是否包含指定的装饰器标记(委托到 gen.has_decorator_marker)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.has_decorator_marker(node, marker_name)
return 0
def is_pass_body(body: list[ast.AST | t.CPtr] | t.CPtr) -> int:
"""检测函数体是否为 pass(委托到 gen.is_pass_body)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.is_pass_body(body)
return 0
def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""获取 LLVM 整数类型的位宽(委托到 gen.get_llvm_type_bits)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.get_llvm_type_bits(ty)
return 0
def infer_expr_type(pool: memhub.MemBuddy | t.CPtr,
node: ast.AST | t.CPtr,
param_types: str) -> llvmlite.LLVMType | t.CPtr:
"""推断表达式的 LLVM 类型(委托到 gen.infer_expr_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.infer_expr_type(pool, node, param_types)
return None
def infer_return_type(pool: memhub.MemBuddy | t.CPtr,
body: list[ast.AST | t.CPtr] | t.CPtr,
param_types: str) -> llvmlite.LLVMType | t.CPtr:
"""扫描函数体中的 return 语句,推断返回类型(委托到 gen.infer_return_type)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.infer_return_type(pool, body, param_types)
return None
def build_param_types_str(pool: memhub.MemBuddy | t.CPtr,
args_node: ast.AST | t.CPtr) -> str:
"""构建参数类型编码字符串(委托到 gen.build_param_types_str)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.build_param_types_str(pool, args_node)
return None
def _strappend(dst: str, dst_size: t.CSizeT, src: str):
"""将 src 追加到 dst 末尾(委托到 gen._strappend)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g._strappend(dst, dst_size, src)
-371
View File
@@ -1,371 +0,0 @@
import t, c
from stdint import *
import llvmlite
import memhub
import string
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesVar - 嵌套作用域符号表 + 变量管理(P6 对象化后的委托层)
#
# 使用 Scope 链(Parent 指针)管理嵌套作用域,
# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。
#
# 作用域类型:
# 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 方法签名引用)。
# ============================================================
# 作用域类型常量
SCOPE_MODULE: t.CDefine = 0
SCOPE_FUNCTION: t.CDefine = 1
SCOPE_BLOCK: t.CDefine = 2
# 每个作用域最大变量数
# 256 太小:NewAstTest main() 有 289 个局部变量,add_var 超限静默失败
# 导致变量未注册,后续使用报"未定义名称"(与 Gen/VarGenMixin 保持一致)。
MAX_VARS: t.CDefine = 1024
# ============================================================
# VarEntry - 变量表条目
# ============================================================
@t.NoVTable
class VarEntry:
"""变量表条目"""
Name: str
Alloca: llvmlite.Value | t.CPtr
Used: t.CInt
AnnotClassName: str # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
# ============================================================
# Scope - 作用域节点
#
# Parent 指向父作用域(None 表示根),
# Vars 是 VarEntry 数组,VarCount 是当前变量数。
# ============================================================
@t.NoVTable
class Scope:
"""作用域节点"""
Parent: Scope | t.CPtr
Vars: VarEntry | t.CPtr
VarCount: t.CInt
Kind: t.CInt
# ============================================================
# SymbolTable - 嵌套作用域符号表
#
# Root 是模块级根作用域,Current 是当前作用域。
# enter_scope/exit_scope 管理作用域栈。
# ============================================================
@t.NoVTable
class SymbolTable:
"""嵌套作用域符号表"""
Pool: memhub.MemBuddy | t.CPtr
Root: Scope | t.CPtr
Current: Scope | t.CPtr
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# P6 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# VarGenMixin 方法,避免函数体 import 包模块与 Generator
# 类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
# ============================================================
# ============================================================
# init_vars — 分配并清零 VarEntry 数组
# ============================================================
def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
"""分配并清零变量表数组(委托到 gen.init_vars)"""
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
# ============================================================
# find_var — 在变量表中按名称查找
# ============================================================
def find_var(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str) -> llvmlite.Value | t.CPtr:
"""在变量表中按名称查找(委托到 gen.find_var)"""
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
# ============================================================
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
# ============================================================
def find_var_entry(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str) -> VarEntry | t.CPtr:
"""在变量表中按名称查找,返回 VarEntry 或 None(委托到 gen.find_var_entry)"""
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
# ============================================================
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
# ============================================================
def lookup_var_entry(symtab: SymbolTable | t.CPtr,
name: str) -> VarEntry | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None(委托到 gen.lookup_var_entry)"""
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
# ============================================================
# set_var_annot_class_name — 设置变量的原始类型注解类名
#
# 在函数参数定义后调用,存储原始类型注解的类名。
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
# 通过 AnnotClassName 查找实际结构体类型。
# ============================================================
def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
name: str,
class_name: str) -> int:
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败(委托到 gen.set_var_annot_class_name)"""
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
# ============================================================
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
#
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
# ============================================================
def set_var_ptr_element(symtab: SymbolTable | t.CPtr,
name: str) -> int:
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败(委托到 gen.set_var_ptr_element)"""
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
# ============================================================
# add_var — 添加变量到变量表
# ============================================================
def add_var(vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""添加变量到变量表(委托到 gen.add_var)"""
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
# ============================================================
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
#
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
# 标准做法:所有 alloca 在函数入口块生成。
#
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
# ============================================================
def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr,
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
"""在函数入口块生成 alloca,返回 alloca 值(委托到 gen._alloca_at_entry)
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
确保所有 alloca 在入口块,避免支配性违规。
"""
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
# ============================================================
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
# ============================================================
def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
builder: llvmlite.IRBuilder | t.CPtr,
vars_ptr: VarEntry | t.CPtr,
var_count: int,
name: str,
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
"""查找或创建变量 alloca(委托到 gen.get_or_create_var)"""
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
# ============================================================
# _create_scope — 创建新作用域节点(内部辅助函数)
# ============================================================
def _create_scope(pool: memhub.MemBuddy | t.CPtr,
parent: Scope | t.CPtr,
kind: int) -> Scope | t.CPtr:
"""创建并初始化作用域节点(委托到 gen._create_scope)"""
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:
"""创建并初始化符号表,包含模块级根作用域(委托到 gen.init_symbol_table)"""
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
# ============================================================
# enter_scope — 进入新作用域
# ============================================================
def enter_scope(symtab: SymbolTable | t.CPtr,
kind: int) -> Scope | t.CPtr:
"""进入新作用域,返回新创建的作用域(委托到 gen.enter_scope)"""
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):
"""退出当前作用域,恢复到父作用域(委托到 gen.exit_scope)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
g.exit_scope(symtab)
# ============================================================
# define_var — 在当前作用域定义变量
# ============================================================
def define_var(symtab: SymbolTable | t.CPtr,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""在当前作用域定义变量,返回 0 成功(委托到 gen.define_var)"""
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
# ============================================================
# define_module_var — 在模块作用域定义变量
# ============================================================
def define_module_var(symtab: SymbolTable | t.CPtr,
name: str,
alloca: llvmlite.Value | t.CPtr) -> int:
"""在模块作用域定义变量,返回 0 成功(委托到 gen.define_module_var)"""
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
# ============================================================
# lookup_var — 从当前作用域逐级向上查找变量
# ============================================================
def lookup_var(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""从当前作用域逐级向上查找变量,返回 alloca 或 None(委托到 gen.lookup_var)"""
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
# ============================================================
# lookup_current — 仅在当前作用域查找变量
# ============================================================
def lookup_current(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""仅在当前作用域查找变量(委托到 gen.lookup_current)"""
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
# ============================================================
# lookup_module_var — 在模块作用域查找变量
# ============================================================
def lookup_module_var(symtab: SymbolTable | t.CPtr,
name: str) -> llvmlite.Value | t.CPtr:
"""在模块作用域查找变量(委托到 gen.lookup_module_var)"""
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
# ============================================================
# is_module_scope - 判断当前是否在模块级作用域
#
# 用于区分模块级代码和函数内代码:
# - 模块级代码:AnnAssign 应修改模块级变量(Python 语义)
# - 函数内代码:无 global 声明时 AnnAssign 应创建局部变量(Python 语义)
# ============================================================
def is_module_scope(symtab: SymbolTable | t.CPtr) -> int:
"""判断当前作用域是否为模块级作用域(Current == Root,委托到 gen.is_module_scope)
Returns: 1=模块级作用域, 0=函数内作用域
"""
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
# ============================================================
# get_or_create_sym — 查找或创建变量(在当前作用域)
# ============================================================
def get_or_create_sym(symtab: 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(在当前作用域,委托到 gen.get_or_create_sym)"""
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
-40
View File
@@ -1,40 +0,0 @@
import t, c
from stdint import *
import ast
import memhub
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Gen.Generator as Generator
# ============================================================
# HandlesWhile - while 循环语句处理(迁移完成,保留跨 Mixin 委托壳)
#
# P6 机械化迁移:WhileHandle 类 → StmtGenCifMixin.translate_while;
# 模块级辅助 _IsConstTrue/_NodeHasBreak/_StmtHasBreak → StmtGenCifMixin
# 方法(merge 可达性判定)。
# 分派中枢(StmtGenMixin)经本壳跨链调用(Viper @t.NoVTable 静态绑定下
# 跨 Mixin self. 调用 mangle 失败,须经模块级委托壳桥回 gen 单例)。
# 迁移收尾(编译器缺陷修复)后统一删除。
# ============================================================
# ============================================================
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
#
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
# 委托函数用本地 _g_gen(cast 成 Generator 类型)调
# StmtGenCifMixin 方法,避免函数体 import 包模块与类/模块名歧义。
# ============================================================
_g_gen: Generator.Generator | t.CPtr = None
# ============================================================
# translate_while - while 循环语句翻译(委托到 gen.translate_while)
# ============================================================
def translate_while(trans: HT.Translator | t.CPtr,
node: ast.AST | t.CPtr) -> int:
"""翻译 while 循环语句(委托到 gen.translate_while)"""
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.translate_while(trans, node)
return 0
+9 -23
View File
@@ -1,23 +1,9 @@
import t, c
from stdint import *
# Handles 模块(绝对导入,Viper 兼容)
# 参考 Python 版 TransPyC lib/core/Handles 的细粒度拆分
import lib.core.Handles.HandlesBase as HandlesBase
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.HandlesExprOps as HandlesExprOps
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesAssign as HandlesAssign
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
import lib.core.Handles.HandlesReturn as HandlesReturn
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesFunctions as HandlesFunctions
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.HandlesAugAssign as HandlesAugAssign
import lib.core.Handles.HandlesMain as HandlesMain
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import t, c
from stdint import *
# Handles 实体模块(去除委托层后保留:数据类/Translator/实体逻辑)
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.ExprCallTable as ExprCallTable
+41 -46
View File
@@ -1,46 +1,41 @@
import t, c
from stdint import *
import string
import stdlib
import memhub
import viperlib
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.IncludesScanner as IncludesScanner
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as GenGenerator
import lib.core.CompilerFactory as CompilerFactory
import lib.core.BuildPipeline as BuildPipeline
import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerStore as StubMergerStore
import lib.core.Handles.ExprCallCtor as ExprCallCtor
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小(1MB)
SRC_BUF_SIZE: t.CDefine = 1048576
# vpi 缓冲区大小(256KB)
PYI_BUF_SIZE: t.CSizeT = 262144
# 拓扑排序相关常量
MAX_CLASSES: t.CDefine = 512
MAX_FILE_DEPS: t.CDefine = 256
MAX_DEP_EDGES: t.CDefine = 16
SHA1_LEN: t.CDefine = 17
CLASS_NAME_LEN: t.CDefine = 64
import t, c
from stdint import *
import string
import stdlib
import memhub
import viperlib
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.IncludesScanner as IncludesScanner
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as GenGenerator
import lib.core.CompilerFactory as CompilerFactory
import lib.core.BuildPipeline as BuildPipeline
import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerStore as StubMergerStore
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小(1MB)
SRC_BUF_SIZE: t.CDefine = 1048576
# vpi 缓冲区大小(256KB)
PYI_BUF_SIZE: t.CSizeT = 262144
# 拓扑排序相关常量
MAX_CLASSES: t.CDefine = 512
MAX_FILE_DEPS: t.CDefine = 256
MAX_DEP_EDGES: t.CDefine = 16
SHA1_LEN: t.CDefine = 17
CLASS_NAME_LEN: t.CDefine = 64
+969 -973
View File
File diff suppressed because it is too large. Load diff
+501 -505
View File
File diff suppressed because it is too large. Load diff
+412 -417
View File
@@ -1,417 +1,412 @@
import t, c
from stdint import *
import string
import stdlib
import memhub
import viperlib
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesType as HandlesType
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesClassDef as HandlesClassDef
import lib.core.IncludesScanner as IncludesScanner
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as GenGenerator
import lib.core.CompilerFactory as CompilerFactory
import lib.core.BuildPipeline as BuildPipeline
import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerStore as StubMergerStore
import lib.core.Handles.ExprCallCtor as ExprCallCtor
import lib.core.Phase1Scan as Phase1Scan
import lib.core.Phase1Main as Phase1Main
import lib.core.Phase1 as Phase1
# ============================================================
# Phase1Topo - Phase1 拆分(阶段 E):Phase1Topo
#
# 直接移动模式:函数迁至此模块,原 Phase1.vp 仅保留常量/_mbuddy;
# 调用方经本模块前缀访问。全局符号经 Phase1._xxx 跨模块访问。
# ============================================================
# ============================================================
# _TopoSortFiles - 根据类继承关系对文件进行拓扑排序
#
# 算法(Kahn):
# 1. 从扁平类信息数组构建"文件 SHA1 → 依赖文件 SHA1 集合"映射
# 2. 计算每个文件的入度(依赖数量)
# 3. 入度为 0 的文件先处理,处理后减少依赖它的文件入度
# 4. 重复直到所有文件处理完成
#
# 注意:依赖方向是"父类所在文件 → 子类所在文件",
# 即父类文件必须先处理。Kahn 用 DepCount 作为剩余依赖计数,
# 依赖为 0 的先处理,初始化 InDegree = DepCount。
#
# Args:
# mb: 内存池
# result: IncludesScanner 扫描结果
# reachable_set: 可达 SHA1 集合
# reachable_count: 可达 SHA1 数量
# use_reachable: 是否使用可达集合过滤
# sha1_set: SHA1 集合
# set_count: SHA1 集合数量
# class_names_buf: 类名扁平数组
# parent_names_buf: 父类名扁平数组
# def_sha1s_buf: 定义 SHA1 扁平数组
# class_count: 类数量
# out_order: 输出拓扑顺序的文件索引数组(调用者分配,int 数组)
# out_count: 输出文件数量
#
# Returns:
# 0 成功,-1 失败
# ============================================================
def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr,
result: IncludesScanner.ScanResult | t.CPtr,
reachable_set: str, reachable_count: int,
use_reachable: int,
sha1_set: str, set_count: int,
class_names_buf: bytes, parent_names_buf: bytes,
def_sha1s_buf: bytes, class_count: int,
out_order: t.CPtr, out_count: t.CPtr,
temp_dir: str, td_len_ts: t.CSizeT) -> int:
"""根据类继承关系对文件进行拓扑排序"""
if result is None or out_order is None or out_count is None:
return -1
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
# 1. 分配扁平数组:文件 SHA1、依赖 SHA1 列表、依赖数量、入度、处理状态
# 用扁平数组代替 FileDepEntry 结构体,避免 str 指针字段 NULL 崩溃
file_sha1s_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
file_deps_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
file_dep_counts: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
file_indegrees: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None:
if file_sha1s_buf is not None:
mb.free(file_sha1s_buf)
if file_deps_buf is not None:
mb.free(file_deps_buf)
if file_dep_counts is not None:
mb.free(file_dep_counts)
if file_indegrees is not None:
mb.free(file_indegrees)
if file_processed is not None:
mb.free(file_processed)
return -1
string.memset(file_sha1s_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
string.memset(file_deps_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
string.memset(file_dep_counts, 0, Phase1.MAX_FILE_DEPS * 4)
string.memset(file_indegrees, 0, Phase1.MAX_FILE_DEPS * 4)
string.memset(file_processed, 0, Phase1.MAX_FILE_DEPS * 4)
file_count: int = 0
# sha1→file_index 映射(简单线性查找,文件数不多)
for i in range(result.Count):
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry is None or entry.Sha1 is None:
continue
sha1_e: str = entry.Sha1
in_set: int = 0
if use_reachable != 0:
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count)
else:
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count)
if in_set == 0:
continue
if file_count >= Phase1.MAX_FILE_DEPS:
break
# 初始化扁平数组:文件 SHA1(偏移 = file_count * Phase1.SHA1_LEN)
# DepCount/InDegree/Processed 已由 memset 清零
sha1_dst: str = file_sha1s_buf + file_count * Phase1.SHA1_LEN
string.strcpy(sha1_dst, sha1_e)
file_count += 1
# 2. 构建依赖边:对每个类,找到父类定义所在文件,建立 子文件→父文件 依赖
for ci in range(class_count):
# 读取父类名(偏移 = ci * Phase1.CLASS_NAME_LEN)
parent_ptr: str = parent_names_buf + ci * Phase1.CLASS_NAME_LEN
if parent_ptr[0] == '\0':
continue
# 读取子类定义 SHA1(偏移 = ci * Phase1.SHA1_LEN)
child_def_sha1: str = def_sha1s_buf + ci * Phase1.SHA1_LEN
# 查找父类定义所在文件的 SHA1
parent_sha1: str = Phase1Scan._FindClassDefSha1(class_names_buf, def_sha1s_buf, class_count, parent_ptr)
if parent_sha1 is None:
continue # 父类不在 includes 中(如 Object、CEnum 等标记基类)
# 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖)
if string.strcmp(parent_sha1, child_def_sha1) == 0:
continue
# 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表
for fi in range(file_count):
fsha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
if string.strcmp(fsha1, child_def_sha1) != 0:
continue
# 读取当前依赖数量
cnt_addr: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
cnt_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr, t.CPtr))
if cnt_ptr is None:
break
cur_cnt: int = cnt_ptr[0]
# 检查依赖是否已添加(去重)
already: int = 0
for di in range(cur_cnt):
dep_slot: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
if string.strcmp(dep_slot, parent_sha1) == 0:
already = 1
break
if already != 0:
break
if cur_cnt < Phase1.MAX_DEP_EDGES:
dep_dst: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt * Phase1.SHA1_LEN
string.strcpy(dep_dst, parent_sha1)
cnt_ptr[0] = cur_cnt + 1
break
# 2.5 补充 import 依赖边:被 import 的模块先完整翻译。
#
# 仅按类继承建边不够:跨模块全局变量 stub(lexer.vp from-import
# tokens.vp 的 _op_head)、跨模块 vtable TypeStr(astaux 继承 base 的
# AST)、泛型模板(base.vp 用 list[...])都要求依赖模块先翻译,而它们
# 之间可能无类继承关系。deps(_includes_deps_*)由 Phase 1a-pre 填充
# (含容器按需注入的 _list/_dict)。
#
# 用 _BuildIncludesSha1Map 复制局部 sha1→模块名 数组(与
# _BuildReachableSha1Set 的 BFS 一致),避免直接使用全局 store 返回值
# 跨函数传参(bytes|t.CPtr 联合转 str 参数)的地址异常。
sha1_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
mod_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
map_count_ts: int = 0
if sha1_arr_ts is not None and mod_arr_ts is not None:
map_count_ts = StubMergerIR._BuildIncludesSha1Map(
temp_dir, td_len_ts, sha1_arr_ts, mod_arr_ts)
for fi_imp in range(file_count):
if map_count_ts <= 0:
break
fsha1_imp: str = file_sha1s_buf + fi_imp * Phase1.SHA1_LEN
deps_imp: str = StubMergerStore.LookupIncludesDeps(fsha1_imp)
if deps_imp is None:
continue
dl_imp: t.CSizeT = string.strlen(deps_imp)
dpos_imp: t.CSizeT = 0
while dpos_imp < dl_imp:
dstart_imp: t.CSizeT = dpos_imp
while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ':
dpos_imp += 1
dlen_imp: t.CSizeT = dpos_imp - dstart_imp
if dpos_imp < dl_imp:
dpos_imp += 1
if dlen_imp == 0:
continue
dname_imp: bytes = stdlib.malloc(dlen_imp + 1)
if dname_imp is None:
continue
string.strncpy(dname_imp, deps_imp + dstart_imp, dlen_imp)
dname_imp[dlen_imp] = '\0'
dsha1_imp: str = StubMergerIR._FindSha1ByModName(
sha1_arr_ts, mod_arr_ts, map_count_ts, dname_imp)
stdlib.free(dname_imp)
if dsha1_imp is None:
continue
# 找依赖文件在列表中的索引(跳过自身)
for fj_imp in range(file_count):
if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0:
continue
if fj_imp == fi_imp:
break
# 去重 + 加边:fi_imp 依赖 fj_imp(InDegree[fi_imp]++)
cnt_addr_imp: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_imp * 4
cnt_ptr_imp: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_imp, t.CPtr))
if cnt_ptr_imp is None:
break
cur_cnt_imp: int = cnt_ptr_imp[0]
already_imp: int = 0
for di_imp in range(cur_cnt_imp):
dep_slot_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_imp * Phase1.SHA1_LEN
if string.strcmp(dep_slot_imp, dsha1_imp) == 0:
already_imp = 1
break
if already_imp == 0 and cur_cnt_imp < Phase1.MAX_DEP_EDGES:
dep_dst_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt_imp * Phase1.SHA1_LEN
string.strcpy(dep_dst_imp, dsha1_imp)
cnt_ptr_imp[0] = cur_cnt_imp + 1
break
# 释放 import 边用的局部映射数组
if sha1_arr_ts is not None:
stdlib.free(sha1_arr_ts)
if mod_arr_ts is not None:
stdlib.free(mod_arr_ts)
# 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件)
# 依赖为 0 的先处理,处理后减少依赖它的文件入度
for fi in range(file_count):
cnt_addr3: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
cnt_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr3, t.CPtr))
ind_addr3: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
ind_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr3, t.CPtr))
if cnt_ptr3 is not None and ind_ptr3 is not None:
ind_ptr3[0] = cnt_ptr3[0]
# 4. 拓扑排序输出
out_idx: int = 0
changed: int = 1
while changed != 0:
changed = 0
for fi in range(file_count):
# 检查处理状态
proc_addr4: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
proc_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr4, t.CPtr))
if proc_ptr4 is None or proc_ptr4[0] != 0:
continue
# 检查入度
ind_addr4: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
ind_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr4, t.CPtr))
if ind_ptr4 is None or ind_ptr4[0] > 0:
continue
# 入度为 0,可以处理
# 找到对应的 result.Entries 索引
target_sha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
for ri in range(result.Count):
ea_r: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
ent_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r, t.CPtr))
if ent_r is not None and ent_r.Sha1 is not None:
if string.strcmp(ent_r.Sha1, target_sha1) == 0:
# 写入输出索引数组
out_idx_addr: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
out_int_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr, t.CPtr))
if out_int_ptr is not None:
out_int_ptr[0] = ri
out_idx += 1
break
# 标记已处理
proc_ptr4[0] = 1
changed = 1
# 减少依赖该文件的其他文件的入度
for fj in range(file_count):
proc_addr5: t.CUInt64T = t.CUInt64T(file_processed) + fj * 4
proc_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr5, t.CPtr))
if proc_ptr5 is None or proc_ptr5[0] != 0:
continue
# 读取 fj 的依赖数量
cnt_addr5: t.CUInt64T = t.CUInt64T(file_dep_counts) + fj * 4
cnt_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr5, t.CPtr))
if cnt_ptr5 is None:
continue
fj_dep_cnt: int = cnt_ptr5[0]
for di in range(fj_dep_cnt):
dep_slot5: str = file_deps_buf + fj * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
if string.strcmp(dep_slot5, target_sha1) == 0:
ind_addr5: t.CUInt64T = t.CUInt64T(file_indegrees) + fj * 4
ind_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr5, t.CPtr))
if ind_ptr5 is not None:
ind_ptr5[0] = ind_ptr5[0] - 1
break
# 处理循环依赖:环内优先输出"被依赖者"(被其余剩余文件依赖数量多者先)。
#
# 背景:容器按需注入(string 用 list 泛型 → 依赖 _list)与真实 import
# (_list import string)形成伪环,Kahn 无法完全归零。若按扫描顺序追加,
# 依赖者(astaux)会先于被依赖者(base)翻译 → 跨模块 vtable TypeStr
# 未注册 → 误杀。被依赖者先翻译,其 stub/TypeStr/模板先就绪,依赖者
# 翻译时可引用(函数/全局声明由 1a-pre 的 vpi 兜底)。
if out_idx < file_count:
rem_idx: t.CPtr = stdlib.malloc(4 * file_count)
rem_depcnt: t.CPtr = stdlib.malloc(4 * file_count)
rem_count: int = 0
if rem_idx is not None and rem_depcnt is not None:
for fi in range(file_count):
proc_addr7: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
proc_ptr7: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr7, t.CPtr))
if proc_ptr7 is not None and proc_ptr7[0] == 0:
rem_idx[rem_count] = fi
rem_depcnt[rem_count] = 0
rem_count += 1
# 计算每个剩余文件的被依赖数(被其余剩余文件依赖)
for i_a in range(rem_count):
fi_a: int = rem_idx[i_a]
target_sha1_a: str = file_sha1s_buf + fi_a * Phase1.SHA1_LEN
for i_b in range(rem_count):
fi_b: int = rem_idx[i_b]
if fi_b == fi_a:
continue
cnt_addr_b: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_b * 4
cnt_ptr_b: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_b, t.CPtr))
if cnt_ptr_b is None:
continue
cnt_b: int = cnt_ptr_b[0]
for di_b in range(cnt_b):
dep_slot_b: str = file_deps_buf + fi_b * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_b * Phase1.SHA1_LEN
if string.strcmp(dep_slot_b, target_sha1_a) == 0:
rem_depcnt[i_a] = rem_depcnt[i_a] + 1
break
# 冒泡降序(被依赖数多者在前)
for i_a in range(rem_count):
for j_a in range(rem_count - 1):
if rem_depcnt[j_a] < rem_depcnt[j_a + 1]:
tmp_i: int = rem_idx[j_a]
rem_idx[j_a] = rem_idx[j_a + 1]
rem_idx[j_a + 1] = tmp_i
tmp_d: int = rem_depcnt[j_a]
rem_depcnt[j_a] = rem_depcnt[j_a + 1]
rem_depcnt[j_a + 1] = tmp_d
# 按序输出剩余文件
for i_a in range(rem_count):
fi_a2: int = rem_idx[i_a]
proc_addr8: t.CUInt64T = t.CUInt64T(file_processed) + fi_a2 * 4
proc_ptr8: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr8, t.CPtr))
if proc_ptr8 is None or proc_ptr8[0] != 0:
continue
target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN
for ri in range(result.Count):
ea_r2: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
ent_r2: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r2, t.CPtr))
if ent_r2 is not None and ent_r2.Sha1 is not None:
if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0:
out_idx_addr2: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
out_int_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr2, t.CPtr))
if out_int_ptr2 is not None:
out_int_ptr2[0] = ri
out_idx += 1
break
proc_ptr8[0] = 1
stdlib.free(rem_idx)
stdlib.free(rem_depcnt)
# 写入输出数量
out_count_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_count, t.CPtr))
if out_count_ptr is not None:
out_count_ptr[0] = out_idx
# 释放扁平数组
mb.free(file_sha1s_buf)
mb.free(file_deps_buf)
mb.free(file_dep_counts)
mb.free(file_indegrees)
mb.free(file_processed)
return 0
import t, c
from stdint import *
import string
import stdlib
import memhub
import viperlib
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import ast
import llvmlite
import lib.core.VLogger as VLogger
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.IncludesScanner as IncludesScanner
import lib.core.StubMerger as StubMerger
import lib.core.Gen.Generator as GenGenerator
import lib.core.CompilerFactory as CompilerFactory
import lib.core.BuildPipeline as BuildPipeline
import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerStore as StubMergerStore
import lib.core.Phase1Scan as Phase1Scan
import lib.core.Phase1Main as Phase1Main
import lib.core.Phase1 as Phase1
# ============================================================
# Phase1Topo - Phase1 拆分(阶段 E):Phase1Topo
#
# 直接移动模式:函数迁至此模块,原 Phase1.vp 仅保留常量/_mbuddy;
# 调用方经本模块前缀访问。全局符号经 Phase1._xxx 跨模块访问。
# ============================================================
# ============================================================
# _TopoSortFiles - 根据类继承关系对文件进行拓扑排序
#
# 算法(Kahn):
# 1. 从扁平类信息数组构建"文件 SHA1 → 依赖文件 SHA1 集合"映射
# 2. 计算每个文件的入度(依赖数量)
# 3. 入度为 0 的文件先处理,处理后减少依赖它的文件入度
# 4. 重复直到所有文件处理完成
#
# 注意:依赖方向是"父类所在文件 → 子类所在文件",
# 即父类文件必须先处理。Kahn 用 DepCount 作为剩余依赖计数,
# 依赖为 0 的先处理,初始化 InDegree = DepCount。
#
# Args:
# mb: 内存池
# result: IncludesScanner 扫描结果
# reachable_set: 可达 SHA1 集合
# reachable_count: 可达 SHA1 数量
# use_reachable: 是否使用可达集合过滤
# sha1_set: SHA1 集合
# set_count: SHA1 集合数量
# class_names_buf: 类名扁平数组
# parent_names_buf: 父类名扁平数组
# def_sha1s_buf: 定义 SHA1 扁平数组
# class_count: 类数量
# out_order: 输出拓扑顺序的文件索引数组(调用者分配,int 数组)
# out_count: 输出文件数量
#
# Returns:
# 0 成功,-1 失败
# ============================================================
def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr,
result: IncludesScanner.ScanResult | t.CPtr,
reachable_set: str, reachable_count: int,
use_reachable: int,
sha1_set: str, set_count: int,
class_names_buf: bytes, parent_names_buf: bytes,
def_sha1s_buf: bytes, class_count: int,
out_order: t.CPtr, out_count: t.CPtr,
temp_dir: str, td_len_ts: t.CSizeT) -> int:
"""根据类继承关系对文件进行拓扑排序"""
if result is None or out_order is None or out_count is None:
return -1
entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
# 1. 分配扁平数组:文件 SHA1、依赖 SHA1 列表、依赖数量、入度、处理状态
# 用扁平数组代替 FileDepEntry 结构体,避免 str 指针字段 NULL 崩溃
file_sha1s_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
file_deps_buf: bytes = mb.alloc(Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
file_dep_counts: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
file_indegrees: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
file_processed: t.CPtr = mb.alloc(Phase1.MAX_FILE_DEPS * 4)
if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None:
if file_sha1s_buf is not None:
mb.free(file_sha1s_buf)
if file_deps_buf is not None:
mb.free(file_deps_buf)
if file_dep_counts is not None:
mb.free(file_dep_counts)
if file_indegrees is not None:
mb.free(file_indegrees)
if file_processed is not None:
mb.free(file_processed)
return -1
string.memset(file_sha1s_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.SHA1_LEN)
string.memset(file_deps_buf, 0, Phase1.MAX_FILE_DEPS * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN)
string.memset(file_dep_counts, 0, Phase1.MAX_FILE_DEPS * 4)
string.memset(file_indegrees, 0, Phase1.MAX_FILE_DEPS * 4)
string.memset(file_processed, 0, Phase1.MAX_FILE_DEPS * 4)
file_count: int = 0
# sha1→file_index 映射(简单线性查找,文件数不多)
for i in range(result.Count):
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
if entry is None or entry.Sha1 is None:
continue
sha1_e: str = entry.Sha1
in_set: int = 0
if use_reachable != 0:
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, reachable_set, reachable_count)
else:
in_set = StubMergerCollect._is_in_sha1_set(sha1_e, sha1_set, set_count)
if in_set == 0:
continue
if file_count >= Phase1.MAX_FILE_DEPS:
break
# 初始化扁平数组:文件 SHA1(偏移 = file_count * Phase1.SHA1_LEN)
# DepCount/InDegree/Processed 已由 memset 清零
sha1_dst: str = file_sha1s_buf + file_count * Phase1.SHA1_LEN
string.strcpy(sha1_dst, sha1_e)
file_count += 1
# 2. 构建依赖边:对每个类,找到父类定义所在文件,建立 子文件→父文件 依赖
for ci in range(class_count):
# 读取父类名(偏移 = ci * Phase1.CLASS_NAME_LEN)
parent_ptr: str = parent_names_buf + ci * Phase1.CLASS_NAME_LEN
if parent_ptr[0] == '\0':
continue
# 读取子类定义 SHA1(偏移 = ci * Phase1.SHA1_LEN)
child_def_sha1: str = def_sha1s_buf + ci * Phase1.SHA1_LEN
# 查找父类定义所在文件的 SHA1
parent_sha1: str = Phase1Scan._FindClassDefSha1(class_names_buf, def_sha1s_buf, class_count, parent_ptr)
if parent_sha1 is None:
continue # 父类不在 includes 中(如 Object、CEnum 等标记基类)
# 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖)
if string.strcmp(parent_sha1, child_def_sha1) == 0:
continue
# 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表
for fi in range(file_count):
fsha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
if string.strcmp(fsha1, child_def_sha1) != 0:
continue
# 读取当前依赖数量
cnt_addr: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
cnt_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr, t.CPtr))
if cnt_ptr is None:
break
cur_cnt: int = cnt_ptr[0]
# 检查依赖是否已添加(去重)
already: int = 0
for di in range(cur_cnt):
dep_slot: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
if string.strcmp(dep_slot, parent_sha1) == 0:
already = 1
break
if already != 0:
break
if cur_cnt < Phase1.MAX_DEP_EDGES:
dep_dst: str = file_deps_buf + fi * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt * Phase1.SHA1_LEN
string.strcpy(dep_dst, parent_sha1)
cnt_ptr[0] = cur_cnt + 1
break
# 2.5 补充 import 依赖边:被 import 的模块先完整翻译。
#
# 仅按类继承建边不够:跨模块全局变量 stub(lexer.vp from-import
# tokens.vp 的 _op_head)、跨模块 vtable TypeStr(astaux 继承 base 的
# AST)、泛型模板(base.vp 用 list[...])都要求依赖模块先翻译,而它们
# 之间可能无类继承关系。deps(_includes_deps_*)由 Phase 1a-pre 填充
# (含容器按需注入的 _list/_dict)。
#
# 用 _BuildIncludesSha1Map 复制局部 sha1→模块名 数组(与
# _BuildReachableSha1Set 的 BFS 一致),避免直接使用全局 store 返回值
# 跨函数传参(bytes|t.CPtr 联合转 str 参数)的地址异常。
sha1_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
mod_arr_ts: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
map_count_ts: int = 0
if sha1_arr_ts is not None and mod_arr_ts is not None:
map_count_ts = StubMergerIR._BuildIncludesSha1Map(
temp_dir, td_len_ts, sha1_arr_ts, mod_arr_ts)
for fi_imp in range(file_count):
if map_count_ts <= 0:
break
fsha1_imp: str = file_sha1s_buf + fi_imp * Phase1.SHA1_LEN
deps_imp: str = StubMergerStore.LookupIncludesDeps(fsha1_imp)
if deps_imp is None:
continue
dl_imp: t.CSizeT = string.strlen(deps_imp)
dpos_imp: t.CSizeT = 0
while dpos_imp < dl_imp:
dstart_imp: t.CSizeT = dpos_imp
while dpos_imp < dl_imp and deps_imp[dpos_imp] != ' ':
dpos_imp += 1
dlen_imp: t.CSizeT = dpos_imp - dstart_imp
if dpos_imp < dl_imp:
dpos_imp += 1
if dlen_imp == 0:
continue
dname_imp: bytes = stdlib.malloc(dlen_imp + 1)
if dname_imp is None:
continue
string.strncpy(dname_imp, deps_imp + dstart_imp, dlen_imp)
dname_imp[dlen_imp] = '\0'
dsha1_imp: str = StubMergerIR._FindSha1ByModName(
sha1_arr_ts, mod_arr_ts, map_count_ts, dname_imp)
stdlib.free(dname_imp)
if dsha1_imp is None:
continue
# 找依赖文件在列表中的索引(跳过自身)
for fj_imp in range(file_count):
if string.strcmp(file_sha1s_buf + fj_imp * Phase1.SHA1_LEN, dsha1_imp) != 0:
continue
if fj_imp == fi_imp:
break
# 去重 + 加边:fi_imp 依赖 fj_imp(InDegree[fi_imp]++)
cnt_addr_imp: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_imp * 4
cnt_ptr_imp: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_imp, t.CPtr))
if cnt_ptr_imp is None:
break
cur_cnt_imp: int = cnt_ptr_imp[0]
already_imp: int = 0
for di_imp in range(cur_cnt_imp):
dep_slot_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_imp * Phase1.SHA1_LEN
if string.strcmp(dep_slot_imp, dsha1_imp) == 0:
already_imp = 1
break
if already_imp == 0 and cur_cnt_imp < Phase1.MAX_DEP_EDGES:
dep_dst_imp: str = file_deps_buf + fi_imp * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + cur_cnt_imp * Phase1.SHA1_LEN
string.strcpy(dep_dst_imp, dsha1_imp)
cnt_ptr_imp[0] = cur_cnt_imp + 1
break
# 释放 import 边用的局部映射数组
if sha1_arr_ts is not None:
stdlib.free(sha1_arr_ts)
if mod_arr_ts is not None:
stdlib.free(mod_arr_ts)
# 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件)
# 依赖为 0 的先处理,处理后减少依赖它的文件入度
for fi in range(file_count):
cnt_addr3: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4
cnt_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr3, t.CPtr))
ind_addr3: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
ind_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr3, t.CPtr))
if cnt_ptr3 is not None and ind_ptr3 is not None:
ind_ptr3[0] = cnt_ptr3[0]
# 4. 拓扑排序输出
out_idx: int = 0
changed: int = 1
while changed != 0:
changed = 0
for fi in range(file_count):
# 检查处理状态
proc_addr4: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
proc_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr4, t.CPtr))
if proc_ptr4 is None or proc_ptr4[0] != 0:
continue
# 检查入度
ind_addr4: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4
ind_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr4, t.CPtr))
if ind_ptr4 is None or ind_ptr4[0] > 0:
continue
# 入度为 0,可以处理
# 找到对应的 result.Entries 索引
target_sha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
for ri in range(result.Count):
ea_r: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
ent_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r, t.CPtr))
if ent_r is not None and ent_r.Sha1 is not None:
if string.strcmp(ent_r.Sha1, target_sha1) == 0:
# 写入输出索引数组
out_idx_addr: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
out_int_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr, t.CPtr))
if out_int_ptr is not None:
out_int_ptr[0] = ri
out_idx += 1
break
# 标记已处理
proc_ptr4[0] = 1
changed = 1
# 减少依赖该文件的其他文件的入度
for fj in range(file_count):
proc_addr5: t.CUInt64T = t.CUInt64T(file_processed) + fj * 4
proc_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr5, t.CPtr))
if proc_ptr5 is None or proc_ptr5[0] != 0:
continue
# 读取 fj 的依赖数量
cnt_addr5: t.CUInt64T = t.CUInt64T(file_dep_counts) + fj * 4
cnt_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr5, t.CPtr))
if cnt_ptr5 is None:
continue
fj_dep_cnt: int = cnt_ptr5[0]
for di in range(fj_dep_cnt):
dep_slot5: str = file_deps_buf + fj * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di * Phase1.SHA1_LEN
if string.strcmp(dep_slot5, target_sha1) == 0:
ind_addr5: t.CUInt64T = t.CUInt64T(file_indegrees) + fj * 4
ind_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr5, t.CPtr))
if ind_ptr5 is not None:
ind_ptr5[0] = ind_ptr5[0] - 1
break
# 处理循环依赖:环内优先输出"被依赖者"(被其余剩余文件依赖数量多者先)。
#
# 背景:容器按需注入(string 用 list 泛型 → 依赖 _list)与真实 import
# (_list import string)形成伪环,Kahn 无法完全归零。若按扫描顺序追加,
# 依赖者(astaux)会先于被依赖者(base)翻译 → 跨模块 vtable TypeStr
# 未注册 → 误杀。被依赖者先翻译,其 stub/TypeStr/模板先就绪,依赖者
# 翻译时可引用(函数/全局声明由 1a-pre 的 vpi 兜底)。
if out_idx < file_count:
rem_idx: t.CPtr = stdlib.malloc(4 * file_count)
rem_depcnt: t.CPtr = stdlib.malloc(4 * file_count)
rem_count: int = 0
if rem_idx is not None and rem_depcnt is not None:
for fi in range(file_count):
proc_addr7: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4
proc_ptr7: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr7, t.CPtr))
if proc_ptr7 is not None and proc_ptr7[0] == 0:
rem_idx[rem_count] = fi
rem_depcnt[rem_count] = 0
rem_count += 1
# 计算每个剩余文件的被依赖数(被其余剩余文件依赖)
for i_a in range(rem_count):
fi_a: int = rem_idx[i_a]
target_sha1_a: str = file_sha1s_buf + fi_a * Phase1.SHA1_LEN
for i_b in range(rem_count):
fi_b: int = rem_idx[i_b]
if fi_b == fi_a:
continue
cnt_addr_b: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi_b * 4
cnt_ptr_b: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr_b, t.CPtr))
if cnt_ptr_b is None:
continue
cnt_b: int = cnt_ptr_b[0]
for di_b in range(cnt_b):
dep_slot_b: str = file_deps_buf + fi_b * Phase1.MAX_DEP_EDGES * Phase1.SHA1_LEN + di_b * Phase1.SHA1_LEN
if string.strcmp(dep_slot_b, target_sha1_a) == 0:
rem_depcnt[i_a] = rem_depcnt[i_a] + 1
break
# 冒泡降序(被依赖数多者在前)
for i_a in range(rem_count):
for j_a in range(rem_count - 1):
if rem_depcnt[j_a] < rem_depcnt[j_a + 1]:
tmp_i: int = rem_idx[j_a]
rem_idx[j_a] = rem_idx[j_a + 1]
rem_idx[j_a + 1] = tmp_i
tmp_d: int = rem_depcnt[j_a]
rem_depcnt[j_a] = rem_depcnt[j_a + 1]
rem_depcnt[j_a + 1] = tmp_d
# 按序输出剩余文件
for i_a in range(rem_count):
fi_a2: int = rem_idx[i_a]
proc_addr8: t.CUInt64T = t.CUInt64T(file_processed) + fi_a2 * 4
proc_ptr8: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr8, t.CPtr))
if proc_ptr8 is None or proc_ptr8[0] != 0:
continue
target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN
for ri in range(result.Count):
ea_r2: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size
ent_r2: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r2, t.CPtr))
if ent_r2 is not None and ent_r2.Sha1 is not None:
if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0:
out_idx_addr2: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4
out_int_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr2, t.CPtr))
if out_int_ptr2 is not None:
out_int_ptr2[0] = ri
out_idx += 1
break
proc_ptr8[0] = 1
stdlib.free(rem_idx)
stdlib.free(rem_depcnt)
# 写入输出数量
out_count_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_count, t.CPtr))
if out_count_ptr is not None:
out_count_ptr[0] = out_idx
# 释放扁平数组
mb.free(file_sha1s_buf)
mb.free(file_deps_buf)
mb.free(file_dep_counts)
mb.free(file_indegrees)
mb.free(file_processed)
return 0
+1285 -1289
View File
File diff suppressed because it is too large. Load diff
+78 -80
View File
@@ -1,80 +1,78 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
# ============================================================
# StubMerger - stub 声明合并模块
#
# 从 temp 目录加载所有 .stub.ll 文件,将声明内容合并到主 IR。
# 这是 Phase2 的核心功能:翻译主文件时,将所有依赖的 stub
# 声明合并到主 IR 前面,使链接器能解析跨模块符号引用。
#
# 合并策略:
# 1. 扫描 temp 目录,收集所有 {sha1}.stub.ll 文件
# 2. 读取每个 stub 文件内容
# 3. 过滤去重(避免重复声明)
# 4. 将声明插入到主 IR 的 target triple 之后
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
# 最大 includes SHA1 数(用于过滤)
MAX_INCLUDES_SHA1: t.CDefine = 1024
# stub 读取缓冲区大小
STUB_READ_BUF_SIZE: t.CDefine = 1048576
# 最大 includes 条目数
MAX_INCLUDES: t.CDefine = 1024
# 可达性分析 worklist/processed 缓冲区大小(8192 不够:递归扫描 source_dir
# 后 worklist 含全部 App 文件 imports 的拼接 + BFS 依赖展开,追加82 溢出)
REACH_WORKLIST_BUF: t.CDefine = 65536
# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件)
# Phase1 扫描完成后填充,供所有函数使用
_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个)
_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个)
_sha1_store_incdir: bytes # 所属 includes 根目录数组(每个 512 字节,MAX_INCLUDES 个,多 includes 支持)
_sha1_store_count: int # 条目数
# includes 依赖内存存储(不依赖 deps.txt 过程文件)
# Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入此处
# _BuildReachableSha1Set 从此处读取依赖,不读 deps.txt
_includes_deps_sha1: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
_includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_INCLUDES 个)
_includes_deps_count: int # 条目数
# BuildCombinedIR 全目录扫描缓存:Phase B 对每个源文件调用一次 BuildCombinedIR,
# 每次 _collect_stub_sha1s 递归扫描 temp_dir 全部切片子目录(O(N×S) 目录枚举,
# 90 文件 × 全目录是 Phase B 慢的根因之一)。按 temp_dir 缓存扫描结果,
# 首次扫描后复用,temp_dir 变化时自动重建。
_stub_scan_cache_dir: str # 缓存对应的 temp_dir(None=未初始化)
_stub_scan_cache_arr: str # 扫描结果数组(每 17 字节一个 SHA1,MAX_INCLUDES_SHA1 个)
_stub_scan_cache_count: int # 收集数量
# 单条依赖字符串最大长度
MAX_DEPS_STR_LEN: t.CDefine = 512
# rel_path 最大长度
MAX_REL_PATH_LEN: t.CDefine = 256
# includes 根目录最大长度(绝对路径,多 includes 支持)
MAX_INC_DIR_LEN: t.CDefine = 512
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
# ============================================================
# StubMerger - stub 声明合并模块
#
# 从 temp 目录加载所有 .stub.ll 文件,将声明内容合并到主 IR。
# 这是 Phase2 的核心功能:翻译主文件时,将所有依赖的 stub
# 声明合并到主 IR 前面,使链接器能解析跨模块符号引用。
#
# 合并策略:
# 1. 扫描 temp 目录,收集所有 {sha1}.stub.ll 文件
# 2. 读取每个 stub 文件内容
# 3. 过滤去重(避免重复声明)
# 4. 将声明插入到主 IR 的 target triple 之后
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
# 最大 includes SHA1 数(用于过滤)
MAX_INCLUDES_SHA1: t.CDefine = 1024
# stub 读取缓冲区大小
STUB_READ_BUF_SIZE: t.CDefine = 1048576
# 最大 includes 条目数
MAX_INCLUDES: t.CDefine = 1024
# 可达性分析 worklist/processed 缓冲区大小(8192 不够:递归扫描 source_dir
# 后 worklist 含全部 App 文件 imports 的拼接 + BFS 依赖展开,追加82 溢出)
REACH_WORKLIST_BUF: t.CDefine = 65536
# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件)
# Phase1 扫描完成后填充,供所有函数使用
_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个)
_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个)
_sha1_store_incdir: bytes # 所属 includes 根目录数组(每个 512 字节,MAX_INCLUDES 个,多 includes 支持)
_sha1_store_count: int # 条目数
# includes 依赖内存存储(不依赖 deps.txt 过程文件)
# Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入此处
# _BuildReachableSha1Set 从此处读取依赖,不读 deps.txt
_includes_deps_sha1: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个)
_includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_INCLUDES 个)
_includes_deps_count: int # 条目数
# BuildCombinedIR 全目录扫描缓存:Phase B 对每个源文件调用一次 BuildCombinedIR,
# 每次 _collect_stub_sha1s 递归扫描 temp_dir 全部切片子目录(O(N×S) 目录枚举,
# 90 文件 × 全目录是 Phase B 慢的根因之一)。按 temp_dir 缓存扫描结果,
# 首次扫描后复用,temp_dir 变化时自动重建。
_stub_scan_cache_dir: str # 缓存对应的 temp_dir(None=未初始化)
_stub_scan_cache_arr: str # 扫描结果数组(每 17 字节一个 SHA1,MAX_INCLUDES_SHA1 个)
_stub_scan_cache_count: int # 收集数量
# 单条依赖字符串最大长度
MAX_DEPS_STR_LEN: t.CDefine = 512
# rel_path 最大长度
MAX_REL_PATH_LEN: t.CDefine = 256
# includes 根目录最大长度(绝对路径,多 includes 支持)
MAX_INC_DIR_LEN: t.CDefine = 512
File diff suppressed because it is too large. Load diff
+284 -286
View File
@@ -1,286 +1,284 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerCollect - StubMerger 拆分(阶段 E):StubMergerCollect
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# _sliced_path - 构建切片路径(stdlib.malloc 分配,调用者负责 free)
#
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
# level=0 → {temp_dir}/{sha1}.{ext}
# level=1 → {temp_dir}/b7/{sha1}.{ext}
# level=2 → {temp_dir}/b7/90/{sha1}.{ext}
#
# 自动调用 BuildPipeline.ensure_dir 创建子目录(level>0 时)。
#
# Args:
# temp_dir: 基础目录
# td_len: temp_dir 长度(避免重复 strlen)
# sha1: SHA1 字符串
# ext: 文件扩展名(如 "stub.ll")
#
# Returns:
# 完整路径(stdlib.malloc 分配,需 stdlib.free),None 失败
# ============================================================
def _sliced_path(temp_dir: str, td_len: t.CSizeT, sha1: str, ext: str) -> str:
"""构建切片路径(stdlib.malloc 分配,调用者负责 free)
level>0 时自动调用 ensure_dir 创建子目录。
"""
if temp_dir is None or sha1 is None or ext is None:
return None
sha1_len: t.CSizeT = string.strlen(sha1)
ext_len: t.CSizeT = string.strlen(ext)
# 子目录前缀:复用 Config.slice_subdir(SHA1 切片唯一权威实现,mbuddy 分配无需 free)
subdir_buf: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
sub_len: t.CSizeT = 0
if subdir_buf is not None:
sub_len = string.strlen(subdir_buf)
# 确保子目录存在: {temp_dir}/{subdir}
# 不创建目录会导致 fileio.File(MODE.W) 静默失败(file.closed==True),
# 进而 BuildCombinedIR 读不到文件返回 0("BuildCombinedIR 失败")。
dir_path_len: t.CSizeT = td_len + sub_len + 2
dir_path: bytes = stdlib.malloc(dir_path_len)
if dir_path is not None:
viperlib.snprintf(dir_path, dir_path_len, "%s/%s", temp_dir, subdir_buf)
BuildPipeline.ensure_dir(dir_path)
stdlib.free(dir_path)
# 构建完整路径
path: str = None
path_len: t.CSizeT = 0
if sub_len > 0:
path_len = td_len + sub_len + sha1_len + ext_len + 4
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
else:
path_len = td_len + sha1_len + ext_len + 3
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
return path
# ============================================================
# _collect_stub_sha1s - 递归扫描子目录,收集 .stub.ll 文件的 SHA1
#
# 根据 level 递归扫描子目录:
# level=0 → 扫描 {base_dir}/*.stub.ll,从文件名提取 SHA1
# level>0 → 扫描 {base_dir}/* 的子目录,对每个子目录递归调用
#
# Args:
# base_dir: 当前扫描目录
# bd_len: base_dir 长度
# level: 剩余递归层数
# out_arr: 输出数组(每个 SHA1 17 字节 = 16字符 + null)
# out_count: 当前已收集数量
# max_count: 最大数量
#
# Returns:
# 收集后的总数量
# ============================================================
def _collect_stub_sha1s(base_dir: str, bd_len: t.CSizeT, level: int,
out_arr: str, out_count: int, max_count: int) -> int:
"""递归扫描子目录,收集 .stub.ll 文件的 SHA1"""
if base_dir is None or out_arr is None:
return out_count
if out_count >= max_count:
return out_count
find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__())
if find_data is None:
return out_count
string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__())
if level <= 0:
# 扫描 {base_dir}/*.stub.ll
pattern: bytes = stdlib.malloc(bd_len + 16)
if pattern is None:
stdlib.free(find_data)
return out_count
viperlib.snprintf(pattern, bd_len + 16, "%s/*.stub.ll", base_dir)
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
stdlib.free(pattern)
if handle != win32base.INVALID_HANDLE_VALUE:
while 1:
if out_count >= max_count:
break
fname: str = find_data.cFileName
if fname is not None:
if fname[0] != '\0':
# 从文件名提取 SHA1(前 16 字符)
string.strncpy(out_arr + out_count * 17, fname, 16)
out_arr[out_count * 17 + 16] = '\0'
out_count += 1
if win32file.FindNextFileA(handle, find_data) == 0:
break
win32file.FindClose(handle)
else:
# 扫描 {base_dir}/* 的子目录
pattern = stdlib.malloc(bd_len + 4)
if pattern is None:
stdlib.free(find_data)
return out_count
viperlib.snprintf(pattern, bd_len + 4, "%s/*", base_dir)
handle = win32file.FindFirstFileA(pattern, find_data)
stdlib.free(pattern)
if handle != win32base.INVALID_HANDLE_VALUE:
while 1:
# 检查是否是目录(FILE_ATTRIBUTE_DIRECTORY = 0x10 = 16)
attrs: t.CUInt32T = find_data.dwFileAttributes
if(attrs & 16) != 0:
fname = find_data.cFileName
if fname is not None:
# 跳过 "." 和 ".."
is_dot: int = 0
if fname[0] == '.':
if fname[1] == '\0':
is_dot = 1
elif fname[1] == '.' and fname[2] == '\0':
is_dot = 1
if is_dot == 0:
# 构建子目录路径并递归扫描
sub_dir: str = Utils.JoinPath(base_dir, fname)
if sub_dir is not None:
sub_dir_len: t.CSizeT = string.strlen(sub_dir)
out_count = _collect_stub_sha1s(sub_dir, sub_dir_len, level - 1, out_arr, out_count, max_count)
stdlib.free(sub_dir)
if win32file.FindNextFileA(handle, find_data) == 0:
break
win32file.FindClose(handle)
stdlib.free(find_data)
return out_count
# ============================================================
# _load_includes_sha1_set - 从全局内存存储器收集 includes 的 SHA1
#
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。
# ============================================================
def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
temp_dir: str,
sha1_set: str) -> int:
"""从全局内存存储器将 includes 的 SHA1 写入 sha1_set
pool/temp_dir 参数保留以兼容现有调用者,但不再使用。
数据来源是 PopulateSha1MapStore 填充的全局存储器。
sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null)
返回找到的 includes SHA1 数量,-1 表示错误"""
if sha1_set is None:
return -1
if StubMerger._sha1_store_arr is None:
return -1
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES_SHA1:
break
idx: t.CSizeT = t.CSizeT(i) * 17
string.strcpy(sha1_set + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
count += 1
return count
# ============================================================
# _is_in_sha1_set - 检查 SHA1 是否在集合中
# ============================================================
def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
"""检查 sha1 是否在集合中"""
if sha1 is None or sha1_set is None:
return 0
for i in range(set_count):
if string.strcmp(sha1_set + i * 17, sha1) == 0:
return 1
return 0
# ============================================================
# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(人类可读输出)
#
# _sha1_map.txt 仅作为人类可读的调试输出,程序内部不读取此文件。
# 机器分析使用 PopulateSha1MapStore 填充的全局内存存储器。
#
# Args:
# mb: 内存池
# temp_dir: 临时目录(_sha1_map.txt 写入位置)
# scan_result: IncludesScanner 扫描结果
#
# Returns:
# 0 成功,非 0 失败
# ============================================================
def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
scan_result: IncludesScanner.ScanResult | t.CPtr,
filter_set: str,
filter_count: int) -> int:
"""将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器)
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
"""
if temp_dir is None or scan_result is None:
return 1
# 构造路径 temp_dir/_sha1_map.txt
dir_len: t.CSizeT = string.strlen(temp_dir)
map_path: bytes = stdlib.malloc(dir_len + 32)
if map_path is None:
return 1
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
# 打开文件写入(CREATE_ALWAYS)
f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.W)
if f.closed:
return 1
# 写入每个 include 条目: {sha1}:includes/{rel_path}\n
entry_size_w: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
line_buf: bytes = stdlib.malloc(512)
if line_buf is None:
f.close()
return 1
written_count: int = 0
for i in range(scan_result.Count):
ea_w: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_w
ent_w: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_w, t.CPtr))
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None:
continue
# 若提供过滤集合,只写入集合中的条目
if filter_set is not None and filter_count > 0:
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0:
continue
viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath)
line_len_w: t.CSizeT = string.strlen(line_buf)
f.write(line_buf, line_len_w)
written_count += 1
f.close()
return 0
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerCollect - StubMerger 拆分(阶段 E):StubMergerCollect
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# _sliced_path - 构建切片路径(stdlib.malloc 分配,调用者负责 free)
#
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
# level=0 → {temp_dir}/{sha1}.{ext}
# level=1 → {temp_dir}/b7/{sha1}.{ext}
# level=2 → {temp_dir}/b7/90/{sha1}.{ext}
#
# 自动调用 BuildPipeline.ensure_dir 创建子目录(level>0 时)。
#
# Args:
# temp_dir: 基础目录
# td_len: temp_dir 长度(避免重复 strlen)
# sha1: SHA1 字符串
# ext: 文件扩展名(如 "stub.ll")
#
# Returns:
# 完整路径(stdlib.malloc 分配,需 stdlib.free),None 失败
# ============================================================
def _sliced_path(temp_dir: str, td_len: t.CSizeT, sha1: str, ext: str) -> str:
"""构建切片路径(stdlib.malloc 分配,调用者负责 free)
level>0 时自动调用 ensure_dir 创建子目录。
"""
if temp_dir is None or sha1 is None or ext is None:
return None
sha1_len: t.CSizeT = string.strlen(sha1)
ext_len: t.CSizeT = string.strlen(ext)
# 子目录前缀:复用 Config.slice_subdir(SHA1 切片唯一权威实现,mbuddy 分配无需 free)
subdir_buf: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
sub_len: t.CSizeT = 0
if subdir_buf is not None:
sub_len = string.strlen(subdir_buf)
# 确保子目录存在: {temp_dir}/{subdir}
# 不创建目录会导致 fileio.File(MODE.W) 静默失败(file.closed==True),
# 进而 BuildCombinedIR 读不到文件返回 0("BuildCombinedIR 失败")。
dir_path_len: t.CSizeT = td_len + sub_len + 2
dir_path: bytes = stdlib.malloc(dir_path_len)
if dir_path is not None:
viperlib.snprintf(dir_path, dir_path_len, "%s/%s", temp_dir, subdir_buf)
BuildPipeline.ensure_dir(dir_path)
stdlib.free(dir_path)
# 构建完整路径
path: str = None
path_len: t.CSizeT = 0
if sub_len > 0:
path_len = td_len + sub_len + sha1_len + ext_len + 4
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
else:
path_len = td_len + sha1_len + ext_len + 3
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
return path
# ============================================================
# _collect_stub_sha1s - 递归扫描子目录,收集 .stub.ll 文件的 SHA1
#
# 根据 level 递归扫描子目录:
# level=0 → 扫描 {base_dir}/*.stub.ll,从文件名提取 SHA1
# level>0 → 扫描 {base_dir}/* 的子目录,对每个子目录递归调用
#
# Args:
# base_dir: 当前扫描目录
# bd_len: base_dir 长度
# level: 剩余递归层数
# out_arr: 输出数组(每个 SHA1 17 字节 = 16字符 + null)
# out_count: 当前已收集数量
# max_count: 最大数量
#
# Returns:
# 收集后的总数量
# ============================================================
def _collect_stub_sha1s(base_dir: str, bd_len: t.CSizeT, level: int,
out_arr: str, out_count: int, max_count: int) -> int:
"""递归扫描子目录,收集 .stub.ll 文件的 SHA1"""
if base_dir is None or out_arr is None:
return out_count
if out_count >= max_count:
return out_count
find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__())
if find_data is None:
return out_count
string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__())
if level <= 0:
# 扫描 {base_dir}/*.stub.ll
pattern: bytes = stdlib.malloc(bd_len + 16)
if pattern is None:
stdlib.free(find_data)
return out_count
viperlib.snprintf(pattern, bd_len + 16, "%s/*.stub.ll", base_dir)
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
stdlib.free(pattern)
if handle != win32base.INVALID_HANDLE_VALUE:
while 1:
if out_count >= max_count:
break
fname: str = find_data.cFileName
if fname is not None:
if fname[0] != '\0':
# 从文件名提取 SHA1(前 16 字符)
string.strncpy(out_arr + out_count * 17, fname, 16)
out_arr[out_count * 17 + 16] = '\0'
out_count += 1
if win32file.FindNextFileA(handle, find_data) == 0:
break
win32file.FindClose(handle)
else:
# 扫描 {base_dir}/* 的子目录
pattern = stdlib.malloc(bd_len + 4)
if pattern is None:
stdlib.free(find_data)
return out_count
viperlib.snprintf(pattern, bd_len + 4, "%s/*", base_dir)
handle = win32file.FindFirstFileA(pattern, find_data)
stdlib.free(pattern)
if handle != win32base.INVALID_HANDLE_VALUE:
while 1:
# 检查是否是目录(FILE_ATTRIBUTE_DIRECTORY = 0x10 = 16)
attrs: t.CUInt32T = find_data.dwFileAttributes
if(attrs & 16) != 0:
fname = find_data.cFileName
if fname is not None:
# 跳过 "." 和 ".."
is_dot: int = 0
if fname[0] == '.':
if fname[1] == '\0':
is_dot = 1
elif fname[1] == '.' and fname[2] == '\0':
is_dot = 1
if is_dot == 0:
# 构建子目录路径并递归扫描
sub_dir: str = Utils.JoinPath(base_dir, fname)
if sub_dir is not None:
sub_dir_len: t.CSizeT = string.strlen(sub_dir)
out_count = _collect_stub_sha1s(sub_dir, sub_dir_len, level - 1, out_arr, out_count, max_count)
stdlib.free(sub_dir)
if win32file.FindNextFileA(handle, find_data) == 0:
break
win32file.FindClose(handle)
stdlib.free(find_data)
return out_count
# ============================================================
# _load_includes_sha1_set - 从全局内存存储器收集 includes 的 SHA1
#
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。
# ============================================================
def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
temp_dir: str,
sha1_set: str) -> int:
"""从全局内存存储器将 includes 的 SHA1 写入 sha1_set
pool/temp_dir 参数保留以兼容现有调用者,但不再使用。
数据来源是 PopulateSha1MapStore 填充的全局存储器。
sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null)
返回找到的 includes SHA1 数量,-1 表示错误"""
if sha1_set is None:
return -1
if StubMerger._sha1_store_arr is None:
return -1
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES_SHA1:
break
idx: t.CSizeT = t.CSizeT(i) * 17
string.strcpy(sha1_set + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
count += 1
return count
# ============================================================
# _is_in_sha1_set - 检查 SHA1 是否在集合中
# ============================================================
def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
"""检查 sha1 是否在集合中"""
if sha1 is None or sha1_set is None:
return 0
for i in range(set_count):
if string.strcmp(sha1_set + i * 17, sha1) == 0:
return 1
return 0
# ============================================================
# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(人类可读输出)
#
# _sha1_map.txt 仅作为人类可读的调试输出,程序内部不读取此文件。
# 机器分析使用 PopulateSha1MapStore 填充的全局内存存储器。
#
# Args:
# mb: 内存池
# temp_dir: 临时目录(_sha1_map.txt 写入位置)
# scan_result: IncludesScanner 扫描结果
#
# Returns:
# 0 成功,非 0 失败
# ============================================================
def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
scan_result: IncludesScanner.ScanResult | t.CPtr,
filter_set: str,
filter_count: int) -> int:
"""将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器)
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
"""
if temp_dir is None or scan_result is None:
return 1
# 构造路径 temp_dir/_sha1_map.txt
dir_len: t.CSizeT = string.strlen(temp_dir)
map_path: bytes = stdlib.malloc(dir_len + 32)
if map_path is None:
return 1
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
# 打开文件写入(CREATE_ALWAYS)
f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.W)
if f.closed:
return 1
# 写入每个 include 条目: {sha1}:includes/{rel_path}\n
entry_size_w: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
line_buf: bytes = stdlib.malloc(512)
if line_buf is None:
f.close()
return 1
written_count: int = 0
for i in range(scan_result.Count):
ea_w: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_w
ent_w: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_w, t.CPtr))
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None:
continue
# 若提供过滤集合,只写入集合中的条目
if filter_set is not None and filter_count > 0:
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0:
continue
viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath)
line_len_w: t.CSizeT = string.strlen(line_buf)
f.write(line_buf, line_len_w)
written_count += 1
f.close()
return 0
+415 -416
View File
@@ -1,416 +1,415 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerIR - StubMerger 拆分(阶段 E):StubMergerIR
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# IsDeclOnlyModule - 判断模块是否为纯声明文件
#
# 读取 {temp_dir}/{sha1}.text.ll,扫描是否含 "define " 行:
# 返回 1 = 纯声明(无函数体,如 stdio.vp 全 pass),无需 .obj
# 返回 0 = 实现文件(含 define 函数体)
# 返回 -1 = text.ll 不存在/无法判断
#
# 与 Phase B+(Phase2.vp 编译缺失 includes 时)的内联判断逻辑一致,
# 供 Phase C 链接时区分"声明文件无需 .obj"与"实现文件缺失"。
# ============================================================
def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
"""判断模块是否为纯声明文件(text.ll 无 define 行)"""
if temp_dir is None or sha1 is None:
return -1
tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll")
if tpath is None:
return -1
tf_d: fileio.File | t.CPtr = fileio.File(tpath, fileio.MODE.R)
stdlib.free(tpath)
if tf_d.closed:
return -1
tbuf_d: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
tbr_d: t.CInt64T = 0
if tbuf_d is not None:
tbr_d = tf_d.read_all(tbuf_d, STUB_READ_BUF_SIZE)
tf_d.close()
if tbuf_d is None:
return -1
if tbr_d <= 0:
# 空 text.ll:无函数体,纯声明
stdlib.free(tbuf_d)
return 1
if tbr_d < STUB_READ_BUF_SIZE:
tbuf_d[tbr_d] = '\0'
else:
tbuf_d[STUB_READ_BUF_SIZE - 1] = '\0'
# 逐行扫描:找 "define " 行即为实现文件
tpos_d: t.CSizeT = 0
while tpos_d < tbr_d:
tls_d: t.CSizeT = tpos_d
while tpos_d < tbr_d:
if tbuf_d[tpos_d] == '\n':
break
tpos_d += 1
tll_d: t.CSizeT = tpos_d - tls_d
if tpos_d < tbr_d:
tpos_d += 1
if tll_d >= 7 and string.strncmp(tbuf_d + tls_d, "define ", 7) == 0:
stdlib.free(tbuf_d)
return 0
stdlib.free(tbuf_d)
return 1
# ============================================================
# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define
#
# 逐字节strncmp搜索 func_sig(如 @"sha1.func"(/ @printf( ),每次
# 找到匹配后检查行首是否以 "declare " 或 "define " 开头,跳过 call 语句。
# 避免 strstr 子串匹配误匹配 call ... @"func"(...) 中的 @"func"( 子串。
#
# Args:
# out_buf: 已有的 IR 文本缓冲区
# func_sig: 函数签名片段,如 @"sha1.func"(/ @printf(
#
# Returns:
# 1=已存在 declare/define, 0=不存在
# ============================================================
def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int:
"""检查 out_buf 中是否已有函数的 declare 或 define 行"""
if out_buf is None or func_sig is None:
return 0
sig_len: t.CSizeT = string.strlen(func_sig)
out_len: t.CSizeT = string.strlen(out_buf)
if sig_len == 0 or out_len == 0 or sig_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + sig_len <= out_len:
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
ls: t.CSizeT = pos
while ls > 0 and out_buf[ls - 1] != '\n':
ls -= 1
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
return 1
if string.strncmp(out_buf + ls, "define ", 7) == 0:
return 1
pos += 1
return 0
# ============================================================
# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉
#
# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖
# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';'
# 使其成为注释,然后追加 define 行。
# ============================================================
def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int:
"""在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉"""
if out_buf is None or func_sig is None:
return 0
sig_len: t.CSizeT = string.strlen(func_sig)
out_len: t.CSizeT = string.strlen(out_buf)
if sig_len == 0 or out_len == 0 or sig_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + sig_len <= out_len:
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
ls: t.CSizeT = pos
while ls > 0 and out_buf[ls - 1] != '\n':
ls -= 1
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
out_buf[ls] = ';'
return 1
pos += 1
return 0
# ============================================================
# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉
#
# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明
# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。
# ============================================================
def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int:
"""在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';'
注释掉**所有**匹配行(而非仅第一个):跨模块同名裸全局(如 main.vp 与
argparse.vp 都声明 StubMerger._mbuddy)时,本地 stub external + 依赖 stub external +
依赖 text 定义会同时存在。只注释第一个会导致依赖 text 的定义残留 →
合成 IR 重复定义 → llc "redefinition of global '@StubMerger._mbuddy'"(ArgparseTest
回归根因)。"以 text 中定义为准"的语义:后追加者注释掉全部旧行,最终
只保留最后一个定义。
"""
if out_buf is None or global_name is None:
return 0
name_len: t.CSizeT = string.strlen(global_name)
out_len: t.CSizeT = string.strlen(out_buf)
if name_len == 0 or out_len == 0 or name_len > out_len:
return 0
pos: t.CSizeT = 0
commented: int = 0
while pos + name_len <= out_len:
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
out_buf[pos] = ';'
commented = 1
pos += 1
return commented
def _HasGlobalInBuf(out_buf: bytes, global_name: str) -> int:
"""检测 out_buf 中是否已有同名全局变量行(行首匹配,未注释)
用于跳过重复追加依赖全局强定义:stub 注入已提供 external 声明,
依赖 text.ll 的强定义只需在定义模块存在一份,复制进每个依赖方
会导致 ld.lld duplicate symbol(如 _op_head、MemBuddy.vtable)。
"""
if out_buf is None or global_name is None:
return 0
name_len: t.CSizeT = string.strlen(global_name)
out_len: t.CSizeT = string.strlen(out_buf)
if name_len == 0 or out_len == 0 or name_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + name_len <= out_len:
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
return 1
pos += 1
return 0
# ============================================================
# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉
#
# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明
#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义
#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明
# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。
# ============================================================
def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int:
"""在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';'
type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容)
返回 1=已注释, 0=未找到
"""
if out_buf is None or type_name_prefix is None:
return 0
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
out_len: t.CSizeT = string.strlen(out_buf)
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + prefix_len <= out_len:
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
# 检查后面是否是 " = type opaque"
p: t.CSizeT = pos + prefix_len
# 跳过空格
while p < out_len and out_buf[p] == ' ':
p += 1
if p < out_len and out_buf[p] == '=':
p += 1
while p < out_len and out_buf[p] == ' ':
p += 1
if p + 11 <= out_len:
if string.strncmp(out_buf + p, "type opaque", 11) == 0:
# 找到 opaque 声明,将行首改为 ';'
out_buf[pos] = ';'
return 1
pos += 1
return 0
# ============================================================
# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块
#
# deps.txt 只记录直接导入的模块名(如 "ast"),但包的 __init__.vp
# 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer 子模块类型。
# 当模块名包含 '.' 时,检查其顶层包名是否在 deps_buf 中。
#
# 例如:
# deps_buf = "ast stdio string"
# mod_name = "ast.lexer" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
# mod_name = "ast.token" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
# mod_name = "foo.bar" → 顶层包 "foo" 不在 deps_buf 中 → 返回 0
# ============================================================
def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
"""检查 mod_name 是否是 deps_buf 中已导入包的子模块"""
if deps_buf is None or mod_name is None:
return 0
# 查找第一个 '.',提取顶层包名
dot_pos: str = string.strchr(mod_name, 46) # '.' = 46
if dot_pos is None:
return 0
pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_pos) - t.CUInt64T(mod_name))
if pkg_len == 0 or pkg_len >= 256:
return 0
# 构造顶层包名(截断到 '.' 之前)
# 直接在 mod_name 上临时截断检查,避免分配
saved_ch: t.CChar = mod_name[pkg_len]
mod_name[pkg_len] = '\0'
result: int = HandlesImports.is_module_imported(deps_buf, mod_name)
mod_name[pkg_len] = saved_ch
return result
# ============================================================
# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque)
#
# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=')
# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } >
# 返回 1=已有完整定义, 0=无完整定义
# ============================================================
def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int:
"""检查 out_buf 中是否已有 type_name_prefix 的完整定义"""
if out_buf is None or type_name_prefix is None:
return 0
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
out_len: t.CSizeT = string.strlen(out_buf)
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + prefix_len <= out_len:
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
# 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';')
is_line_start: int = 0
if pos == 0:
is_line_start = 1
elif out_buf[pos - 1] == '\n':
is_line_start = 1
if is_line_start == 1:
# 检查后面是否是 " = type {" 或 " = type <"
p: t.CSizeT = pos + prefix_len
while p < out_len and out_buf[p] == ' ':
p += 1
if p < out_len and out_buf[p] == '=':
p += 1
while p < out_len and out_buf[p] == ' ':
p += 1
if p + 5 < out_len:
if string.strncmp(out_buf + p, "type ", 5) == 0:
p += 5
if p < out_len:
if out_buf[p] == '{' or out_buf[p] == '<':
return 1
pos += 1
return 0
# ============================================================
# _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射
#
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。
# 所有内存由 stdlib.malloc 分配,调用者负责释放。
# ============================================================
def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
sha1_list: str,
mod_list: str) -> int:
"""从全局内存存储器复制 sha1→module_name 映射到调用者数组
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
数据来源是 PopulateSha1MapStore 填充的全局存储器。
"""
if sha1_list is None or mod_list is None:
return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return 0
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES:
break
idx: t.CSizeT = t.CSizeT(i) * 17
idx2: t.CSizeT = t.CSizeT(i) * 64
string.strcpy(sha1_list + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
string.strcpy(mod_list + t.CSizeT(count) * 64, StubMerger._sha1_store_mod + idx2)
count += 1
return count
# ============================================================
# _FindSha1ByModName - 从模块名查找 SHA1(精确匹配)
#
# 在 sha1_arr/mod_arr 映射中查找模块名对应的 SHA1。
# 用于依赖图分析:模块名 → SHA1。
#
# Args:
# sha1_arr: SHA1 数组(每个 17 字节)
# mod_arr: 模块名数组(每个 64 字节)
# count: 映射条目数
# mod_name: 要查找的模块名
#
# Returns:
# SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None
# ============================================================
def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
count: int, mod_name: str) -> str:
"""从模块名查找 SHA1(精确匹配 + 包名回退)
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
"""
if sha1_arr is None or mod_arr is None or mod_name is None:
return None
if count <= 0:
return None
# 第一遍:精确匹配
for i in range(count):
idx: t.CSizeT = t.CSizeT(i) * 64
if string.strcmp(mod_arr + idx, mod_name) == 0:
sidx: t.CSizeT = t.CSizeT(i) * 17
return sha1_arr + sidx
# 第二遍:包名回退("ast" → "ast.__init__")
nm_len: t.CSizeT = string.strlen(mod_name)
init_buf: bytes = stdlib.malloc(nm_len + 12)
if init_buf is not None:
viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name)
for i in range(count):
idx2: t.CSizeT = t.CSizeT(i) * 64
if string.strcmp(mod_arr + idx2, init_buf) == 0:
sidx2: t.CSizeT = t.CSizeT(i) * 17
stdlib.free(init_buf)
return sha1_arr + sidx2
stdlib.free(init_buf)
return None
# ============================================================
# _AddSha1ToSet - 将 SHA1 加入集合(去重)
#
# 检查 SHA1 是否已在集合中,若不在则加入。返回新的 count。
#
# Args:
# set_buf: SHA1 集合缓冲区(每个 17 字节)
# count: 当前集合中的 SHA1 数量
# sha1: 要加入的 SHA1
#
# Returns:
# 新的 count(如果已存在则不变)
# ============================================================
def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
"""将 SHA1 加入集合,返回新 count"""
if set_buf is None or sha1 is None:
return count
for i in range(count):
idx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(set_buf + idx, sha1) == 0:
return count
if count < MAX_INCLUDES_SHA1:
idx: t.CSizeT = t.CSizeT(count) * 17
string.strcpy(set_buf + idx, sha1)
return count + 1
return count
import lib.core.Gen.GenApi as GenApi
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerIR - StubMerger 拆分(阶段 E):StubMergerIR
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# IsDeclOnlyModule - 判断模块是否为纯声明文件
#
# 读取 {temp_dir}/{sha1}.text.ll,扫描是否含 "define " 行:
# 返回 1 = 纯声明(无函数体,如 stdio.vp 全 pass),无需 .obj
# 返回 0 = 实现文件(含 define 函数体)
# 返回 -1 = text.ll 不存在/无法判断
#
# 与 Phase B+(Phase2.vp 编译缺失 includes 时)的内联判断逻辑一致,
# 供 Phase C 链接时区分"声明文件无需 .obj"与"实现文件缺失"。
# ============================================================
def IsDeclOnlyModule(temp_dir: str, td_len: t.CSizeT, sha1: str) -> int:
"""判断模块是否为纯声明文件(text.ll 无 define 行)"""
if temp_dir is None or sha1 is None:
return -1
tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll")
if tpath is None:
return -1
tf_d: fileio.File | t.CPtr = fileio.File(tpath, fileio.MODE.R)
stdlib.free(tpath)
if tf_d.closed:
return -1
tbuf_d: bytes = stdlib.malloc(STUB_READ_BUF_SIZE)
tbr_d: t.CInt64T = 0
if tbuf_d is not None:
tbr_d = tf_d.read_all(tbuf_d, STUB_READ_BUF_SIZE)
tf_d.close()
if tbuf_d is None:
return -1
if tbr_d <= 0:
# 空 text.ll:无函数体,纯声明
stdlib.free(tbuf_d)
return 1
if tbr_d < STUB_READ_BUF_SIZE:
tbuf_d[tbr_d] = '\0'
else:
tbuf_d[STUB_READ_BUF_SIZE - 1] = '\0'
# 逐行扫描:找 "define " 行即为实现文件
tpos_d: t.CSizeT = 0
while tpos_d < tbr_d:
tls_d: t.CSizeT = tpos_d
while tpos_d < tbr_d:
if tbuf_d[tpos_d] == '\n':
break
tpos_d += 1
tll_d: t.CSizeT = tpos_d - tls_d
if tpos_d < tbr_d:
tpos_d += 1
if tll_d >= 7 and string.strncmp(tbuf_d + tls_d, "define ", 7) == 0:
stdlib.free(tbuf_d)
return 0
stdlib.free(tbuf_d)
return 1
# ============================================================
# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define
#
# 逐字节strncmp搜索 func_sig(如 @"sha1.func"(/ @printf( ),每次
# 找到匹配后检查行首是否以 "declare " 或 "define " 开头,跳过 call 语句。
# 避免 strstr 子串匹配误匹配 call ... @"func"(...) 中的 @"func"( 子串。
#
# Args:
# out_buf: 已有的 IR 文本缓冲区
# func_sig: 函数签名片段,如 @"sha1.func"(/ @printf(
#
# Returns:
# 1=已存在 declare/define, 0=不存在
# ============================================================
def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int:
"""检查 out_buf 中是否已有函数的 declare 或 define 行"""
if out_buf is None or func_sig is None:
return 0
sig_len: t.CSizeT = string.strlen(func_sig)
out_len: t.CSizeT = string.strlen(out_buf)
if sig_len == 0 or out_len == 0 or sig_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + sig_len <= out_len:
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
ls: t.CSizeT = pos
while ls > 0 and out_buf[ls - 1] != '\n':
ls -= 1
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
return 1
if string.strncmp(out_buf + ls, "define ", 7) == 0:
return 1
pos += 1
return 0
# ============================================================
# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉
#
# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖
# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';'
# 使其成为注释,然后追加 define 行。
# ============================================================
def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int:
"""在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉"""
if out_buf is None or func_sig is None:
return 0
sig_len: t.CSizeT = string.strlen(func_sig)
out_len: t.CSizeT = string.strlen(out_buf)
if sig_len == 0 or out_len == 0 or sig_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + sig_len <= out_len:
if string.strncmp(out_buf + pos, func_sig, sig_len) == 0:
ls: t.CSizeT = pos
while ls > 0 and out_buf[ls - 1] != '\n':
ls -= 1
if string.strncmp(out_buf + ls, "declare ", 8) == 0:
out_buf[ls] = ';'
return 1
pos += 1
return 0
# ============================================================
# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉
#
# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明
# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。
# ============================================================
def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int:
"""在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';'
注释掉**所有**匹配行(而非仅第一个):跨模块同名裸全局(如 main.vp 与
argparse.vp 都声明 StubMerger._mbuddy)时,本地 stub external + 依赖 stub external +
依赖 text 定义会同时存在。只注释第一个会导致依赖 text 的定义残留 →
合成 IR 重复定义 → llc "redefinition of global '@StubMerger._mbuddy'"(ArgparseTest
回归根因)。"以 text 中定义为准"的语义:后追加者注释掉全部旧行,最终
只保留最后一个定义。
"""
if out_buf is None or global_name is None:
return 0
name_len: t.CSizeT = string.strlen(global_name)
out_len: t.CSizeT = string.strlen(out_buf)
if name_len == 0 or out_len == 0 or name_len > out_len:
return 0
pos: t.CSizeT = 0
commented: int = 0
while pos + name_len <= out_len:
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
out_buf[pos] = ';'
commented = 1
pos += 1
return commented
def _HasGlobalInBuf(out_buf: bytes, global_name: str) -> int:
"""检测 out_buf 中是否已有同名全局变量行(行首匹配,未注释)
用于跳过重复追加依赖全局强定义:stub 注入已提供 external 声明,
依赖 text.ll 的强定义只需在定义模块存在一份,复制进每个依赖方
会导致 ld.lld duplicate symbol(如 _op_head、MemBuddy.vtable)。
"""
if out_buf is None or global_name is None:
return 0
name_len: t.CSizeT = string.strlen(global_name)
out_len: t.CSizeT = string.strlen(out_buf)
if name_len == 0 or out_len == 0 or name_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + name_len <= out_len:
if string.strncmp(out_buf + pos, global_name, name_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
return 1
pos += 1
return 0
# ============================================================
# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉
#
# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明
#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义
#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明
# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。
# ============================================================
def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int:
"""在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';'
type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容)
返回 1=已注释, 0=未找到
"""
if out_buf is None or type_name_prefix is None:
return 0
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
out_len: t.CSizeT = string.strlen(out_buf)
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + prefix_len <= out_len:
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
# 确认是行首(前一个是换行或 pos==0)
if pos == 0 or out_buf[pos - 1] == '\n':
# 检查后面是否是 " = type opaque"
p: t.CSizeT = pos + prefix_len
# 跳过空格
while p < out_len and out_buf[p] == ' ':
p += 1
if p < out_len and out_buf[p] == '=':
p += 1
while p < out_len and out_buf[p] == ' ':
p += 1
if p + 11 <= out_len:
if string.strncmp(out_buf + p, "type opaque", 11) == 0:
# 找到 opaque 声明,将行首改为 ';'
out_buf[pos] = ';'
return 1
pos += 1
return 0
# ============================================================
# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块
#
# deps.txt 只记录直接导入的模块名(如 "ast"),但包的 __init__.vp
# 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer 子模块类型。
# 当模块名包含 '.' 时,检查其顶层包名是否在 deps_buf 中。
#
# 例如:
# deps_buf = "ast stdio string"
# mod_name = "ast.lexer" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
# mod_name = "ast.token" → 顶层包 "ast" 在 deps_buf 中 → 返回 1
# mod_name = "foo.bar" → 顶层包 "foo" 不在 deps_buf 中 → 返回 0
# ============================================================
def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
"""检查 mod_name 是否是 deps_buf 中已导入包的子模块"""
if deps_buf is None or mod_name is None:
return 0
# 查找第一个 '.',提取顶层包名
dot_pos: str = string.strchr(mod_name, 46) # '.' = 46
if dot_pos is None:
return 0
pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_pos) - t.CUInt64T(mod_name))
if pkg_len == 0 or pkg_len >= 256:
return 0
# 构造顶层包名(截断到 '.' 之前)
# 直接在 mod_name 上临时截断检查,避免分配
saved_ch: t.CChar = mod_name[pkg_len]
mod_name[pkg_len] = '\0'
result: int = GenApi.is_module_imported(deps_buf, mod_name)
mod_name[pkg_len] = saved_ch
return result
# ============================================================
# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque)
#
# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=')
# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } >
# 返回 1=已有完整定义, 0=无完整定义
# ============================================================
def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int:
"""检查 out_buf 中是否已有 type_name_prefix 的完整定义"""
if out_buf is None or type_name_prefix is None:
return 0
prefix_len: t.CSizeT = string.strlen(type_name_prefix)
out_len: t.CSizeT = string.strlen(out_buf)
if prefix_len == 0 or out_len == 0 or prefix_len > out_len:
return 0
pos: t.CSizeT = 0
while pos + prefix_len <= out_len:
if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0:
# 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';')
is_line_start: int = 0
if pos == 0:
is_line_start = 1
elif out_buf[pos - 1] == '\n':
is_line_start = 1
if is_line_start == 1:
# 检查后面是否是 " = type {" 或 " = type <"
p: t.CSizeT = pos + prefix_len
while p < out_len and out_buf[p] == ' ':
p += 1
if p < out_len and out_buf[p] == '=':
p += 1
while p < out_len and out_buf[p] == ' ':
p += 1
if p + 5 < out_len:
if string.strncmp(out_buf + p, "type ", 5) == 0:
p += 5
if p < out_len:
if out_buf[p] == '{' or out_buf[p] == '<':
return 1
pos += 1
return 0
# ============================================================
# _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射
#
# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。
# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。
# 所有内存由 stdlib.malloc 分配,调用者负责释放。
# ============================================================
def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
sha1_list: str,
mod_list: str) -> int:
"""从全局内存存储器复制 sha1→module_name 映射到调用者数组
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
数据来源是 PopulateSha1MapStore 填充的全局存储器。
"""
if sha1_list is None or mod_list is None:
return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return 0
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= MAX_INCLUDES:
break
idx: t.CSizeT = t.CSizeT(i) * 17
idx2: t.CSizeT = t.CSizeT(i) * 64
string.strcpy(sha1_list + t.CSizeT(count) * 17, StubMerger._sha1_store_arr + idx)
string.strcpy(mod_list + t.CSizeT(count) * 64, StubMerger._sha1_store_mod + idx2)
count += 1
return count
# ============================================================
# _FindSha1ByModName - 从模块名查找 SHA1(精确匹配)
#
# 在 sha1_arr/mod_arr 映射中查找模块名对应的 SHA1。
# 用于依赖图分析:模块名 → SHA1。
#
# Args:
# sha1_arr: SHA1 数组(每个 17 字节)
# mod_arr: 模块名数组(每个 64 字节)
# count: 映射条目数
# mod_name: 要查找的模块名
#
# Returns:
# SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None
# ============================================================
def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
count: int, mod_name: str) -> str:
"""从模块名查找 SHA1(精确匹配 + 包名回退)
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
"""
if sha1_arr is None or mod_arr is None or mod_name is None:
return None
if count <= 0:
return None
# 第一遍:精确匹配
for i in range(count):
idx: t.CSizeT = t.CSizeT(i) * 64
if string.strcmp(mod_arr + idx, mod_name) == 0:
sidx: t.CSizeT = t.CSizeT(i) * 17
return sha1_arr + sidx
# 第二遍:包名回退("ast" → "ast.__init__")
nm_len: t.CSizeT = string.strlen(mod_name)
init_buf: bytes = stdlib.malloc(nm_len + 12)
if init_buf is not None:
viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name)
for i in range(count):
idx2: t.CSizeT = t.CSizeT(i) * 64
if string.strcmp(mod_arr + idx2, init_buf) == 0:
sidx2: t.CSizeT = t.CSizeT(i) * 17
stdlib.free(init_buf)
return sha1_arr + sidx2
stdlib.free(init_buf)
return None
# ============================================================
# _AddSha1ToSet - 将 SHA1 加入集合(去重)
#
# 检查 SHA1 是否已在集合中,若不在则加入。返回新的 count。
#
# Args:
# set_buf: SHA1 集合缓冲区(每个 17 字节)
# count: 当前集合中的 SHA1 数量
# sha1: 要加入的 SHA1
#
# Returns:
# 新的 count(如果已存在则不变)
# ============================================================
def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
"""将 SHA1 加入集合,返回新 count"""
if set_buf is None or sha1 is None:
return count
for i in range(count):
idx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(set_buf + idx, sha1) == 0:
return count
if count < MAX_INCLUDES_SHA1:
idx: t.CSizeT = t.CSizeT(count) * 17
string.strcpy(set_buf + idx, sha1)
return count + 1
return count
+407 -409
View File
@@ -1,409 +1,407 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# PopulateSha1MapStore - 从扫描结果填充全局 SHA1 映射存储器
#
# 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
# 模块名通过 _PathToModuleName(includes/rel_path) 计算。
# 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
#
# Args:
# scan_result: IncludesScanner 扫描结果
#
# Returns:
# 填充的条目数,-1 表示失败
# ============================================================
def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> int:
"""从扫描结果填充全局 SHA1 映射存储器
遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
模块名通过 _PathToModuleName(includes/rel_path) 计算。
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
"""
if scan_result is None:
return -1
# 释放旧存储器
if StubMerger._sha1_store_arr is not None:
stdlib.free(StubMerger._sha1_store_arr)
if StubMerger._sha1_store_mod is not None:
stdlib.free(StubMerger._sha1_store_mod)
if StubMerger._sha1_store_rel is not None:
stdlib.free(StubMerger._sha1_store_rel)
if StubMerger._sha1_store_incdir is not None:
stdlib.free(StubMerger._sha1_store_incdir)
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return -1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
p_bad: int = 0
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
for i in range(scan_result.Count):
if StubMerger._sha1_store_count >= MAX_INCLUDES:
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p
ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Sha1 is None or ent.RelPath is None:
p_bad += 1
continue
# 构建完整路径 includes/{RelPath}(_PathToModuleName 需要)
rp_len: t.CSizeT = string.strlen(ent.RelPath)
full_path_buf: bytes = stdlib.malloc(rp_len + 10)
if full_path_buf is None:
p_bad += 1
continue
viperlib.snprintf(full_path_buf, rp_len + 10, "includes/%s", ent.RelPath)
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
stdlib.free(full_path_buf)
if mod_name is not None:
idx: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1)
idx2: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
mn_len: t.CSizeT = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63)
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
stdlib.free(mod_name)
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
if rp_len < MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
else:
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
if ent.IncDir is not None:
icd_len: t.CSizeT = string.strlen(ent.IncDir)
if icd_len < MAX_INC_DIR_LEN:
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
else:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
StubMerger._sha1_store_count += 1
if p_bad > 0:
fb_pbad: str = VLogger.fmt_buf()
if fb_pbad is not None:
viperlib.snprintf(fb_pbad, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad)
VLogger.error(fb_pbad, "StubMerger")
return StubMerger._sha1_store_count
# ============================================================
# AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器
#
# Phase1 调用 PopulateSha1MapStore 填充 includes 文件,
# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目,
# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块
# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
# _build_source_path_from_sha1 查找 StubMerger 的源路径)。
#
# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。
# 若 SHA1 已存在(去重),跳过。
#
# Args:
# sha1: SHA1 字符串(16 字符 + null)
# rel_path: 相对路径(如 "lib/core/StubMerger.vp",
# 不含 includes/ 前缀,与 _sha1_map.txt 格式一致)
#
# Returns:
# 0 成功(含去重跳过),1 失败
# ============================================================
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
if sha1 is None or rel_path is None:
return 1
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
if StubMerger._sha1_store_arr is None:
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return 1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
if StubMerger._sha1_store_count >= MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._sha1_store_count):
sidx_d: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0:
return 0
# 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger"
full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10)
if full_path_buf is None:
return 1
viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path)
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
stdlib.free(full_path_buf)
if mod_name is None:
return 1
# 写入 SHA1
idx_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1)
# 写入模块名
idx_m: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
mn_len: t.CSizeT = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
stdlib.free(mod_name)
# 写入相对路径
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
rp_len: t.CSizeT = string.strlen(rel_path)
if rp_len < MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
else:
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
StubMerger._sha1_store_incdir[idx_inc_a] = '\0'
StubMerger._sha1_store_count += 1
return 0
# ============================================================
# GetSha1StoreCount - 获取全局存储器条目数
# ============================================================
def GetSha1StoreCount() -> int:
"""返回全局 SHA1 存储器的条目数"""
return StubMerger._sha1_store_count
# ============================================================
# LookupSha1ByModName - 从模块名查找 SHA1(直接查全局存储器)
#
# 精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
# 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
#
# Returns:
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
# ============================================================
def LookupSha1ByModName(mod_name: str) -> str:
"""从模块名查找 SHA1(精确匹配 + 包名回退),委托通用实现 _FindSha1ByModName"""
return StubMergerIR._FindSha1ByModName(StubMerger._sha1_store_arr, StubMerger._sha1_store_mod, StubMerger._sha1_store_count, mod_name)
# ============================================================
# LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1
#
# 用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
# 去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
# 包含三种匹配方式:精确、后缀、反向后缀。
#
# Returns:
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
# ============================================================
def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1"""
if mod_suffix is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return None
if StubMerger._sha1_store_count <= 0:
return None
suffix_len_sf: t.CSizeT = string.strlen(mod_suffix)
if suffix_len_sf == 0:
return None
i_sf: int
for i_sf in range(StubMerger._sha1_store_count):
idx_sf: t.CSizeT = t.CSizeT(i_sf) * 64
mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf
mod_len_sf: t.CSizeT = string.strlen(mod_name_sf)
if mod_len_sf == 0:
continue
# 精确匹配
if mod_len_sf == suffix_len_sf:
if string.strcmp(mod_name_sf, mod_suffix) == 0:
sidx_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx_sf
# 后缀匹配:mod_name 以 "." + mod_suffix 结尾
if mod_len_sf > suffix_len_sf:
if mod_name_sf[mod_len_sf - suffix_len_sf - 1] == '.':
cmp_start_sf: str = mod_name_sf + mod_len_sf - suffix_len_sf
if string.strcmp(cmp_start_sf, mod_suffix) == 0:
sidx2_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx2_sf
# 反向后缀匹配:mod_suffix 以 "." + mod_name 结尾
if suffix_len_sf > mod_len_sf:
if mod_suffix[suffix_len_sf - mod_len_sf - 1] == '.':
cmp_start_rev_sf: str = mod_suffix + suffix_len_sf - mod_len_sf
if string.strcmp(cmp_start_rev_sf, mod_name_sf) == 0:
sidx_rev_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx_rev_sf
return None
# ============================================================
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
#
# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules
# 后调用此函数存入内存。_BuildReachableSha1Set 从内存读取,不读 deps.txt。
#
# Args:
# sha1: includes 文件的 SHA1(16字符)
# deps_str: 依赖模块名字符串(空格分隔,如 "t c stdint string")
#
# Returns:
# 0 成功,非 0 失败
# ============================================================
def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
"""将 includes 文件的依赖存入内存"""
if sha1 is None:
return 1
# 延迟初始化
if StubMerger._includes_deps_sha1 is None:
StubMerger._includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN)
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
return 1
string.memset(StubMerger._includes_deps_sha1, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN)
StubMerger._includes_deps_count = 0
if StubMerger._includes_deps_count >= MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._includes_deps_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
return 0
# 写入 SHA1
idx: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * 17
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
# 写入依赖字符串
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * MAX_DEPS_STR_LEN
if deps_str is not None:
dl: t.CSizeT = string.strlen(deps_str)
if dl < MAX_DEPS_STR_LEN:
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
else:
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1)
else:
StubMerger._includes_deps_str[idx2] = '\0'
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
return 0
# ============================================================
# LookupIncludesDeps - 从内存查找 includes 文件的依赖
#
# Args:
# sha1: includes 文件的 SHA1(16字符)
#
# Returns:
# 依赖模块名字符串指针(空格分隔),None 表示未找到
# ============================================================
def LookupIncludesDeps(sha1: str) -> str:
"""从内存查找 includes 文件的依赖"""
if sha1 is None or StubMerger._includes_deps_sha1 is None:
return None
if StubMerger._includes_deps_count <= 0:
return None
for i in range(StubMerger._includes_deps_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN
return StubMerger._includes_deps_str + idx2
return None
def GetSha1StoreArrPtr() -> bytes | t.CPtr:
"""返回 SHA1 数组指针(每个条目 17 字节)"""
return StubMerger._sha1_store_arr
def GetSha1StoreModArrPtr() -> bytes | t.CPtr:
"""返回模块名数组指针(每个条目 64 字节)"""
return StubMerger._sha1_store_mod
def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
"""返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)"""
return StubMerger._sha1_store_rel
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
return StubMerger._sha1_store_incdir
# ============================================================
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
#
# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN]
# 内存归全局存储器所有,调用者不要 free
# ============================================================
def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int:
"""获取全局存储器数组指针
out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 指针,
函数将存储器数组指针写入这些位置。
返回条目数,-1 失败
"""
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None:
return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
return -1
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr))
if sp is not None:
sp[0] = StubMerger._sha1_store_arr
mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr))
if mp is not None:
mp[0] = StubMerger._sha1_store_mod
rp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_rel_arr, t.CPtr))
if rp is not None:
rp[0] = StubMerger._sha1_store_rel
return StubMerger._sha1_store_count
# ============================================================
# LookupSha1RelPath - 通过 SHA1 查找相对路径
#
# 遍历全局存储器,返回 sha1 对应的相对路径指针(只读,不要 free)。
# 用于错误提示:将 sha1 转换为人类可读的文件路径。
#
# Args:
# sha1: SHA1 字符串(16 字符)
#
# Returns:
# 相对路径字符串指针(只读),None=未找到
# ============================================================
def LookupSha1RelPath(sha1: str) -> str:
"""通过 SHA1 查找相对路径,返回只读指针,None=未找到"""
if sha1 is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None:
return None
for i in range(StubMerger._sha1_store_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN
return StubMerger._sha1_store_rel + ridx
return None
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerTopo as StubMergerTopo
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerStore - StubMerger 拆分(阶段 E):StubMergerStore
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# PopulateSha1MapStore - 从扫描结果填充全局 SHA1 映射存储器
#
# 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
# 模块名通过 _PathToModuleName(includes/rel_path) 计算。
# 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
#
# Args:
# scan_result: IncludesScanner 扫描结果
#
# Returns:
# 填充的条目数,-1 表示失败
# ============================================================
def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> int:
"""从扫描结果填充全局 SHA1 映射存储器
遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。
模块名通过 _PathToModuleName(includes/rel_path) 计算。
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
"""
if scan_result is None:
return -1
# 释放旧存储器
if StubMerger._sha1_store_arr is not None:
stdlib.free(StubMerger._sha1_store_arr)
if StubMerger._sha1_store_mod is not None:
stdlib.free(StubMerger._sha1_store_mod)
if StubMerger._sha1_store_rel is not None:
stdlib.free(StubMerger._sha1_store_rel)
if StubMerger._sha1_store_incdir is not None:
stdlib.free(StubMerger._sha1_store_incdir)
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return -1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
p_bad: int = 0
entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__()
for i in range(scan_result.Count):
if StubMerger._sha1_store_count >= MAX_INCLUDES:
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p
ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Sha1 is None or ent.RelPath is None:
p_bad += 1
continue
# 构建完整路径 includes/{RelPath}(_PathToModuleName 需要)
rp_len: t.CSizeT = string.strlen(ent.RelPath)
full_path_buf: bytes = stdlib.malloc(rp_len + 10)
if full_path_buf is None:
p_bad += 1
continue
viperlib.snprintf(full_path_buf, rp_len + 10, "includes/%s", ent.RelPath)
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
stdlib.free(full_path_buf)
if mod_name is not None:
idx: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1)
idx2: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
mn_len: t.CSizeT = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63)
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
stdlib.free(mod_name)
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
idx3: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
if rp_len < MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
else:
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0'
# 保存所属 includes 根目录(Phase2 预注册/按需编译拼路径用)
idx_inc: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
if ent.IncDir is not None:
icd_len: t.CSizeT = string.strlen(ent.IncDir)
if icd_len < MAX_INC_DIR_LEN:
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
else:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + MAX_INC_DIR_LEN - 1] = '\0'
StubMerger._sha1_store_count += 1
if p_bad > 0:
fb_pbad: str = VLogger.fmt_buf()
if fb_pbad is not None:
viperlib.snprintf(fb_pbad, 1024, "includes SHA1 存储有 %d 个条目失败", p_bad)
VLogger.error(fb_pbad, "StubMerger")
return StubMerger._sha1_store_count
# ============================================================
# AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器
#
# Phase1 调用 PopulateSha1MapStore 填充 includes 文件,
# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目,
# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块
# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过
# _build_source_path_from_sha1 查找 StubMerger 的源路径)。
#
# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。
# 若 SHA1 已存在(去重),跳过。
#
# Args:
# sha1: SHA1 字符串(16 字符 + null)
# rel_path: 相对路径(如 "lib/core/StubMerger.vp",
# 不含 includes/ 前缀,与 _sha1_map.txt 格式一致)
#
# Returns:
# 0 成功(含去重跳过),1 失败
# ============================================================
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
if sha1 is None or rel_path is None:
return 1
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
if StubMerger._sha1_store_arr is None:
StubMerger._sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(MAX_INCLUDES * MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return 1
string.memset(StubMerger._sha1_store_arr, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, MAX_INCLUDES * MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
if StubMerger._sha1_store_count >= MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._sha1_store_count):
sidx_d: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0:
return 0
# 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger"
full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10)
if full_path_buf is None:
return 1
viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path)
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
stdlib.free(full_path_buf)
if mod_name is None:
return 1
# 写入 SHA1
idx_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 17
string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1)
# 写入模块名
idx_m: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * 64
mn_len: t.CSizeT = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
stdlib.free(mod_name)
# 写入相对路径
idx_r: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_REL_PATH_LEN
rp_len: t.CSizeT = string.strlen(rel_path)
if rp_len < MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
else:
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0'
# App 源文件不属于任何 includes 目录:IncDir 留空(Phase2 回退 includes_dir 参数)
idx_inc_a: t.CSizeT = t.CSizeT(StubMerger._sha1_store_count) * MAX_INC_DIR_LEN
StubMerger._sha1_store_incdir[idx_inc_a] = '\0'
StubMerger._sha1_store_count += 1
return 0
# ============================================================
# GetSha1StoreCount - 获取全局存储器条目数
# ============================================================
def GetSha1StoreCount() -> int:
"""返回全局 SHA1 存储器的条目数"""
return StubMerger._sha1_store_count
# ============================================================
# LookupSha1ByModName - 从模块名查找 SHA1(直接查全局存储器)
#
# 精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
# 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
#
# Returns:
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
# ============================================================
def LookupSha1ByModName(mod_name: str) -> str:
"""从模块名查找 SHA1(精确匹配 + 包名回退),委托通用实现 _FindSha1ByModName"""
return StubMergerIR._FindSha1ByModName(StubMerger._sha1_store_arr, StubMerger._sha1_store_mod, StubMerger._sha1_store_count, mod_name)
# ============================================================
# LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1
#
# 用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点),
# 去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。
# 包含三种匹配方式:精确、后缀、反向后缀。
#
# Returns:
# SHA1 字符串指针(指向全局存储器内部,无需释放),None 未找到
# ============================================================
def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1"""
if mod_suffix is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return None
if StubMerger._sha1_store_count <= 0:
return None
suffix_len_sf: t.CSizeT = string.strlen(mod_suffix)
if suffix_len_sf == 0:
return None
i_sf: int
for i_sf in range(StubMerger._sha1_store_count):
idx_sf: t.CSizeT = t.CSizeT(i_sf) * 64
mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf
mod_len_sf: t.CSizeT = string.strlen(mod_name_sf)
if mod_len_sf == 0:
continue
# 精确匹配
if mod_len_sf == suffix_len_sf:
if string.strcmp(mod_name_sf, mod_suffix) == 0:
sidx_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx_sf
# 后缀匹配:mod_name 以 "." + mod_suffix 结尾
if mod_len_sf > suffix_len_sf:
if mod_name_sf[mod_len_sf - suffix_len_sf - 1] == '.':
cmp_start_sf: str = mod_name_sf + mod_len_sf - suffix_len_sf
if string.strcmp(cmp_start_sf, mod_suffix) == 0:
sidx2_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx2_sf
# 反向后缀匹配:mod_suffix 以 "." + mod_name 结尾
if suffix_len_sf > mod_len_sf:
if mod_suffix[suffix_len_sf - mod_len_sf - 1] == '.':
cmp_start_rev_sf: str = mod_suffix + suffix_len_sf - mod_len_sf
if string.strcmp(cmp_start_rev_sf, mod_name_sf) == 0:
sidx_rev_sf: t.CSizeT = t.CSizeT(i_sf) * 17
return StubMerger._sha1_store_arr + sidx_rev_sf
return None
# ============================================================
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
#
# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules
# 后调用此函数存入内存。_BuildReachableSha1Set 从内存读取,不读 deps.txt。
#
# Args:
# sha1: includes 文件的 SHA1(16字符)
# deps_str: 依赖模块名字符串(空格分隔,如 "t c stdint string")
#
# Returns:
# 0 成功,非 0 失败
# ============================================================
def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
"""将 includes 文件的依赖存入内存"""
if sha1 is None:
return 1
# 延迟初始化
if StubMerger._includes_deps_sha1 is None:
StubMerger._includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17)
StubMerger._includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN)
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
return 1
string.memset(StubMerger._includes_deps_sha1, 0, MAX_INCLUDES * 17)
string.memset(StubMerger._includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN)
StubMerger._includes_deps_count = 0
if StubMerger._includes_deps_count >= MAX_INCLUDES:
return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._includes_deps_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
return 0
# 写入 SHA1
idx: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * 17
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
# 写入依赖字符串
idx2: t.CSizeT = t.CSizeT(StubMerger._includes_deps_count) * MAX_DEPS_STR_LEN
if deps_str is not None:
dl: t.CSizeT = string.strlen(deps_str)
if dl < MAX_DEPS_STR_LEN:
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
else:
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1)
else:
StubMerger._includes_deps_str[idx2] = '\0'
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
return 0
# ============================================================
# LookupIncludesDeps - 从内存查找 includes 文件的依赖
#
# Args:
# sha1: includes 文件的 SHA1(16字符)
#
# Returns:
# 依赖模块名字符串指针(空格分隔),None 表示未找到
# ============================================================
def LookupIncludesDeps(sha1: str) -> str:
"""从内存查找 includes 文件的依赖"""
if sha1 is None or StubMerger._includes_deps_sha1 is None:
return None
if StubMerger._includes_deps_count <= 0:
return None
for i in range(StubMerger._includes_deps_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN
return StubMerger._includes_deps_str + idx2
return None
def GetSha1StoreArrPtr() -> bytes | t.CPtr:
"""返回 SHA1 数组指针(每个条目 17 字节)"""
return StubMerger._sha1_store_arr
def GetSha1StoreModArrPtr() -> bytes | t.CPtr:
"""返回模块名数组指针(每个条目 64 字节)"""
return StubMerger._sha1_store_mod
def GetSha1StoreRelArrPtr() -> bytes | t.CPtr:
"""返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)"""
return StubMerger._sha1_store_rel
def GetSha1StoreIncdirArrPtr() -> bytes | t.CPtr:
"""返回所属 includes 根目录数组指针(每个条目 MAX_INC_DIR_LEN 字节,空串表示不属于任何 includes 目录)"""
return StubMerger._sha1_store_incdir
# ============================================================
# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用)
#
# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。
# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN]
# 内存归全局存储器所有,调用者不要 free
# ============================================================
def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int:
"""获取全局存储器数组指针
out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 指针,
函数将存储器数组指针写入这些位置。
返回条目数,-1 失败
"""
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None:
return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
return -1
sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr))
if sp is not None:
sp[0] = StubMerger._sha1_store_arr
mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr))
if mp is not None:
mp[0] = StubMerger._sha1_store_mod
rp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_rel_arr, t.CPtr))
if rp is not None:
rp[0] = StubMerger._sha1_store_rel
return StubMerger._sha1_store_count
# ============================================================
# LookupSha1RelPath - 通过 SHA1 查找相对路径
#
# 遍历全局存储器,返回 sha1 对应的相对路径指针(只读,不要 free)。
# 用于错误提示:将 sha1 转换为人类可读的文件路径。
#
# Args:
# sha1: SHA1 字符串(16 字符)
#
# Returns:
# 相对路径字符串指针(只读),None=未找到
# ============================================================
def LookupSha1RelPath(sha1: str) -> str:
"""通过 SHA1 查找相对路径,返回只读指针,None=未找到"""
if sha1 is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None:
return None
for i in range(StubMerger._sha1_store_count):
sidx: t.CSizeT = t.CSizeT(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN
return StubMerger._sha1_store_rel + ridx
return None
+166 -168
View File
@@ -1,168 +1,166 @@
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesStruct as HandlesStruct
import lib.core.Handles.HandlesImports as HandlesImports
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerTopo - StubMerger 拆分(阶段 E):StubMergerTopo
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# BuildTopoSortedIndices - 对可达 includes 逆拓扑排序(被依赖者先)
#
# 背景:跨模块 vtable 生成要求被依赖模块先完整翻译(如 astaux.vp 继承
# base.vp 的 AST,vtable 槽位需 AST.accept 的 TypeStr 已注册到全局表)。
# Phase B+ 原先按 store 扫描顺序编译,依赖顺序不保证 → fail-fast 暴露。
#
# 算法:Kahn 逆拓扑。边 m→d 表示 m 依赖 d(d 在 m 的 deps 中)。
# indegree[m] = m 在可达集合内的直接依赖数;
# 入度为 0(不依赖任何可达模块)者先输出,输出后对依赖它的模块
# 减入度,入度归 0 者入队。结果即"被依赖者先编译"。
# reachable_count <= 0 时对全部 store 排序(与既有全量编译行为一致)。
#
# Args:
# store_count / store_sha1_arr / store_mod_arr: store 元数据
# reachable_set / reachable_count: 可达集合(_BuildReachableSha1Set 输出)
# sorted_idx: 输出数组(store_count+1 个 8 字节槽),前 N 个为拓扑序 store 索引
#
# Returns:
# 拓扑序条数;有环时剩余条目按 store 顺序补齐(避免漏编译)
# ============================================================
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
store_mod_arr: bytes, reachable_set: bytes,
reachable_count: int,
sorted_idx: t.CSizeT | t.CPtr) -> int:
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None:
return 0
indegree: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
queue: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
rel_idx: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
if indegree is None or queue is None or rel_idx is None:
if indegree is not None:
stdlib.free(indegree)
if queue is not None:
stdlib.free(queue)
if rel_idx is not None:
stdlib.free(rel_idx)
return 0
# 收集可达 store 索引(reachable_count<=0 时全量,对齐既有全量编译行为)
rel_count: int = 0
i_t: int
if reachable_set is None or reachable_count <= 0:
for i_t in range(store_count):
rel_idx[rel_count] = i_t
rel_count += 1
else:
for i_t in range(store_count):
if StubMergerCollect._is_in_sha1_set(store_sha1_arr + t.CSizeT(i_t) * 17, reachable_set, reachable_count) != 0:
rel_idx[rel_count] = i_t
rel_count += 1
# 计算入度:m 在可达集合内的直接依赖数
i_r: int
for i_r in range(rel_count):
si: int = rel_idx[i_r]
deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si) * 17)
if deps_si is None:
continue
dl_si: t.CSizeT = string.strlen(deps_si)
dpos: t.CSizeT = 0
while dpos < dl_si:
dstart: t.CSizeT = dpos
while dpos < dl_si and deps_si[dpos] != ' ':
dpos += 1
dlen: t.CSizeT = dpos - dstart
if dpos < dl_si:
dpos += 1
if dlen == 0:
continue
dname_buf: bytes = stdlib.malloc(dlen + 1)
if dname_buf is None:
continue
string.strncpy(dname_buf, deps_si + dstart, dlen)
dname_buf[dlen] = '\0'
dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf)
stdlib.free(dname_buf)
if dsha1 is not None and StubMergerCollect._is_in_sha1_set(dsha1, reachable_set, reachable_count) != 0:
indegree[si] = indegree[si] + 1
# Kahn:入度为 0(不依赖任何可达模块)者先出 → 最先编译
q_head: int = 0
q_tail: int = 0
for i_r in range(rel_count):
si2: int = rel_idx[i_r]
if indegree[si2] == 0:
queue[q_tail] = si2
q_tail += 1
out_count: int = 0
while q_head < q_tail:
m: int = queue[q_head]
q_head += 1
sorted_idx[out_count] = m
out_count += 1
# 对依赖 m 的可达模块减入度
mod_m: str = store_mod_arr + t.CSizeT(m) * 64
mod_m_len: t.CSizeT = string.strlen(mod_m)
for i_r in range(rel_count):
si3: int = rel_idx[i_r]
if indegree[si3] == 0:
continue
deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si3) * 17)
if deps_si3 is None:
continue
dl_si3: t.CSizeT = string.strlen(deps_si3)
dpos3: t.CSizeT = 0
found_dep: int = 0
while dpos3 < dl_si3 and found_dep == 0:
dstart3: t.CSizeT = dpos3
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ':
dpos3 += 1
dlen3: t.CSizeT = dpos3 - dstart3
if dpos3 < dl_si3:
dpos3 += 1
if dlen3 == 0:
continue
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0:
found_dep = 1
if found_dep == 1:
indegree[si3] = indegree[si3] - 1
if indegree[si3] == 0:
queue[q_tail] = si3
q_tail += 1
# 有环时剩余条目按 store 顺序补齐(避免漏编译)
for i_r in range(rel_count):
si4: int = rel_idx[i_r]
if indegree[si4] > 0:
sorted_idx[out_count] = si4
out_count += 1
stdlib.free(indegree)
stdlib.free(queue)
stdlib.free(rel_idx)
return out_count
import t, c
from stdint import *
import memhub
import string
import stdlib
import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import viperlib
import sys
import ast
import lib.core.VLogger as VLogger
import lib.core.IncludesScanner as IncludesScanner
import lib.core.Handles.HandlesTranslator as HandlesTranslator
import lib.core.BuildPipeline as BuildPipeline
import lib.StubGen.VpiReader as VpiReader
import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
import lib.core.StubMergerCollect as StubMergerCollect
import lib.core.StubMergerStore as StubMergerStore
import lib.core.StubMergerIR as StubMergerIR
import lib.core.StubMergerBuild as StubMergerBuild
import lib.core.StubMerger as StubMerger
# ============================================================
# StubMergerTopo - StubMerger 拆分(阶段 E):StubMergerTopo
#
# 直接移动模式:函数实现迁至此模块,原 StubMerger.vp 仅保留
# 常量/全局变量;调用方经本模块前缀访问。全局变量跨模块经
# StubMerger._xxx 访问(main.vp 先例)。
# ============================================================
# ============================================================
# BuildTopoSortedIndices - 对可达 includes 逆拓扑排序(被依赖者先)
#
# 背景:跨模块 vtable 生成要求被依赖模块先完整翻译(如 astaux.vp 继承
# base.vp 的 AST,vtable 槽位需 AST.accept 的 TypeStr 已注册到全局表)。
# Phase B+ 原先按 store 扫描顺序编译,依赖顺序不保证 → fail-fast 暴露。
#
# 算法:Kahn 逆拓扑。边 m→d 表示 m 依赖 d(d 在 m 的 deps 中)。
# indegree[m] = m 在可达集合内的直接依赖数;
# 入度为 0(不依赖任何可达模块)者先输出,输出后对依赖它的模块
# 减入度,入度归 0 者入队。结果即"被依赖者先编译"。
# reachable_count <= 0 时对全部 store 排序(与既有全量编译行为一致)。
#
# Args:
# store_count / store_sha1_arr / store_mod_arr: store 元数据
# reachable_set / reachable_count: 可达集合(_BuildReachableSha1Set 输出)
# sorted_idx: 输出数组(store_count+1 个 8 字节槽),前 N 个为拓扑序 store 索引
#
# Returns:
# 拓扑序条数;有环时剩余条目按 store 顺序补齐(避免漏编译)
# ============================================================
def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
store_mod_arr: bytes, reachable_set: bytes,
reachable_count: int,
sorted_idx: t.CSizeT | t.CPtr) -> int:
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None:
return 0
indegree: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
queue: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
rel_idx: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(stdlib.malloc(8 * (store_count + 1)))
if indegree is None or queue is None or rel_idx is None:
if indegree is not None:
stdlib.free(indegree)
if queue is not None:
stdlib.free(queue)
if rel_idx is not None:
stdlib.free(rel_idx)
return 0
# 收集可达 store 索引(reachable_count<=0 时全量,对齐既有全量编译行为)
rel_count: int = 0
i_t: int
if reachable_set is None or reachable_count <= 0:
for i_t in range(store_count):
rel_idx[rel_count] = i_t
rel_count += 1
else:
for i_t in range(store_count):
if StubMergerCollect._is_in_sha1_set(store_sha1_arr + t.CSizeT(i_t) * 17, reachable_set, reachable_count) != 0:
rel_idx[rel_count] = i_t
rel_count += 1
# 计算入度:m 在可达集合内的直接依赖数
i_r: int
for i_r in range(rel_count):
si: int = rel_idx[i_r]
deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si) * 17)
if deps_si is None:
continue
dl_si: t.CSizeT = string.strlen(deps_si)
dpos: t.CSizeT = 0
while dpos < dl_si:
dstart: t.CSizeT = dpos
while dpos < dl_si and deps_si[dpos] != ' ':
dpos += 1
dlen: t.CSizeT = dpos - dstart
if dpos < dl_si:
dpos += 1
if dlen == 0:
continue
dname_buf: bytes = stdlib.malloc(dlen + 1)
if dname_buf is None:
continue
string.strncpy(dname_buf, deps_si + dstart, dlen)
dname_buf[dlen] = '\0'
dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf)
stdlib.free(dname_buf)
if dsha1 is not None and StubMergerCollect._is_in_sha1_set(dsha1, reachable_set, reachable_count) != 0:
indegree[si] = indegree[si] + 1
# Kahn:入度为 0(不依赖任何可达模块)者先出 → 最先编译
q_head: int = 0
q_tail: int = 0
for i_r in range(rel_count):
si2: int = rel_idx[i_r]
if indegree[si2] == 0:
queue[q_tail] = si2
q_tail += 1
out_count: int = 0
while q_head < q_tail:
m: int = queue[q_head]
q_head += 1
sorted_idx[out_count] = m
out_count += 1
# 对依赖 m 的可达模块减入度
mod_m: str = store_mod_arr + t.CSizeT(m) * 64
mod_m_len: t.CSizeT = string.strlen(mod_m)
for i_r in range(rel_count):
si3: int = rel_idx[i_r]
if indegree[si3] == 0:
continue
deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + t.CSizeT(si3) * 17)
if deps_si3 is None:
continue
dl_si3: t.CSizeT = string.strlen(deps_si3)
dpos3: t.CSizeT = 0
found_dep: int = 0
while dpos3 < dl_si3 and found_dep == 0:
dstart3: t.CSizeT = dpos3
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ':
dpos3 += 1
dlen3: t.CSizeT = dpos3 - dstart3
if dpos3 < dl_si3:
dpos3 += 1
if dlen3 == 0:
continue
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0:
found_dep = 1
if found_dep == 1:
indegree[si3] = indegree[si3] - 1
if indegree[si3] == 0:
queue[q_tail] = si3
q_tail += 1
# 有环时剩余条目按 store 顺序补齐(避免漏编译)
for i_r in range(rel_count):
si4: int = rel_idx[i_r]
if indegree[si4] > 0:
sorted_idx[out_count] = si4
out_count += 1
stdlib.free(indegree)
stdlib.free(queue)
stdlib.free(rel_idx)
return out_count
+673 -712
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff