Some simple information syncing

This commit is contained in:
2026-07-28 21:08:58 +08:00
parent 1837339f69
commit 3633be1995
65 changed files with 1132 additions and 368581 deletions

View File

@@ -12,7 +12,7 @@ class Buf:
length: t.CSizeT
capacity: t.CSizeT
owned: bool
def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass
def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT = 0, owned: bool = False) -> t.CInt: pass
def clear(self: Buf) -> t.CInt: pass
def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass
def cstr(self: Buf) -> t.CChar | t.CPtr: pass

367074
1.txt

File diff suppressed because it is too large Load Diff

0
2.txt Normal file
View File

View File

@@ -52,71 +52,36 @@ def Load_project_config(path: str) -> int:
global IncludesDir
if path is None:
stdio.printf("[CFG] FAIL: path is None\n")
stdio.fflush(0)
return 1
if _mbuddy is None:
stdio.printf("[CFG] FAIL: _mbuddy is None\n")
stdio.fflush(0)
return 1
# 打开文件
stdio.printf("[CFG] before File ctor path=%s\n", path)
stdio.fflush(0)
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R)
f_closed_flag: int = 1
if f is not None:
if f.closed:
f_closed_flag = 1
else:
f_closed_flag = 0
stdio.printf("[CFG] after File ctor f=%p closed=%d\n", f, f_closed_flag)
stdio.fflush(0)
if f is None:
stdio.printf("[CFG] FAIL: File ctor returned None\n")
stdio.fflush(0)
return 1
if f.closed:
stdio.printf("[CFG] FAIL: f.closed is True\n")
stdio.fflush(0)
return 1
# 分配读取缓冲区
CFG_BUF_SIZE: t.CSizeT = 8192
buf: bytes = _mbuddy.alloc(CFG_BUF_SIZE)
if buf is None:
stdio.printf("[CFG] FAIL: alloc buf failed\n")
stdio.fflush(0)
f.close()
return 1
stdio.printf("[CFG] before read_all\n")
stdio.fflush(0)
bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE)
f.close()
stdio.printf("[CFG] after read_all bytes_read=%d\n", bytes_read)
stdio.fflush(0)
if bytes_read <= 0:
stdio.printf("[CFG] FAIL: bytes_read <= 0\n")
stdio.fflush(0)
return 1
# 解析 JSON
stdio.printf("[CFG] before json_parse\n")
stdio.fflush(0)
root: JsonValue | t.CPtr = json_parse(_mbuddy, buf)
stdio.printf("[CFG] after json_parse root=%p\n", root)
stdio.fflush(0)
if root is None:
stdio.printf("[CFG] FAIL: json_parse returned None\n")
stdio.fflush(0)
return 1
if not root.is_object():
stdio.printf("[CFG] FAIL: root is not object\n")
stdio.fflush(0)
return 1
stdio.printf("[CFG] root is object OK\n")
stdio.fflush(0)
# 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制)
sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir")

View File

@@ -16,7 +16,7 @@ import w32.win32base
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# ============================================================

View File

@@ -9,14 +9,15 @@ import lib.core.VLogger as VLogger
# ============================================================
# 全局 mbuddy 内存池指针(由 App/main.py 初始化后注入)
_mbuddy: memhub.MemManager | t.CPtr
# 注意: 使用 MemBuddy 类型而非 MemManager避免虚函数分派不工作时调用父类 alloc 返回 None
_mbuddy: memhub.MemBuddy | t.CPtr
def InitLib(mb: memhub.MemManager | t.CPtr) -> int:
def InitLib(mb: memhub.MemBuddy | t.CPtr) -> int:
"""初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。
Args:
mb: memhub.MemManager 实例指针MemBuddy 等子类通过多态传入)
mb: memhub.MemBuddy 实例指针
Returns:
0 表示成功,非 0 表示失败

View File

@@ -27,7 +27,7 @@ import lib.Projectrans.Config as Config
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576
@@ -270,26 +270,11 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s
return 1
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
if result is None:
# 用 stdlib.system() 直接在控制台运行,输出直接显示
# 避免 subprocess 管道捕获丢失输出
sys_ret: int = stdlib.system(cmd)
if sys_ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "subprocess.run 返回 None: %s", module_name)
VLogger.error(fb, "LLC")
return 1
if result.returncode != 0:
# 先直接输出 llc 的具体错误信息VLogger.error 会 sys.exit必须先输出
# 注意: subprocess 在 Windows 下将 stderr 合并到 stdoutsi.hStdError = stdout_write
# 因此 result.stderr 总是 None错误信息在 result.stdout 中
# stdout 通常已含换行符,不再额外加 \n
if result.stdout is not None:
stdio.printf("%s", result.stdout)
stdio.fflush(0)
if result.stderr is not None:
stdio.printf("%s", result.stderr)
stdio.fflush(0)
# 最后输出编译失败摘要VLogger.error 会 sys.exit
fb = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd)
VLogger.error(fb, "LLC")
@@ -524,23 +509,13 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT,
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s",
linker_cmd, obj_paths, linker_output, linker_flags)
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
if result is None:
VLogger.error("subprocess.run 返回 None", "link")
return 1
if result.returncode != 0:
# 先直接输出 linker 的具体错误信息VLogger.error 会 sys.exit必须先输出
# stdout/stderr 通常已含换行符,不再额外加 \n
if result.stdout is not None:
stdio.printf("%s", result.stdout)
stdio.fflush(0)
if result.stderr is not None:
stdio.printf("%s", result.stderr)
stdio.fflush(0)
# 最后输出链接失败摘要VLogger.error 会 sys.exit
# 用 stdlib.system() 直接在控制台运行链接,输出直接显示
# 避免 subprocess 管道捕获丢失输出TransPyV 标准句柄可能无效)
sys_ret: int = stdlib.system(cmd)
if sys_ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", result.returncode, cmd)
viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", sys_ret, cmd)
VLogger.error(fb, "link")
return 1
return 0

View File

@@ -4,6 +4,7 @@ import ast
import llvmlite
import memhub
import string
import stdio
import lib.core.Handles.HandlesBase as HandlesBase
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesVar as HandlesVar
@@ -49,18 +50,72 @@ def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
# ============================================================
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
#
# 支持 ast.Constant(INT),其他形式返回 0
# 支持的表达式形式:
# 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) -> int:
"""从值节点提取整数常量(支持 Constant INT"""
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp"""
if val_node is None:
return 0
if val_node.kind() != ast.ASTKind.Constant:
k: int = val_node.kind()
# Case 1: Constant(INT) — 如 0x0002
if k == ast.ASTKind.Constant:
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
if cn.const_kind != ast.CONST_INT:
return 0
return cn.int_val
# Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN
if k == ast.ASTKind.BinOp:
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node)
left_val: int = extract_cdefine_int_value(bop.left)
right_val: int = extract_cdefine_int_value(bop.right)
if bop.op == ast.OpKind.BitOr:
return left_val | right_val
if bop.op == ast.OpKind.BitAnd:
return left_val & right_val
if bop.op == ast.OpKind.Add:
return left_val + right_val
if bop.op == ast.OpKind.Sub:
return left_val - right_val
return 0
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
if cn.const_kind != ast.CONST_INT:
# Case 3: Name — 引用已注册的 CDefine 常量
if k == ast.ASTKind.Name:
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node)
if nm.id is not None:
looked_up: int = HandlesType.lookup_cdefine_constant(nm.id)
if HandlesType.is_cdefine_found() != 0:
return looked_up
return 0
return cn.int_val
# Case 4: Call — 如 t.CUnsignedLong(-11)
if k == ast.ASTKind.Call:
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node)
if cl.args is not None and cl.args.__len__() > 0:
first_arg: ast.AST | t.CPtr = cl.args.get(0)
arg_val: int = extract_cdefine_int_value(first_arg)
return arg_val
return 0
# Case 5: UnaryOp — 如 -11
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node)
operand_val: int = extract_cdefine_int_value(uop.operand)
if uop.op == ast.OpKind.USub:
return -operand_val
if uop.op == ast.OpKind.UAdd:
return operand_val
if uop.op == ast.OpKind.Invert:
return ~operand_val
return 0
return 0
# ============================================================

View File

@@ -238,8 +238,6 @@ class AssignHandle(HandlesBase.Mixin):
setitem_done = 1
if setitem_done == 0:
sub_vk: int = sub_asgn.value.kind()
stdio.printf("[ASGN-SUB] fallback failed: val_kind=%d\n", sub_vk)
stdio.fflush(0)
if setitem_done == 0:
HandlesType.fatal_error(target, "subscript ptr is None")
continue
@@ -249,25 +247,14 @@ class AssignHandle(HandlesBase.Mixin):
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
builder, pool, mod, target, self.Trans)
if field_ptr is not None:
stdio.printf("[ASGN-ATTR] field_ptr ok ty_not_null=%d\n",
1 if field_ptr.Ty is not None else 0)
stdio.fflush(0)
# 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64
store_val: llvmlite.Value | t.CPtr = rhs_val
if field_ptr.Ty is not None:
field_ty: llvmlite.LLVMType | t.CPtr = field_ptr.Ty.Pointee
if field_ty is not None:
stdio.printf("[ASGN-ATTR] coerce rhs_ty=%d field_ty=%d\n",
HandlesExpr.get_llvm_type_bits(rhs_val.Ty),
HandlesExpr.get_llvm_type_bits(field_ty))
stdio.fflush(0)
store_val = HandlesExpr.coerce_to_type(
builder, rhs_val, field_ty)
stdio.printf("[ASGN-ATTR] pre_store\n")
stdio.fflush(0)
llvmlite.build_store(builder, store_val, field_ptr)
stdio.printf("[ASGN-ATTR] post_store\n")
stdio.fflush(0)
else:
# 构造详细错误信息
attr_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(target)

View File

@@ -69,7 +69,7 @@ class TypeInfo:
# ============================================================
class TypeRegistry:
_ht: hashtable.HashTable | t.CPtr
__mbuddy__: memhub.MemManager | t.CPtr
__mbuddy__: memhub.MemBuddy | t.CPtr
def Register(self, ti: TypeInfo | t.CPtr) -> int:
"""注册一个 TypeInfo。ti.Name 字段必须已设置。
@@ -106,7 +106,7 @@ class TypeRegistry:
#
# 默认值Kind=Basic, IsSigned=-1, 其余=0/None
# ============================================================
def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr:
def NewTypeInfo(pool: memhub.MemBuddy | t.CPtr) -> TypeInfo | t.CPtr:
ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__())
if ptr is None:
return None
@@ -119,7 +119,7 @@ def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr:
# ============================================================
# NewTypeRegistry - 工厂函数:创建类型注册表
# ============================================================
def NewTypeRegistry(pool: memhub.MemManager | t.CPtr) -> TypeRegistry | t.CPtr:
def NewTypeRegistry(pool: memhub.MemBuddy | t.CPtr) -> TypeRegistry | t.CPtr:
ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__())
if ptr is None:
return None

View File

@@ -818,7 +818,7 @@ def _translate_enum_def(trans: HT.Translator | t.CPtr,
# 用于联合体确定最大字段大小
# ============================================================
def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""计算 LLVM 类型的字节大小"""
"""计算 LLVM 类型的字节大小(含对齐 padding"""
if ty is None:
return 0
match ty:
@@ -831,20 +831,79 @@ def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int:
case llvmlite.LLVMType.Array(elem_ty, count):
return _get_type_size(elem_ty) * count
case llvmlite.LLVMType.Struct(fields, fcount, name):
# 计算结构体大小,考虑字段对齐 padding
# 规则: 每个字段的对齐 = 该字段类型的自然对齐
# 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1
# 结构体总大小需对齐到最大字段对齐的倍数
total: int = 0
max_align: int = 1
cur: llvmlite.ParamNode | t.CPtr = fields
i: int = 0
while cur is not None and i < fcount:
if cur.Ty is not None:
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
total += _get_type_size(fty)
fsize: int = _get_type_size(fty)
falign: int = _get_type_align(fty)
# 对齐当前偏移到字段对齐边界
if falign > 0:
rem: int = total % falign
if rem != 0:
total += falign - rem
total += fsize
if falign > max_align:
max_align = falign
cur = cur.Next
i += 1
# 结构体总大小对齐到最大字段对齐的倍数
rem2: int = total % max_align
if rem2 != 0:
total += max_align - rem2
return total
case _:
return 8
def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int:
"""返回类型的自然对齐(字节)"""
if ty is None:
return 1
match ty:
case llvmlite.LLVMType.Int(bits):
if bits <= 8:
return 1
elif bits <= 16:
return 2
elif bits <= 32:
return 4
else:
return 8
case llvmlite.LLVMType.Float(bits):
if bits <= 32:
return 4
else:
return 8
case llvmlite.LLVMType.Ptr(pointee):
return 8
case llvmlite.LLVMType.Array(elem_ty, count):
return _get_type_align(elem_ty)
case llvmlite.LLVMType.Struct(fields, fcount, name):
# 结构体的对齐 = 最大字段对齐
max_align: int = 1
cur: llvmlite.ParamNode | t.CPtr = fields
i: int = 0
while cur is not None and i < fcount:
if cur.Ty is not None:
fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty)
fa: int = _get_type_align(fty)
if fa > max_align:
max_align = fa
cur = cur.Next
i += 1
return max_align
case _:
return 8
# ============================================================
# _translate_union_def — 翻译联合体定义
#
@@ -3003,17 +3062,21 @@ def _translate_method(trans: HT.Translator | t.CPtr,
return 0
# 提取默认参数信息(方法的 args[0] 是 self不含在 param_count 中)
md_defaults: list[ast.AST | t.CPtr] | t.CPtr = None
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__()
# 否则编译器无法识别属性返回的 list 类型GEP base 会变成 i32 0 导致 llc 报错
md_defaults: t.CVoid | t.CPtr = None
md_default_count: int = 0
md_param_count: int = 0
md_args_node: ast.Arguments | t.CPtr = fd.args
if md_args_node is not None:
md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node)
if md_ags.args is not None:
md_param_count = md_ags.args.__len__() - 1
md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args
md_param_count = md_alist.__len__() - 1
if md_ags.defaults is not None:
md_defaults = md_ags.defaults
md_default_count = md_ags.defaults.__len__()
md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults
md_defaults = md_dlist
md_default_count = md_dlist.__len__()
# 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配)
max_funcs: int = 256
@@ -3059,12 +3122,16 @@ def _translate_method(trans: HT.Translator | t.CPtr,
# 进入函数作用域
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
# 注册 self 为 SSA 值(不创建 alloca,不 store
# 这样 self.field 通过 lookup_var 获取 Ptr(struct_ty) 后直接 GEP
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
HandlesVar.define_var(trans.SymTab, "self", self_val)
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
# self 创建 alloca store(与其他参数一致
# 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次
# 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃
self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty)
if self_alloca is not None:
HandlesVar.define_var(trans.SymTab, "self", self_alloca)
# 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用)
HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name)
self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self")
llvmlite.build_store(func_builder, self_val, self_alloca)
# 为其他参数创建 alloca 并 store与普通函数一致跳过索引 0 的 self 参数)
if args_node is not None:

View File

@@ -238,7 +238,10 @@ def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr,
if val_bits != 0 and is_ptr_type(target_ty) != 0:
return llvmlite.build_inttoptr(builder, val, target_ty)
# 指针 → 整数: ptrtoint当目标明确是整数而非指针时
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and is_ptr_type(target_ty) == 0:
# 注意: target_bits == 8 时跳过 ptrtoint走后面的 build_load 解引用首字符
# 修复: buf[idx] = '\0' 中 '\0' 是 CONST_STR → i8* 指针,
# ptrtoint 会截断地址低 8 位(非 0应 load 解引用取首字符 0
if is_ptr_type(val.Ty) != 0 and target_bits != 0 and target_bits != 8 and is_ptr_type(target_ty) == 0:
return llvmlite.build_ptrtoint(builder, val, target_ty)
if val_bits != 0 and target_bits != 0:
if val_bits == target_bits:
@@ -284,8 +287,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
"""创建全局字符串常量并返回 i8* bitcast"""
escaped: t.CChar | t.CPtr = escape_llvm_string(pool, str_val)
if escaped is None:
stdio.printf("[CGS] escape_llvm_string None\n")
stdio.fflush(0)
return None
slen: t.CSizeT = string.strlen(str_val)
@@ -301,8 +302,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
# 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名
gv_name: t.CChar | t.CPtr = pool.alloc(48)
if gv_name is None:
stdio.printf("[CGS] gv_name alloc None\n")
stdio.fflush(0)
return None
if trans.ModuleSha1 is not None:
viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx)
@@ -311,8 +310,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty)
if gv is None:
stdio.printf("[CGS] new_global_variable None name=%s\n", gv_name)
stdio.fflush(0)
return None
llvmlite.module_add_global(mod, gv)
@@ -324,8 +321,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty)
gv_ref_name: t.CChar | t.CPtr = pool.alloc(64)
if gv_ref_name is None:
stdio.printf("[CGS] gv_ref_name alloc None\n")
stdio.fflush(0)
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)
@@ -333,9 +328,6 @@ def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
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)
if bc is None:
stdio.printf("[CGS] build_bitcast None\n")
stdio.fflush(0)
return bc
@@ -350,12 +342,8 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
"""翻译常量int/str/bool"""
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node)
if cn is None:
stdio.printf("[TC] cn is None\n")
stdio.fflush(0)
return None
ck: int = cn.const_kind
stdio.printf("[TC] const_kind=%d\n", ck)
stdio.fflush(0)
if cn.const_kind == ast.CONST_INT:
# 超出 i32 范围则用 i64避免常量创建时被截断
iv: t.CInt64T = cn.int_val
@@ -366,18 +354,15 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
# 浮点常量默认创建为 double64 位),赋值时由 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:
stdio.printf("[TC] CONST_STR but str_val is None\n")
stdio.fflush(0)
return None
stdio.printf("[TC] CONST_STR sv[0]=%d\n", sv[0])
stdio.fflush(0)
r: llvmlite.Value | t.CPtr = create_global_string(builder, pool, mod, sv, trans)
if r is None:
stdio.printf("[TC] create_global_string returned None\n")
stdio.fflush(0)
return r
elif cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0:
@@ -385,32 +370,14 @@ def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
return llvmlite.const_int32(pool, 0)
elif cn.const_kind == ast.CONST_NONE:
# None → i8* null空指针常量用于 `p is None` / `p is not None` 比较
stdio.printf("[TC] NONE step1 Int8\n")
stdio.fflush(0)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
if i8_ty is None:
stdio.printf("[TC] NONE Int8 alloc None\n")
stdio.fflush(0)
return None
stdio.printf("[TC] NONE step2 Ptr\n")
stdio.fflush(0)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
if i8_ptr_ty is None:
stdio.printf("[TC] NONE Ptr alloc None\n")
stdio.fflush(0)
return None
stdio.printf("[TC] NONE step3 ConstNull\n")
stdio.fflush(0)
rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null")
if rv_none is None:
stdio.printf("[TC] NONE ConstNull None\n")
stdio.fflush(0)
else:
stdio.printf("[TC] NONE ok\n")
stdio.fflush(0)
return rv_none
stdio.printf("[TC] unknown const_kind=%d\n", ck)
stdio.fflush(0)
return None
@@ -632,12 +599,6 @@ def translate_value(builder: llvmlite.IRBuilder | t.CPtr,
k: int = node.kind()
if k == ast.ASTKind.Constant:
rv: llvmlite.Value | t.CPtr = translate_constant(builder, pool, mod, node, trans)
if rv is None:
stdio.printf("[TV] Constant returned None\n")
stdio.fflush(0)
else:
stdio.printf("[TV] Constant ok\n")
stdio.fflush(0)
return rv
elif k == ast.ASTKind.Name:
return translate_name_value(builder, pool, node, trans)
@@ -686,24 +647,25 @@ def translate_ifexp(builder: llvmlite.IRBuilder | t.CPtr,
func: llvmlite.Function | t.CPtr = trans._cur_func
if func is None:
stdio.printf("[IFEXP] func=None\n")
stdio.fflush(0)
return None
# 1. 求值条件
cond_val: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, ie.test, None, 0, trans)
if cond_val is None:
stdio.printf("[IFEXP] cond_val=None\n")
stdio.fflush(0)
return None
# 转换为 i1
cond_bits: int = get_llvm_type_bits(cond_val.Ty)
if cond_bits == 1:
cond_i1: llvmlite.Value | t.CPtr = cond_val
else:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
if is_ptr_type(cond_val.Ty) != 0:
# 指针类型:与 null 比较
null_cond: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, cond_val.Ty, "null")
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, null_cond)
else:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero)
# 2. 创建三个基本块
cnt: int = trans._label_counter
@@ -818,14 +780,10 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
comparators: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators
if comparators is None or comparators.__len__() == 0:
stdio.printf("[CMP] comparators empty\n")
stdio.fflush(0)
return None
rhs: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, comparators.get(0), None, 0, trans)
if rhs is None:
stdio.printf("[CMP] rhs=None\n")
stdio.fflush(0)
return None
# === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 ===
@@ -846,8 +804,6 @@ def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
lhs: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, cmp.left, None, 0, trans)
if lhs is None:
stdio.printf("[CMP] lhs=None\n")
stdio.fflush(0)
return None
# === 比较运算符重载路径 2: lhs 是 Ptr(Struct) ===
@@ -933,7 +889,11 @@ def translate_unaryop(builder: llvmlite.IRBuilder | t.CPtr,
# +x = x
return operand
elif uo.op == ast.OpKind.Not:
# not x = (x == 0),返回 i1
# not x = (x == 0/null),返回 i1
if is_ptr_type(operand.Ty) != 0:
# 指针类型:与 null 比较
null_op: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, operand.Ty, "null")
return llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, operand, null_op)
operand_bits_not: int = get_llvm_type_bits(operand.Ty)
zero = llvmlite.const_int32(pool, 0)
if operand_bits_not == 64:
@@ -1009,12 +969,17 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
if val is None:
return None
# 转为 i1已经是 i1 的直接用,否则与 0 比较)
# 转为 i1已经是 i1 的直接用,否则与 0/null 比较)
val_bits: int = get_llvm_type_bits(val.Ty)
val_i1: llvmlite.Value | t.CPtr = val
if val_bits != 1:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero)
if is_ptr_type(val.Ty) != 0:
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, val.Ty, "null")
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, null_val)
else:
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero)
# 创建 next BB求值下一个值
cnt = builder.Counter
@@ -1051,8 +1016,13 @@ def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
last_bits: int = get_llvm_type_bits(last_val.Ty)
last_i1: llvmlite.Value | t.CPtr = last_val
if last_bits != 1:
zero = llvmlite.const_int32(pool, 0)
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero)
if is_ptr_type(last_val.Ty) != 0:
# 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配)
null_val2: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, last_val.Ty, "null")
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, null_val2)
else:
zero = llvmlite.const_int32(pool, 0)
last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero)
llvmlite.build_br(builder, merge_bb)
@@ -1147,33 +1117,27 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
name: str,
from_imports: str) -> int:
"""跨模块查找 CDefine 常量,返回值或 -1未找到"""
# [XMOD-CD] 诊断:记录跨模块 CDefine 查找入口
_xmod_log_buf: str = pool.alloc(512)
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] enter name=%s from_imports=%s\n", name, from_imports)
_xmod_lf: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf.closed:
_xmod_lf.write_str(_xmod_log_buf)
_xmod_lf.close()
if name is None or from_imports is None:
stdio.printf("[XMCD] FAIL name=%s reason=from_imports_is_none\n", name)
return -1
# 1. 从 from_imports 查找名称对应的模块名
# allow_star_fallback=1: CDefine 常量(如 INVALID_HANDLE_VALUE通过
# from w32.win32base import * 导入,不会作为精确条目出现在 from_imports 中,
# 而是作为 *:w32.win32base 条目。必须启用 star import 回退才能找到源模块。
mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 1)
# 先尝试精确匹配(allow_star_fallback=0避免 CDefine 常量被 star import 误导
mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 0)
if mod_name_raw is None:
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step1 mod=None name=%s\n", name)
_xmod_lf2: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf2.closed:
_xmod_lf2.write_str(_xmod_log_buf)
_xmod_lf2.close()
return -1
# 精确匹配失败:尝试 star import 回退
# CDefine 常量(如 INVALID_HANDLE_VALUE通过 from w32.win32base import * 导入,
# 不会作为精确条目出现在 from_imports 中,而是作为 *:w32.win32base 条目。
mod_name_raw = HandlesImports.lookup_from_import(from_imports, name, 1)
if mod_name_raw is None:
stdio.printf("[XMCD] FAIL name=%s reason=lookup_from_import_returned_none\n", name)
return -1
stdio.printf("[XMCD] star_fallback name=%s mod=%s\n", name, mod_name_raw)
# 打印 from_imports 用于诊断精确匹配失败原因
fi_len: t.CSizeT = string.strlen(from_imports)
stdio.printf("[XMCD] from_imports (len=%d): %s\n", fi_len, from_imports)
else:
stdio.printf("[XMCD] exact_match name=%s mod=%s\n", name, mod_name_raw)
# 2. 复制模块名到新缓冲区lookup_from_import 返回的是内部指针)
# 截断于空格、null、或 ':'(别名格式的分隔符)
@@ -1197,29 +1161,9 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
if sha1 is None:
sha1 = HandlesExprCall._lookup_module_sha1_suffix(base_mod)
if sha1 is None:
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FAIL step4 sha1=None base_mod=%s\n", base_mod)
_xmod_lf3: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf3.closed:
_xmod_lf3.write_str(_xmod_log_buf)
_xmod_lf3.close()
stdio.printf("[XMCD] FAIL name=%s base_mod=%s reason=sha1_not_found\n", name, base_mod)
return -1
# [XMOD-CD] 诊断:记录 SHA1 查找成功
if _xmod_log_buf is not None:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] ok step4 base_mod=%s sha1=%s\n", base_mod, sha1)
_xmod_lf4: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf4.closed:
_xmod_lf4.write_str(_xmod_log_buf)
_xmod_lf4.close()
# 4.5 优先查全局跨模块 CDefine 表(编译期注册,无需文件 I/O
gcdef_val: int = HandlesType.lookup_global_cdefine(sha1, name)
if HandlesType.is_cdefine_found() != 0:
return gcdef_val
# 5. 获取 temp_dir
temp_dir: str = HandlesType.get_temp_dir()
if temp_dir is None:
@@ -1271,44 +1215,14 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
VLogger.error(err_buf, "XMOD-CD")
stdlib.free(pyi_buf)
return -1
# [XMOD-CD] 诊断:记录 src_path
_xmod_dbg_sp2: str = pool.alloc(512)
if _xmod_dbg_sp2 is not None:
viperlib.snprintf(_xmod_dbg_sp2, 512,
"[XMOD-CD] py-fallback src_path=%s sha1=%s\n", src_path, sha1)
_xmod_lf_sp2: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_sp2.closed:
_xmod_lf_sp2.write_str(_xmod_dbg_sp2)
_xmod_lf_sp2.close()
pf = fileio.File(src_path, fileio.MODE.R)
stdlib.free(src_path)
if pf.closed:
# [XMOD-CD] 诊断:文件打开失败
_xmod_dbg_fc: str = pool.alloc(512)
if _xmod_dbg_fc is not None:
viperlib.snprintf(_xmod_dbg_fc, 512,
"[XMOD-CD] FAIL file-closed sha1=%s\n", sha1)
_xmod_lf_fc: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_fc.closed:
_xmod_lf_fc.write_str(_xmod_dbg_fc)
_xmod_lf_fc.close()
stdlib.free(pyi_buf)
return -1
bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE)
pf.close()
if bytes_read <= 0:
# [XMOD-CD] 诊断:文件读取失败
_xmod_dbg_br: str = pool.alloc(512)
if _xmod_dbg_br is not None:
viperlib.snprintf(_xmod_dbg_br, 512,
"[XMOD-CD] FAIL bytes_read=%d sha1=%s\n", bytes_read, sha1)
_xmod_lf_br: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_br.closed:
_xmod_lf_br.write_str(_xmod_dbg_br)
_xmod_lf_br.close()
stdlib.free(pyi_buf)
return -1
if bytes_read < PYI_READ_BUF_SIZE:
@@ -1320,25 +1234,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
# 格式: NAME: t.CDefine = value
name_len: t.CSizeT = string.strlen(name)
total_len: t.CSizeT = string.strlen(pyi_buf)
# [XMOD-CD] 诊断:记录文件读取结果和 total_len
_xmod_dbg1: str = pool.alloc(512)
if _xmod_dbg1 is not None:
_dbg_first80: str = pool.alloc(81)
if _dbg_first80 is not None:
_dbg_n: int = 0
while _dbg_n < 80 and _dbg_n < total_len:
_dbg_first80[_dbg_n] = pyi_buf[_dbg_n]
_dbg_n += 1
_dbg_first80[_dbg_n] = '\0'
else:
_dbg_first80 = "<alloc-fail>"
viperlib.snprintf(_xmod_dbg1, 512, "[XMOD-CD] file-read name=%s bytes_read=%d total_len=%d first80=%.80s\n",
name, bytes_read, total_len, _dbg_first80)
_xmod_lf_d1: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_d1.closed:
_xmod_lf_d1.write_str(_xmod_dbg1)
_xmod_lf_d1.close()
pos: t.CSizeT = 0
result_val: int = 0
result_found: int = 0
@@ -1393,7 +1288,29 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
eq_pos += 1
# 解析整数值(支持十六进制 0x 前缀)
# 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / t.CInt(...) 等类型构造函数
# 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF)
# 如果是,跳过 "t.CXxx(" 前缀,解析括号内的值,忽略结尾 ')'
is_type_ctor: int = 0
if eq_pos + 2 < line_start + line_len:
if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.':
# 找到 '(' 的位置
paren_pos: t.CSizeT = eq_pos + 2
while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(':
paren_pos += 1
if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(':
is_type_ctor = 1
eq_pos = paren_pos + 1 # 跳过 '('
# 跳过括号内可能的前导空格
while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ':
eq_pos += 1
# 解析整数值(支持十六进制 0x 前缀和负号)
# 负号标记
is_neg: int = 0
if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-':
is_neg = 1
eq_pos += 1
val_str_start: t.CSizeT = eq_pos
val_str_len: t.CSizeT = 0
is_hex: int = 0
@@ -1447,9 +1364,13 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
break
hex_result = hex_result * 16 + hd
result_val = hex_result
# 十六进制负值(如 0xFFFFFFFF保持原样由 32 位截断处理
result_found = 1
else:
result_val = string.atoi(val_buf)
# 应用负号(如 t.CUnsignedLong(-11) → -11
if is_neg != 0:
result_val = -result_val
result_found = 1
break
@@ -1488,26 +1409,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
if rc_sub_len == 0:
continue
# [XMOD-CD] 诊断:记录找到的 from . 行和子模块名
_xmod_dbg_rc: str = pool.alloc(512)
if _xmod_dbg_rc is not None:
_rc_sub_buf_dbg: str = pool.alloc(rc_sub_len + 1)
if _rc_sub_buf_dbg is not None:
_rc_si2: t.CSizeT
for _rc_si2 in range(rc_sub_len):
_rc_sub_buf_dbg[_rc_si2] = pyi_buf[rc_sub_start + _rc_si2]
_rc_sub_buf_dbg[rc_sub_len] = '\0'
else:
_rc_sub_buf_dbg = "<alloc-fail>"
viperlib.snprintf(_xmod_dbg_rc, 512,
"[XMOD-CD] rc-from-line name=%s sub=%s rc_line_start=%d rc_line_len=%d\n",
name, _rc_sub_buf_dbg, rc_line_start, rc_line_len)
_xmod_lf_rc: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_rc.closed:
_xmod_lf_rc.write_str(_xmod_dbg_rc)
_xmod_lf_rc.close()
# 检查行是否包含 "import"
rc_has_import: int = 0
rc_ipos: t.CSizeT = rc_sub_end
@@ -1594,18 +1495,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
rc_name_match = 1
rc_cpos += 1
# [XMOD-CD] 诊断:记录 NAME 匹配结果
_xmod_dbg_match: str = pool.alloc(512)
if _xmod_dbg_match is not None:
viperlib.snprintf(_xmod_dbg_match, 512,
"[XMOD-CD] rc-match name=%s star=%d name_match=%d has_paren=%d rc_scan_end=%d rc_imp_start=%d\n",
name, rc_star, rc_name_match, rc_has_paren, rc_scan_end, rc_imp_start)
_xmod_lf_m: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_m.closed:
_xmod_lf_m.write_str(_xmod_dbg_match)
_xmod_lf_m.close()
if rc_star == 0 and rc_name_match == 0:
continue
@@ -1632,18 +1521,6 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
continue
viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod)
# [XMOD-CD] 诊断:记录递归调用前的状态
_xmod_dbg_recurse: str = pool.alloc(512)
if _xmod_dbg_recurse is not None:
viperlib.snprintf(_xmod_dbg_recurse, 512,
"[XMOD-CD] rc-recurse name=%s full_mod=%s fi=%s star=%d name_match=%d has_paren=%d scan_end=%d\n",
name, rc_full_mod, rc_fi, rc_star, rc_name_match, rc_has_paren, rc_scan_end)
_xmod_lf_rec: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf_rec.closed:
_xmod_lf_rec.write_str(_xmod_dbg_recurse)
_xmod_lf_rec.close()
# 递归调用查找子模块
rc_sub_val: int = _lookup_cross_module_cdefine(pool, name, rc_fi)
if HandlesType.is_cdefine_found() != 0:
@@ -1659,21 +1536,37 @@ def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
else:
HandlesType.set_cdefine_found(0)
# [XMOD-CD] 诊断:记录查找结果
if _xmod_log_buf is not None:
if result_found != 0:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] FOUND name=%s val=%d base_mod=%s\n", name, result_val, base_mod)
else:
viperlib.snprintf(_xmod_log_buf, 512, "[XMOD-CD] NOTFOUND name=%s base_mod=%s sha1=%s\n", name, base_mod, sha1)
_xmod_lf5: fileio.File | t.CPtr = fileio.File(
"d:/Users/TermiNexus/Desktop/TransPyC/_xmod_cdefine.log", fileio.MODE.A)
if not _xmod_lf5.closed:
_xmod_lf5.write_str(_xmod_log_buf)
_xmod_lf5.close()
return result_val
# ============================================================
# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定
#
# CDefine 常量(如 FOREGROUND_GREEN, STD_OUTPUT_HANDLE, SCOPE_MODULE
# 都遵循 ALL_CAPS 约定:仅含大写字母 A-Z、数字 0-9、下划线 _
# 且至少含一个大写字母。
#
# Python 关键字match, if, for和变量名self, pool, builder
# 都含小写字母,不会匹配,从而避免 fail-fast 误报。
#
# 返回: 1=符合 CDefine 命名约定, 0=不符合
# ============================================================
def _is_cdefine_name_pattern(name: str) -> int:
"""检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)"""
if name is None:
return 0
has_upper: int = 0
i: t.CSizeT = 0
while name[i] != '\0':
c: t.CChar = name[i]
if c >= 'a' and c <= 'z':
return 0
if c >= 'A' and c <= 'Z':
has_upper = 1
i += 1
return has_upper
# ============================================================
# 翻译变量引用Name 节点)→ load
# ============================================================
@@ -1690,27 +1583,21 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
return None
# CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码)
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到全局
# NAME: t.CDefine = value 形式定义的常量在编译期已注册到本地
cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id)
if HandlesType.is_cdefine_found() != 0:
return llvmlite.const_int32(pool, cdef_val)
# 本地 CDefine 表未找到:尝试跨模块查找
# 对于 from w32.win32base import * 导入的 INVALID_HANDLE_VALUE 等常量
# CDefine 表在模块切换时被清空,需要从 from_imports 查找来源模块并读取 .pyi
if trans is not None:
if trans._from_imports is not None:
# 本地表未找到:尝试跨模块 .pyi 查找(保证多模块查表存表一致)
# 仅对符合 CDefine 命名约定ALL_CAPS的名字触发跨模块查找
# 避免对普通变量名mb/name/ptr/pool/self 等)误触发,造成严重性能损耗
if _is_cdefine_name_pattern(nm_id) != 0:
if trans is not None and trans._from_imports is not None:
cdef_val = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
if HandlesType.is_cdefine_found() != 0:
return llvmlite.const_int32(pool, cdef_val)
# 模块别名检查:如果 nm_id 是已导入模块名(如 win32file, fileio
# 不应被当作普通变量或全局变量,返回 None 让上层处理
if trans is not None and trans._imported_modules is not None:
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
return None
# global 变量:从模块作用域查找
# global 变量从模块作用域查找global 声明优先级最高)
if trans is not None:
if HT.is_global_name(trans, nm_id) != 0:
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
@@ -1727,23 +1614,40 @@ def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
if HT.is_nonlocal_name(trans, nm_id) != 0:
return HandlesNonlocal.load_nonlocal_var(trans, nm_id)
# 局部变量查找(必须先于模块别名检查)
# 否则与模块同名的局部变量(如 `import t, c` 后的局部变量 c会被误判为模块别名
# 导致 SymTab 已注册的局部变量查找不到rhs_val is None bug 根因)
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm_id)
if alloca is None:
# 跨模块 CDefine 查找(仅当 Name 不是任何变量时才尝试):
# 从 from_imports 解析源模块,再从该模块的 pyi 文件中解析 CDefine 常量值
# (如 FLAG_IS_ASYNC 从 base.py 导入)
if trans is not None and trans._from_imports is not None:
cross_val: int = _lookup_cross_module_cdefine(pool, nm_id, trans._from_imports)
if cross_val >= 0:
return llvmlite.const_int32(pool, cross_val)
return None
if alloca is not None:
load_ty: llvmlite.LLVMType | t.CPtr = None
if alloca.Ty is not None:
load_ty = alloca.Ty.Pointee
if load_ty is None:
load_ty = llvmlite.Int32(pool)
return llvmlite.build_load(builder, load_ty, alloca)
load_ty: llvmlite.LLVMType | t.CPtr = None
if alloca.Ty is not None:
load_ty = alloca.Ty.Pointee
if load_ty is None:
load_ty = llvmlite.Int32(pool)
return llvmlite.build_load(builder, load_ty, alloca)
# 模块别名检查SymTab 查找失败后才检查
# 如果 nm_id 是已导入模块名(如 win32file, fileio且未被声明为局部变量
# 返回 None 让上层处理(用于属性访问 win32file.CreateFileA
if trans is not None and trans._imported_modules is not None:
if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0:
return None
# 所有查找路径均失败
# fail-fast: 仅对符合 CDefine 命名约定ALL_CAPS的名字报错
# 避免对 match/self/pool 等关键字和变量名误报
# 跨模块 CDefine 查找已在上方完成,此处不重复
if _is_cdefine_name_pattern(nm_id) != 0:
err_buf2: str = pool.alloc(256)
if err_buf2 is not None:
cur_sha1: str = "(unknown)"
if trans is not None and trans.ModuleSha1 is not None:
cur_sha1 = trans.ModuleSha1
viperlib.snprintf(err_buf2, 256,
"[CD] FATAL: Name '%s' NOT found (CDefine local+cross + global + nonlocal + alloca + module alias) in module sha1=%s\n",
nm_id, cur_sha1)
VLogger.error(err_buf2, "CD")
return None
# ============================================================
@@ -1989,22 +1893,11 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
if nm.id is not None and trans is not None:
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
if alloca is None:
stdio.printf("[TS] alloca=None var=%s\n", nm.id)
stdio.fflush(0)
elif alloca.Ty is None:
stdio.printf("[TS] alloca.Ty=None var=%s\n", nm.id)
stdio.fflush(0)
if alloca is not None and alloca.Ty is not None:
if is_ptr_type(alloca.Ty) != 0:
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
if pointee is None:
stdio.printf("[TS] pointee=None var=%s\n", nm.id)
stdio.fflush(0)
if pointee is not None:
# 不调用 pointee.kind() 避免跨模块引用 LLVMType.kind 符号
stdio.printf("[TS] var=%s pointee_not_null\n", nm.id)
stdio.fflush(0)
# 单层 match避免嵌套 match 的编译器 bug
match pointee:
case llvmlite.LLVMType.Array(elem_ty, count):
@@ -2015,8 +1908,6 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
return llvmlite.build_load(builder, elem_ty, elem_ptr)
return None
case llvmlite.LLVMType.Ptr(inner_ty):
stdio.printf("[TS] matched Ptr var=%s\n", nm.id)
stdio.fflush(0)
# 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct
# list 的 subscript 应该走 __getitem__ 内联路径,而非指针遍历
list_struct_name: str = None
@@ -2064,32 +1955,16 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
# 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr):
# 优先转发到 __getitem__避免 IsPtrElement 误判为指针遍历
cls_nm_rd_ptr: str = _get_custom_struct_cls_nm(pool, inner_ty)
if cls_nm_rd_ptr is None:
stdio.printf("[TS] cls_nm=None var=%s\n", nm.id)
stdio.fflush(0)
if not (cls_nm_rd_ptr is None):
stdio.printf("[TS] cls_nm=%s var=%s\n", cls_nm_rd_ptr, nm.id)
stdio.fflush(0)
stdio.printf("[TS] pre_getitem cls=%s\n", cls_nm_rd_ptr)
stdio.fflush(0)
obj_ptr_rd: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, pointee, alloca)
if obj_ptr_rd is None:
stdio.printf("[TS] __getitem__ build_load=None\n")
stdio.fflush(0)
if not (obj_ptr_rd is None):
arg_vals_rd_p: t.CSizeT | t.CPtr = pool.alloc(8)
if arg_vals_rd_p is None:
stdio.printf("[TS] __getitem__ alloc=None\n")
stdio.fflush(0)
if not (arg_vals_rd_p is None):
arg_vals_rd_p[0] = t.CSizeT(idx_val)
ret_rd_p: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr(
pool, builder, mod, cls_nm_rd_ptr, "__getitem__",
obj_ptr_rd, arg_vals_rd_p, 1, trans)
if ret_rd_p is None:
stdio.printf("[TS] __getitem__ call=None cls=%s\n", cls_nm_rd_ptr)
stdio.fflush(0)
if not (ret_rd_p is None):
return ret_rd_p
return None
@@ -2493,11 +2368,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans)
if obj_ptr is None or obj_ptr.Ty is None:
if at.value.kind() == ast.ASTKind.Name:
nm_d: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value)
if nm_d.id is not None:
stdio.printf("[TA-DIAG] obj_ptr=None attr=%s name=%s\n",
at.attr, nm_d.id)
return None
# 如果 obj_ptr 是 Ptr(Ptr(Struct))X|t.CPtr 变量的 alloca
@@ -2540,29 +2410,15 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry(
trans.SymTab, nm_fb.id)
if var_entry is not None and var_entry.AnnotClassName is not None:
stdio.printf("[TA-DIAG] fallback annot=%s attr=%s\n",
var_entry.AnnotClassName, at.attr)
cur_sha1: str = trans.ModuleSha1
field_info = HandlesStruct.lookup_field_by_class(
var_entry.AnnotClassName, at.attr, cur_sha1)
if field_info is None:
stdio.printf("[TA-DIAG] lfbc_failed annot=%s attr=%s\n",
var_entry.AnnotClassName, at.attr)
stdio.fflush(0)
else:
stdio.printf("[TA-DIAG] lfbc_ok annot=%s attr=%s idx=%d\n",
var_entry.AnnotClassName, at.attr, field_info.Index)
stdio.fflush(0)
# 回退 1 成功bitcast obj_ptr 到 AnnotClassName 对应的结构体类型
# 原始 struct_ty 可能是 i8X|t.CPtr 简化为 Ptr(i8)
# 需用实际结构体类型做 GEP否则 GEP i8 失败
if field_info is not None:
annot_se: HandlesStruct.StructEntry | t.CPtr = \
HandlesStruct.find_struct(var_entry.AnnotClassName)
if annot_se is None:
stdio.printf("[TA-DIAG] fb1 find_struct None annot=%s\n",
var_entry.AnnotClassName)
stdio.fflush(0)
if annot_se is not None and annot_se.Ty is not None:
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \
llvmlite.Ptr(pool, annot_se.Ty)
@@ -2576,11 +2432,6 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
# (原始 struct_ty 可能是 i8ensure 无效)
HandlesStruct.ensure_struct_def_in_module(
pool, mod, annot_se.Ty)
stdio.printf("[TA-DIAG] fb1 struct_ty updated\n")
stdio.fflush(0)
else:
stdio.printf("[TA-DIAG] fb1 bitcast None\n")
stdio.fflush(0)
# 回退 2: 子类搜索 — 注解类型是基类但实际值是派生类
# 如 node: AST | t.CPtr = If(...),访问 node.orelse
if field_info is None:
@@ -2615,29 +2466,14 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
return None
# 普通结构体GEP + load
field_idx: int = field_info.Index
stdio.printf("[TA-DIAG] gep_try idx=%d struct_is_ptr=%d\n",
field_idx, is_ptr_type(struct_ty))
stdio.fflush(0)
field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct(
builder, struct_ty, field_ty, obj_ptr, field_idx)
if field_ptr is None:
stdio.printf("[TA-DIAG] gep_failed idx=%d\n", field_idx)
stdio.fflush(0)
if field_ptr is not None:
stdio.printf("[TA-DIAG] gep_ok idx=%d is_array=%d\n",
field_idx, is_array_type(field_ty))
stdio.fflush(0)
# 数组类型字段不能 load 为 SSA value直接返回字段指针
# 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素
if is_array_type(field_ty) != 0:
return field_ptr
stdio.printf("[TA-DIAG] pre_load idx=%d field_ty_not_null=%d\n",
field_idx, 1 if field_ty is not None else 0)
stdio.fflush(0)
loaded_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, field_ty, field_ptr)
stdio.printf("[TA-DIAG] post_load idx=%d loaded=%d\n",
field_idx, 1 if loaded_val is not None else 0)
stdio.fflush(0)
# 联合类型字段(如 Token | t.CPtr被编译为 i8*
# 若 AnnotClassName 指示了具体结构体类型bitcast 为正确的结构体指针
if loaded_val is not None and field_info.AnnotClassName is not None:
@@ -2647,17 +2483,8 @@ def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty)
return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty)
return loaded_val
# 诊断:所有字段查找路径失败
sn_diag: str = HandlesStruct._extract_struct_name(struct_ty)
if sn_diag is not None:
stdio.printf("[TA-DIAG] field=None attr=%s sname=%s\n",
at.attr, sn_diag)
else:
stdio.printf("[TA-DIAG] field=None attr=%s sname=(null)\n",
at.attr)
return None
case _:
stdio.printf("[TA-DIAG] type_mismatch attr=%s\n", at.attr)
return None
# ============================================================
@@ -2686,34 +2513,17 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value)
if nm.id is not None and trans is not None:
alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id)
if alloca is None:
stdio.printf("[GSP] alloca=None var=%s\n", nm.id)
stdio.fflush(0)
elif alloca.Ty is None:
stdio.printf("[GSP] alloca.Ty=None var=%s\n", nm.id)
stdio.fflush(0)
if alloca is not None and alloca.Ty is not None:
if is_ptr_type(alloca.Ty) != 0:
pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
if pointee is None:
stdio.printf("[GSP] pointee=None var=%s\n", nm.id)
stdio.fflush(0)
if pointee is not None:
pe_arr: int = is_array_type(pointee)
pe_ptr: int = is_ptr_type(pointee)
stdio.printf("[GSP] var=%s pe_arr=%d pe_ptr=%d\n", nm.id, pe_arr, pe_ptr)
stdio.fflush(0)
# 单层 match避免嵌套 match 的编译器 bug
match pointee:
case llvmlite.LLVMType.Array(elem_ty, count):
stdio.printf("[GSP] matched Array\n")
stdio.fflush(0)
# 数组遍历
return llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca, idx_val)
case llvmlite.LLVMType.Ptr(inner_ty):
stdio.printf("[GSP] matched Ptr\n")
stdio.fflush(0)
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针,
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
# 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。
@@ -2731,9 +2541,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
if cls_nm_ptr_chk is None:
pass
if not (cls_nm_ptr_chk is None):
stdio.printf("[GSP] custom struct %s, defer to __setitem__\n",
cls_nm_ptr_chk)
stdio.fflush(0)
return None
# bytes|t.CPtr / str|t.CPtr: alloca 是 i8**
# 直接 GEP 按 i8* 步长8 字节),不 load
@@ -2742,39 +2549,26 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
ve_pe: HandlesVar.VarEntry | t.CPtr = \
HandlesVar.lookup_var_entry(trans.SymTab, nm.id)
if ve_pe is not None and ve_pe.IsPtrElement == 1:
stdio.printf("[GSP] IsPtrElement=1, gep direct\n")
stdio.fflush(0)
return llvmlite.build_gep(
builder, pointee, alloca, idx_val)
# 普通指针遍历: 先 load 指针值,再 GEP
ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
builder, pointee, alloca)
if ptr_val is None:
stdio.printf("[GSP] build_load=None\n")
stdio.fflush(0)
return None
gep_r: llvmlite.Value | t.CPtr = llvmlite.build_gep(
builder, inner_ty, ptr_val, idx_val)
if gep_r is None:
stdio.printf("[GSP] build_gep=None\n")
stdio.fflush(0)
return gep_r
case _:
# pointee 是普通标量类型 (如 i64, i32, i8):
# alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针
# 支持 arg_vals[i] = val 这类参数数组下标赋值
stdio.printf("[GSP] matched scalar, gep direct\n")
stdio.fflush(0)
return llvmlite.build_gep(builder, pointee, alloca, idx_val)
# 通用路径
stdio.printf("[GSP] fallback to generic path\n")
stdio.fflush(0)
ptr_val: llvmlite.Value | t.CPtr = translate_value(
builder, pool, mod, sub.value, None, 0, trans)
if ptr_val is None or ptr_val.Ty is None:
stdio.printf("[GSP] generic: ptr_val=None\n")
stdio.fflush(0)
return None
if is_ptr_type(ptr_val.Ty) != 0:
elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
@@ -2792,9 +2586,6 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
if cls_nm_gen is None:
pass
if not (cls_nm_gen is None):
stdio.printf("[GSP] generic custom struct %s, defer to __setitem__\n",
cls_nm_gen)
stdio.fflush(0)
return None
# 指针类型: 单索引 GEP (getelementptr ty, ptr, idx)
return llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val)

View File

@@ -362,29 +362,49 @@ def _ensure_c_lib_declare(pool: memhub.MemBuddy | t.CPtr,
# ============================================================
def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name: str) -> llvmlite.LLVMType | t.CPtr:
"""根据函数名推断外部 includes 函数的返回类型"""
"""根据函数名推断外部 includes 函数的返回类型
支持三种函数名形式:
1. 裸名: "parse", "strlen"
2. 别名: "json_parse"from X import parse as json_parse
3. 带 SHA1 前缀: "240a9a4157959a9f.parse"(跨模块调用 mangled name
"""
if pool is None or func_name is None:
return llvmlite.Int32(pool)
# 提取裸函数名:去掉 SHA1 前缀(如 "240a9a4157959a9f.parse" → "parse"
# SHA1 前缀是 16 位十六进制 + '.',检查是否有 '.' 分隔
bare_name: str = func_name
dot_pos: str = string.strrchr(func_name, 46) # 46 = ord('.')
if dot_pos is not None:
# '.' 后的部分是裸函数名
bare_name = dot_pos + 1
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 返回 i8* 的函数(指针返回值,截断会导致错误)
if func_name == "strchr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "strrchr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "strstr":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "strcpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "strncpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "memset":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "memset32":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "memcpy":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "memmove":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if bare_name == "strchr" or func_name == "strchr":
return i8_ptr_ty
if bare_name == "strrchr" or func_name == "strrchr":
return i8_ptr_ty
if bare_name == "strstr" or func_name == "strstr":
return i8_ptr_ty
if bare_name == "strcpy" or func_name == "strcpy":
return i8_ptr_ty
if bare_name == "strncpy" or func_name == "strncpy":
return i8_ptr_ty
if bare_name == "memset" or func_name == "memset":
return i8_ptr_ty
if bare_name == "memset32" or func_name == "memset32":
return i8_ptr_ty
if bare_name == "memcpy" or func_name == "memcpy":
return i8_ptr_ty
if bare_name == "memmove" or func_name == "memmove":
return i8_ptr_ty
# JSON 解析函数返回 JsonValue*(指针)
# from json.__parser import parse as json_parse → 别名 json_parse 也需覆盖
if bare_name == "parse" or func_name == "parse" or func_name == "json_parse":
return i8_ptr_ty
# MemBuddy 方法(当类型信息丢失时可能走外部函数路径)
if func_name == "alloc":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
@@ -394,6 +414,14 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "alloc_buf":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# VLogger 模块函数(跨模块调用时 stub 未注入,返回指针被截断为 i32 导致崩溃)
if func_name == "get_logger":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
if func_name == "fmt_buf":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏)
if func_name == "get_includes_binary_dir":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 返回 i64 的函数
if func_name == "strlen":
@@ -442,6 +470,17 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return i8_ptr_ty
if func_name == "LoadLibraryW":
return i8_ptr_ty
# Win32 Handle 返回函数HANDLE = void* = i8*
if func_name == "GetStdHandle":
return i8_ptr_ty
if func_name == "CreateFileA":
return i8_ptr_ty
if func_name == "CreateFileW":
return i8_ptr_ty
if func_name == "FindFirstFileA":
return i8_ptr_ty
if func_name == "FindFirstFileW":
return i8_ptr_ty
# Win32 API 返回 i64 (SIZE_T) 的函数
if func_name == "VirtualQuery":
@@ -486,7 +525,11 @@ def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name == "function_get_param_head" or func_name == "param_get_next":
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# 默认 i32
# 默认 i32整数与本模块函数定义的默认返回类型一致HandlesFunctions.py line 324
# 已知返回指针的函数在上方显式列出(返回 i8*),已知返回 i64 的函数也显式列出
# 避免使用 i64 导致 stub 声明declare i64与实际定义define i32类型不匹配
# x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致
# 与 _infer_method_ret_ty 的默认策略保持一致
return llvmlite.Int32(pool)
# ============================================================
@@ -2154,6 +2197,29 @@ def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr,
if ctor_entry is not None:
is_oop = ctor_entry.IsOOP
# 跨模块 OOP 类推断IsOOP 可能未设置Phase1 缓存跳过 _translate_oop_methods
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
init_lookup_name: t.CChar | t.CPtr = pool.alloc(128)
if init_lookup_name is not None:
viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
init_found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, init_lookup_name)
if init_found_func is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
init_defaults_entry: FuncDefaultsEntry | t.CPtr = find_func_defaults(init_lookup_name)
if init_defaults_entry is not None:
is_oop = 1
if ctor_entry is not None:
ctor_entry.IsOOP = 1
ctor_entry.HasInit = 1
if is_oop != 0:
# 存储指针:默认用 alloca如果有 __new__ 则用 __new__ 返回的指针
storage_ptr: llvmlite.Value | t.CPtr = tmp
@@ -2773,7 +2839,13 @@ def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
ret_ty: llvmlite.LLVMType | t.CPtr,
param_head: llvmlite.ParamNode | t.CPtr,
param_count: int):
"""为跨模块方法调用创建 declare 声明"""
"""为跨模块方法调用创建 declare 声明
若模块中已存在同名 declare 且参数数量较少(例如 File.__init__ 的
stub 仅 3 个参数,而实际调用传入 4 个),则向现有 declare 追加缺失
参数,避免 llc 报 `argument invalid for parameter type` 之类的错误。
已存在的 define 不修改(其参数由定义决定)。
"""
if pool is None or mod is None or call_name is None:
return
# 检查模块中是否已有同名函数declare 或 define
@@ -2781,7 +2853,32 @@ def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
while existing is not None:
if existing.Name is not None:
if string.strcmp(existing.Name, call_name) == 0:
return # 已存在,无需重复声明
# 已存在:仅当是 declare 且参数数量不足时追加缺失参数
if existing.IsDeclared == 1:
# 遍历现有参数链表计数(避免依赖 GSList.Count 字段的类型推断)
cur_count: int = 0
cur_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(existing)
while cur_p is not None:
cur_count += 1
cur_p = cur_p.Next
# 只追加缺失的参数cur_count < param_count 时)
if cur_count < param_count:
# 定位到 param_head 的第 cur_count 个节点开始追加
pnode2: llvmlite.ParamNode | t.CPtr = param_head
pi2: int = 0
# 跳过已有的 cur_count 个参数
while pnode2 is not None and pi2 < cur_count:
pnode2 = pnode2.Next
pi2 += 1
# 追加剩余参数
while pnode2 is not None and pi2 < param_count:
if pnode2.Ty is not None:
param2: llvmlite.Param | t.CPtr = llvmlite.new_param(pool, pnode2.Ty, None)
if param2 is not None:
llvmlite.function_add_param(existing, param2)
pnode2 = pnode2.Next
pi2 += 1
return
existing = existing.Next
# 创建函数声明
func: llvmlite.Function | t.CPtr = llvmlite.new_function(pool, call_name, ret_ty)
@@ -2832,18 +2929,35 @@ def _infer_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
return i8_ptr_ty
if string.strcmp(method_name, "__enter__") == 0:
return i8_ptr_ty
# 工厂方法:返回对象指针(截断会导致后续方法调用崩溃)
if string.strcmp(method_name, "parse_args") == 0:
return i8_ptr_ty
# 魔术方法:返回对象指针(如 JsonValue.__getitem__ 返回 JsonValue*
if string.strcmp(method_name, "__getitem__") == 0:
return i8_ptr_ty
# 返回 i8* 的方法(返回字符串/类型名/描述)
if string.strcmp(method_name, "type_name") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_name") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_str") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_path") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "get_buf") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "to_string") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "as_string") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "__repr__") == 0:
return i8_ptr_ty
if string.strcmp(method_name, "__str__") == 0:
return i8_ptr_ty
# 返回 i8* 的方法(返回对象指针,如 JsonValue.get_item → JsonValue*
if string.strcmp(method_name, "get_item") == 0:
return i8_ptr_ty
# 返回 void 的方法
if string.strcmp(method_name, "__before_init__") == 0:
@@ -2853,10 +2967,12 @@ def _infer_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
if string.strcmp(method_name, "__exit__") == 0:
return llvmlite.Void(pool)
# 默认 i64(整数):既可安全截断为 i32trunc也可转换为指针inttoptr
# 避免使用指针类型i8*)导致 coerce_to_type 生成 load解引用造成崩溃
# x86-64 ABI 中 i32 返回值在 rax 低 32 位i64 读取后 trunc 取低 32 位是安全的
return llvmlite.Int64(pool)
# 默认 i32(整数):与本模块函数定义的默认返回类型一致HandlesFunctions.py line 324
# 已知返回指针的方法在上方显式列出(返回 i8*),已知返回 void 的方法也显式列出
# 避免使用 i64 导致 stub 声明declare i64与实际定义define i32类型不匹配
# x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致
# 与 _infer_external_func_ret_ty 的默认策略保持一致
return llvmlite.Int32(pool)
# ============================================================
# _translate_method_call - 翻译方法调用 obj.method(args)
@@ -2981,6 +3097,65 @@ def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
total_count: int = 1 + can
# 默认参数填充:如果调用点参数少于函数定义参数,用默认值填充缺失参数
# 查找函数的 defaults 信息
mdf_defaults: t.CVoid | t.CPtr = None
mdf_default_count: int = 0
mdf_param_count: int = 0
if trans is not None and trans._funcs is not None:
mdf_entry: FuncEntry | t.CPtr = find_func_entry_in_table(
trans._funcs, trans._func_count, lookup_name)
if mdf_entry is not None:
mdf_defaults = mdf_entry.Defaults
mdf_default_count = mdf_entry.DefaultCount
mdf_param_count = mdf_entry.ParamCount
if mdf_defaults is None:
mdf_gd: FuncDefaultsEntry | t.CPtr = find_func_defaults(lookup_name)
if mdf_gd is not None:
mdf_defaults = mdf_gd.Defaults
mdf_default_count = mdf_gd.DefaultCount
mdf_param_count = mdf_gd.ParamCount
# 计算需要填充的参数(不含 self
# can = 已提供的非 self 参数数量
# mdf_param_count = 函数定义的非 self 参数数量
if mdf_param_count > can:
mdf_offset: int = mdf_param_count - mdf_default_count
mdf_pi: int = can
while mdf_pi < mdf_param_count:
# 优先用默认值
if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset:
mdf_di: int = mdf_pi - mdf_offset
if mdf_di < mdf_default_count:
mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr))
mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di)
if mdf_node is not None:
mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, mdf_node, None, 0, trans)
if mdf_val is not None:
llvmlite.value_set_next(mdf_val, None)
llvmlite.value_set_next(tail, mdf_val)
tail = mdf_val
total_count += 1
mdf_pi += 1
continue
# 无默认值时用零值兜底(需要 found_func 获取参数类型)
if found_func is not None:
param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func)
skip_z: int = 0
while skip_z <= mdf_pi and param_node_z is not None:
param_node_z = llvmlite.param_get_next(param_node_z)
skip_z += 1
if param_node_z is not None:
zero_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(param_node_z)
zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, zero_ty)
if zero_val is not None:
llvmlite.value_set_next(zero_val, None)
llvmlite.value_set_next(tail, zero_val)
tail = zero_val
total_count += 1
mdf_pi += 1
# 虚方法分发:如果类有虚表且该方法在虚表中,走间接调用
# (不依赖 found_func — 继承的虚方法可能没有子类实现)
# 复用前面已获取的 mc_entryfind_struct_by_type 规避跨模块同名找错)
@@ -3061,6 +3236,30 @@ def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr,
is_oop: int = 0
if kw_entry is not None:
is_oop = kw_entry.IsOOP
# 跨模块 OOP 类推断IsOOP 可能未设置Phase1 缓存跳过 _translate_oop_methods
# 方案1: 检查当前模块是否有 ClassName.__init__ 的声明stub 注入)
# 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠)
if is_oop == 0 and class_name is not None:
kw_init_lookup: t.CChar | t.CPtr = pool.alloc(128)
if kw_init_lookup is not None:
viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name)
# 方案1: 检查当前模块的函数声明
kw_init_found: llvmlite.Function | t.CPtr = find_func_in_module(mod, kw_init_lookup)
if kw_init_found is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
else:
# 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入)
kw_init_defaults: FuncDefaultsEntry | t.CPtr = find_func_defaults(kw_init_lookup)
if kw_init_defaults is not None:
is_oop = 1
if kw_entry is not None:
kw_entry.IsOOP = 1
kw_entry.HasInit = 1
if is_oop != 0:
_call_method_on_ptr(pool, builder, mod, class_name,
"__before_init__", tmp, None, 0, trans)
@@ -3693,13 +3892,27 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8i64
# __len__ 是 list[T] 的内置方法list 是泛型类不注册 struct
# 注意: 必须用 translate_value 而非 translate_name_value因为 len_at.value
# 可能是 Attribute 节点(如 md_ags.argstranslate_name_value 只处理 Name 节点,
# 对 Attribute 会错误返回 i32 0导致 GEP base 不是指针base of getelementptr must be a pointer
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
len_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func)
if len_at.attr is not None and string.strcmp(len_at.attr, "__len__") == 0:
if len_at.value is not None and can == 0:
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_name_value(
builder, pool, len_at.value, trans)
if obj_val is not None:
obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, len_at.value, funcs_ptr, func_count, trans)
if obj_val is not None and obj_val.Ty is not None:
# 防御性类型检查: obj_val 必须是指针类型才能做 GEP
# 如果 translate_value 返回 i32 (如 CDefine 常量被误解析、
# 模块属性前向引用回退为 i32)GEP base 会是 i32 而非指针,
# 导致 llc 报错 "base of getelementptr must be a pointer"
if HandlesExpr.is_ptr_type(obj_val.Ty) == 0:
# 诊断: 输出节点类型信息帮助定位根本原因
len_node_kind: int = len_at.value.kind()
stdio.printf(
"[LEN-DIAG] __len__ on non-ptr (kind=%d), fallback to 0\n",
len_node_kind)
return llvmlite.const_int64(pool, 0)
i64_ty_len: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
# 注意: 必须用 const_int64 而非 ConstInt(...,"0")
# ConstInt 的 name 参数 "0" 会被当作 IR 文本值输出 i64 0
@@ -3917,6 +4130,20 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
lm_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
builder, pool, mod, lm_at.value, funcs_ptr, func_count, trans)
if lm_obj is not None:
# 防御性类型检查: lm_obj 必须是指针类型才能做 GEP
# translate_value 对某些 Attribute 节点(如 ast.Arguments 的属性)
# 可能返回 i32 0 (非指针),直接 GEP 会导致
# "base of getelementptr must be a pointer" 错误
if lm_obj.Ty is None or HandlesExpr.is_ptr_type(lm_obj.Ty) == 0:
lm_node_kind: int = lm_at.value.kind()
fb_lm: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb_lm is not None:
viperlib.snprintf(fb_lm, 1024,
"list 方法 '%s' 的目标对象非指针 (node kind=%d)"
"translate_value 类型推断失败",
lm_name, lm_node_kind)
VLogger.critical(fb_lm, "LIST-METHOD")
return None
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
@@ -4245,6 +4472,9 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# 旧逻辑IsDeclared==1 时用 func_name 裸名是错误的stub 注入的 declare Name 已带 SHA1 前缀,
# 用裸名会导致 call @_PathToModuleName 而 define 是 @"sha1._PathToModuleName",链接报 undefined reference
call_name: str = func_name
# 原始函数名(别名导入时记录,如 from X import parse as json_parse → orig_func_name="parse"
# 用于在别名处理后重新推断返回类型,避免 _infer_external_func_ret_ty 用别名匹配失败
orig_func_name: str = None
if found_func is not None:
found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func)
if found_name is not None:
@@ -4357,6 +4587,11 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
bo_buf[bo_i] = bare_orig[bo_i]
bo_buf[bo_len] = '\0'
bare_func_name = bo_buf
# 记录原始函数名,供后续重新推断返回类型
# 例如 from json.__parser import parse as json_parse
# func_name="json_parse", bare_func_name="parse"
# _infer_external_func_ret_ty 用 "parse" 能正确匹配,用 "json_parse" 则返回默认 i32
orig_func_name = bare_func_name
if is_cexport_func(bare_sha1, bare_func_name) != 0:
call_name = bare_func_name
else:
@@ -4382,6 +4617,14 @@ def translate_call(pool: memhub.MemBuddy | t.CPtr,
# memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失)
if func_name == "memcpy" and can >= 3:
return _emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst2, mc_src2, mc_num2)
# 别名导入重新推断返回类型:
# from X import parse as json_parse → func_name="json_parse" 时 _infer_external_func_ret_ty 返回默认 i32
# 用 orig_func_name="parse" 重新推断,能正确匹配返回 i8*JsonValue*
# 避免指针被截断为 i32 后 inttoptr 丢失高 32 位导致崩溃
if orig_func_name is not None and orig_func_name != func_name:
re_inferred_ty: llvmlite.LLVMType | t.CPtr = _infer_external_func_ret_ty(pool, orig_func_name)
if re_inferred_ty is not None:
call_ret_ty = re_inferred_ty
# 跨模块调用:创建 declare 声明,避免 llc 报 undefined value
_ensure_method_declare(pool, mod, call_name, call_ret_ty, head, can)
return llvmlite.build_call(builder, call_name, head, can, call_ret_ty, 0)

View File

@@ -353,17 +353,21 @@ def forward_declare_functions(trans: HT.Translator | t.CPtr,
continue
# 提取默认参数信息
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__()
# 否则编译器无法识别属性返回的 list 类型GEP base 会变成 i32 0 导致 llc 报错
fd_args_node: ast.Arguments | t.CPtr = fd.args
fd_defaults: list[ast.AST | t.CPtr] | t.CPtr = None
fd_defaults: t.CVoid | t.CPtr = None
fd_default_count: int = 0
fd_param_count: int = 0
if fd_args_node is not None:
fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node)
if fd_ags.args is not None:
fd_param_count = fd_ags.args.__len__()
fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args
fd_param_count = fd_alist.__len__()
if fd_ags.defaults is not None:
fd_defaults = fd_ags.defaults
fd_default_count = fd_ags.defaults.__len__()
fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults
fd_defaults = fd_dlist
fd_default_count = fd_dlist.__len__()
# 注册到函数表(用裸名 fd.name不是 mangled_name
max_funcs: int = 256
@@ -552,16 +556,18 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
llvmlite.function_set_attrs(func, func_attrs)
# 提取默认参数信息
tfd_defaults: list[ast.AST | t.CPtr] | t.CPtr = None
tfd_defaults: t.CVoid | t.CPtr = None
tfd_default_count: int = 0
tfd_param_count: int = 0
if args_node is not None:
tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
if tfd_ags.args is not None:
tfd_param_count = tfd_ags.args.__len__()
tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args
tfd_param_count = tfd_alist.__len__()
if tfd_ags.defaults is not None:
tfd_defaults = tfd_ags.defaults
tfd_default_count = tfd_ags.defaults.__len__()
tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults
tfd_defaults = tfd_dlist
tfd_default_count = tfd_dlist.__len__()
# 注册到函数表
max_funcs: int = 256
@@ -668,8 +674,6 @@ def translate_function_def(trans: HT.Translator | t.CPtr,
for bi2 in range(bn2):
stmt2: ast.AST | t.CPtr = body.get(bi2)
if stmt2 is not None:
stdio.printf("[DBG] TR body stmt=%d kind=%d\n", bi2, stmt2.kind())
stdio.fflush(0)
HandlesBody.translate_stmt(trans, stmt2)
# 如果函数体最后一条语句不是 Return添加隐式 ret

View File

@@ -559,6 +559,21 @@ class ImportsHandle(HandlesBase.Mixin):
resolved: str = _resolve_relative_module(
self.Trans.Pool, self.Trans.CurrentPackage,
impf.level, impf.module)
# [IFD] 诊断 from-import 名称处理
mod_dbg: str = "(null)"
if impf.module is not None:
mod_dbg = impf.module
pkg_dbg: str = "(null)"
if self.Trans.CurrentPackage is not None:
pkg_dbg = self.Trans.CurrentPackage
res_dbg: str = "(null)"
if resolved is not None:
res_dbg = resolved
names_dbg: t.CSizeT = 0
if impf.names is not None:
names_dbg = impf.names.__len__()
stdio.printf("[IFD] level=%d module=%s pkg=%s resolved=%s names=%d\n",
impf.level, mod_dbg, pkg_dbg, res_dbg, names_dbg)
if resolved is not None:
names: list[ast.AST | t.CPtr] | t.CPtr = impf.names
if names is not None:

View File

@@ -88,6 +88,10 @@ def translate_children(trans: HT.Translator | t.CPtr,
if child is None: continue
kd: int = child.kind()
# _declare_only == 0 时_translate_module_level 已预处理导入语句,
# 此处跳过避免重复处理from_imports 条目重复)
if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom):
continue
if kd == ast.ASTKind.Import:
trans.ImportsH.HandleImport(child)
elif kd == ast.ASTKind.ImportFrom:
@@ -97,10 +101,6 @@ def translate_children(trans: HT.Translator | t.CPtr,
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
# Phase 1b 全量翻译:正常翻译函数体
if trans._declare_only == 0:
fd_dbg: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
if fd_dbg is not None and fd_dbg.name is not None:
stdio.printf("[DBG] TR func=%s\n", fd_dbg.name)
stdio.fflush(0)
added: int = HandlesFunctions.translate_function_def(trans, child)
added_total += added
elif trans._declare_only == 1:
@@ -109,10 +109,6 @@ def translate_children(trans: HT.Translator | t.CPtr,
# ClassDef 在模块级直接处理(不需要 builder
# _declare_only=2import扫描模式时跳过只处理 import 依赖
if trans._declare_only != 2:
cd_dbg: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child)
if cd_dbg is not None and cd_dbg.name is not None:
stdio.printf("[DBG] TR class=%s\n", cd_dbg.name)
stdio.fflush(0)
HandlesClassDef.translate_class_def(trans, child)
elif trans._declare_only == 0 and trans._cur_builder is not None:
# 有 builder → 委托 HandlesBody 分派

View File

@@ -522,16 +522,8 @@ def lookup_field_by_class(class_name: str,
entry = find_struct(class_name)
if entry is None:
# 诊断:遍历打印所有已注册结构体名,确认目标类是否在注册表中
stdio.printf("[LFBC-DIAG] FAIL class=%s field=%s sha1=%s count=%d\n",
class_name, field_name,
sha1 if sha1 is not None else "(null)", _struct_count)
for diag_i in range(_struct_count):
diag_entry: StructEntry | t.CPtr = _get_struct_entry(diag_i)
if diag_entry is not None and diag_entry.Name is not None:
stdio.printf("[LFBC-DIAG] [%d] %s sha1=%s fc=%d\n",
diag_i, diag_entry.Name,
diag_entry.ModuleSha1 if diag_entry.ModuleSha1 is not None else "(null)",
diag_entry.FieldCount)
return None
for fi in range(entry.FieldCount):
fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi)
@@ -539,8 +531,6 @@ def lookup_field_by_class(class_name: str,
if string.strcmp(fe.Name, field_name) == 0:
return fe
# 诊断:找到结构体但字段未找到
stdio.printf("[LFBC-DIAG] NOFIELD class=%s field=%s sname=%s fc=%d\n",
class_name, field_name, entry.Name, entry.FieldCount)
return None

View File

@@ -68,22 +68,8 @@ _g_cdefine_names: list[str] | t.CPtr = None
_g_cdefine_values: list[str] | t.CPtr = None
# ============================================================
# 全局跨模块 CDefine 表(按模块 SHA1 索引,跨模块持久化
#
# 本地表在模块切换时被 clear_cdefine_constants 清空,
# 导致跨模块引用(如 HandlesVar.SCOPE_FUNCTION找不到常量。
# 全局表在模块切换时不清空,跨模块查找直接查表,无需文件 I/O。
#
# 数据布局:
# _g_gcdef_sha1s: 每条 17 字节(模块 SHA1 16字符 + null
# _g_gcdef_names: 每条 64 字节(常量名 + null
# _g_gcdef_values: 每条 32 字节(值字符串 + null
# 当前模块 SHA1Phase1 在模块开始翻译前设置,供报错使用
# ============================================================
MAX_GLOBAL_CDEFINE: t.CDefine = 1024
_g_gcdef_sha1s: bytes = None
_g_gcdef_names: bytes = None
_g_gcdef_values: bytes = None
_g_gcdef_count: int = 0
_g_current_module_sha1: str = None
@@ -93,29 +79,14 @@ def set_current_module_sha1(sha1: str) -> None:
_g_current_module_sha1 = sha1
def _global_cdefine_init(pool: memhub.MemBuddy | t.CPtr) -> int:
"""懒初始化全局 CDefine 表"""
global _g_gcdef_sha1s, _g_gcdef_names, _g_gcdef_values
if _g_gcdef_sha1s is None:
_g_gcdef_sha1s = stdlib.malloc(MAX_GLOBAL_CDEFINE * 17)
_g_gcdef_names = stdlib.malloc(MAX_GLOBAL_CDEFINE * 64)
_g_gcdef_values = stdlib.malloc(MAX_GLOBAL_CDEFINE * 32)
if _g_gcdef_sha1s is None or _g_gcdef_names is None or _g_gcdef_values is None:
return 1
string.memset(_g_gcdef_sha1s, 0, MAX_GLOBAL_CDEFINE * 17)
string.memset(_g_gcdef_names, 0, MAX_GLOBAL_CDEFINE * 64)
string.memset(_g_gcdef_values, 0, MAX_GLOBAL_CDEFINE * 32)
return 0
def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
name: str, value: int) -> None:
"""注册 CDefine 编译期常量到本地表和全局表
"""注册 CDefine 编译期常量到本地表
值以十进制字符串存储。注意value 是 32 位有符号整数,
0xFFFFFFFF 会存储为 "-1"lookup 时用 found 标志区分"未找到"和值为 -1。
"""
global _g_cdefine_names, _g_cdefine_values, _g_gcdef_count
global _g_cdefine_names, _g_cdefine_values
if _g_cdefine_names is None:
_g_cdefine_names = list[str](pool, 64)
_g_cdefine_values = list[str](pool, 64)
@@ -126,41 +97,6 @@ def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr,
_g_cdefine_values.append(val_buf)
else:
_g_cdefine_values.append("0")
# 同时注册到全局跨模块表(用当前模块 SHA1 索引)
if _g_current_module_sha1 is not None and _g_gcdef_count < MAX_GLOBAL_CDEFINE:
if _global_cdefine_init(pool) == 0:
sidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 17
nidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 64
vidx: t.CSizeT = t.CSizeT(_g_gcdef_count) * 32
string.strcpy(_g_gcdef_sha1s + sidx, _g_current_module_sha1)
string.strcpy(_g_gcdef_names + nidx, name)
vbuf: str = _g_gcdef_values + vidx
viperlib.snprintf(vbuf, 32, "%d", value)
_g_gcdef_count += 1
def lookup_global_cdefine(module_sha1: str, name: str) -> int:
"""从全局跨模块表查找 CDefine 常量
用 module_sha1 + name 精确匹配。
找到时设置 _g_cdefine_found=1 并返回值;未找到返回 0。
"""
global _g_cdefine_found
if module_sha1 is None or name is None:
return 0
if _g_gcdef_sha1s is None or _g_gcdef_count <= 0:
return 0
i: t.CSizeT = 0
while i < _g_gcdef_count:
sidx: t.CSizeT = t.CSizeT(i) * 17
nidx: t.CSizeT = t.CSizeT(i) * 64
vidx: t.CSizeT = t.CSizeT(i) * 32
if string.strcmp(_g_gcdef_sha1s + sidx, module_sha1) == 0:
if string.strcmp(_g_gcdef_names + nidx, name) == 0:
_g_cdefine_found = 1
return string.atoi(_g_gcdef_values + vidx)
i += 1
return 0
def lookup_cdefine_constant(name: str) -> int:
@@ -645,6 +581,14 @@ def map_t_type(pool: memhub.MemBuddy | t.CPtr,
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "VOIDPTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
# Windows API 跨模块 typedefwin32base.py 中定义)
# HANDLE = VOIDPTR = i8*LPCSTR = const char* = i8*LPCWSTR = const wchar_t* = i16*
elif string.strcmp(type_name, "HANDLE") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "LPCSTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "LPCWSTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int16(pool))
elif string.strcmp(type_name, "INT8PTR") == 0:
return llvmlite.Ptr(pool, llvmlite.Int8(pool))
elif string.strcmp(type_name, "INT16PTR") == 0:

View File

@@ -22,7 +22,7 @@ import lib.core.VLogger as VLogger
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 文件路径最大长度
MAX_PATH_LEN: t.CDefine = 512

View File

@@ -24,7 +24,7 @@ import lib.Projectrans.Config as Config
import lib.StubGen.Converter as StubConverter
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576
@@ -944,7 +944,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
src_buf[SRC_BUF_SIZE - 1] = 0
# 解析 AST
stdio.printf("[P1B-1] parse %s\n", entry.RelPath)
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
if lx is None:
stdlib.free(src_buf)
@@ -953,7 +952,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
ast._lexer_init(lx, src_buf, mb)
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
stdio.printf("[P1B-1a] parse-done %s\n", entry.RelPath)
if tree is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
@@ -964,7 +962,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue
# 生成 .pyi 存根文件(直接遍历 AST不依赖 PythonToStubConverter
stdio.printf("[P1B-2] pyi %s\n", entry.RelPath)
pyi_buf: bytes = stdlib.malloc(PYI_BUF_SIZE)
if pyi_buf is not None:
pyi_pos: t.CSizeT = StubConverter._GeneratePyiFromAst(mb, tree, entry.RelPath, pyi_buf, PYI_BUF_SIZE)
@@ -979,7 +976,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(pyi_buf)
# 翻译 AST → LLVM IR
stdio.printf("[P1B-3] translate %s\n", entry.RelPath)
tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
if tr is None:
stdlib.free(src_buf)
@@ -992,7 +988,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
HandlesType.clear_cdefine_constants()
HandlesStruct.reset_visible_structs(mb, 0)
ret: int = tr.translate(tree)
stdio.printf("[P1B-3a] translate-done %s ret=%d\n", entry.RelPath, ret)
if ret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
@@ -1007,7 +1002,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
continue
# dump stub IR (declarations only)
stdio.printf("[P1B-4] stub %s\n", entry.RelPath)
PHASE1_IR_SIZE: t.CSizeT = 1048576
stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
if stub_buf is None:
@@ -1033,7 +1027,6 @@ def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
stdlib.free(stub_buf)
# dump text IR (definitions only)
stdio.printf("[P1B-5] text %s\n", entry.RelPath)
text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE)
if text_buf is None:
stdlib.free(src_buf)

View File

@@ -24,7 +24,7 @@ import lib.Projectrans.Utils as Utils
import lib.Projectrans.Config as Config
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 源代码缓冲区大小1MB
SRC_BUF_SIZE: t.CDefine = 1048576
@@ -32,6 +32,9 @@ SRC_BUF_SIZE: t.CDefine = 1048576
# 最大源文件数(递归扫描子目录后文件数增多,增大到 64
MAX_SRC_FILES: t.CDefine = 64
# 全局栈金丝雀(避免局部变量改变栈布局)
_g_canary: t.CUInt32T
@t.NoVTable
class SrcFileEntry:
@@ -172,8 +175,8 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
VLogger.error("source_dir 为空", "project")
return 1
stdio.printf("[DBG] RunMultiFileProject enter src=%s\n", source_dir)
stdio.fflush(0)
# === 栈金丝雀检查(全局变量,不影响栈布局)===
_g_canary = 305419896
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
@@ -188,8 +191,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
string.memset(entries, 0, MAX_SRC_FILES * entry_size)
file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES)
stdio.printf("[DBG] scan done file_count=%d\n", file_count)
stdio.fflush(0)
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "%d 个源文件", file_count)
@@ -296,8 +297,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# === 2. Phase A: 为每个文件生成 stub + text ===
if do_phase1 != 0:
stdio.printf("[DBG] before Phase A\n")
stdio.fflush(0)
if log is not None:
log.banner("Phase A: 生成 stub + text")
@@ -311,8 +310,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
PHASE_A_PRE_MAX_PASSES: t.CInt = 3
for pass_i in range(PHASE_A_PRE_MAX_PASSES):
struct_count_before: int = HandlesStruct.get_struct_count()
stdio.printf("[DBG] PhaseA-pre pass=%d struct_count_before=%d\n", pass_i, struct_count_before)
stdio.fflush(0)
for i in range(file_count):
ea_pre: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_pre, t.CPtr))
@@ -322,8 +319,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
if string.strlen(ent_pre.Path) > src_dir_len_pre + 1:
rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1
pkg_pre = HandlesImports.compute_package_from_relpath(mb, rel_path_pre)
stdio.printf("[DBG] PhaseA-pre pass=%d file=%s\n", pass_i, ent_pre.Path)
stdio.fflush(0)
tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1)
if tr_pre is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -331,8 +326,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path)
VLogger.warning(fb, "PhaseA")
struct_count_after: int = HandlesStruct.get_struct_count()
stdio.printf("[DBG] PhaseA-pre pass=%d done struct_count_after=%d\n", pass_i, struct_count_after)
stdio.fflush(0)
# 收敛检查:本遍没有新结构体注册 → 所有类已注册
if struct_count_after == struct_count_before:
break
@@ -341,16 +334,11 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
PHASE_A_IR_SIZE: t.CSizeT = 1048576
td_len_pa: t.CSizeT = string.strlen(temp_dir)
stdio.printf("[DBG] PhaseA full-translate start\n")
stdio.fflush(0)
for i in range(file_count):
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Path is None:
continue
stdio.printf("[DBG] PhaseA file=%s\n", ent.Path)
stdio.fflush(0)
# 计算源文件的包名(相对 source_dir 的目录部分)
src_dir_len_pa: t.CSizeT = string.strlen(source_dir)
pkg_pa: str = None
@@ -413,8 +401,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# === 3. Phase B: 编译每个文件为 .obj ===
if do_phase2 != 0:
stdio.printf("[DBG] before Phase B\n")
stdio.fflush(0)
if log is not None:
log.banner("Phase B: 编译 .obj")
@@ -441,12 +427,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
if ent is None or ent.Path is None or ent.Sha1 is None:
continue
stdio.printf("[DBG] PhaseB file=%s\n", ent.Path)
stdio.fflush(0)
# 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR
stdio.printf("[DBG] PhaseB step=alloc combined_ir\n")
stdio.fflush(0)
combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE)
if combined_ir is None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -454,11 +435,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path)
VLogger.error(fb, "PhaseB")
continue
stdio.printf("[DBG] PhaseB step=BuildCombinedIR sha1=%s\n", ent.Sha1)
stdio.fflush(0)
combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE)
stdio.printf("[DBG] PhaseB step=BuildCombinedIR done len=%d\n", combined_len)
stdio.fflush(0)
if combined_len == 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
@@ -468,13 +445,9 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
continue
# 编译为 .obj
stdio.printf("[DBG] PhaseB step=compile_module_to_obj\n")
stdio.fflush(0)
cret: int = BuildPipeline.compile_module_to_obj(
combined_ir, combined_len, temp_dir, output_dir, ent.Sha1,
cc_cmd, cc_flags)
stdio.printf("[DBG] PhaseB step=compile_module_to_obj done cret=%d\n", cret)
stdio.fflush(0)
stdlib.free(combined_ir)
if cret != 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -484,9 +457,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
sys.exit(1)
compiled_count += 1
stdio.printf("[DBG] PhaseB step=obj_path construct\n")
stdio.fflush(0)
# 构造 .obj 路径,检测是否是 main 模块test_main.py 或 main.py
od_len: t.CSizeT = string.strlen(output_dir)
is_main_mod: int = 0
@@ -517,11 +487,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
else:
VLogger.warning(".obj 路径缓冲区不足", "PhaseB")
stdlib.free(obj_path_sliced)
stdio.printf("[DBG] PhaseB step=obj_path done\n")
stdio.fflush(0)
stdio.printf("[DBG] PhaseB loop done compiled_count=%d\n", compiled_count)
stdio.fflush(0)
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count)
@@ -538,27 +503,18 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
# 检测并编译缺失的 includes 文件到 output_dir加入链接命令。
# 数据来源StubMerger 全局内存存储器(不读取 _sha1_map.txt 文件)
if includes_dir is not None and includes_binary_dir is not None:
stdio.printf("[DBG] PhaseB+ start\n")
stdio.fflush(0)
inc_compiled: int = 0
td_len_mi: t.CSizeT = string.strlen(temp_dir)
# 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题)
store_count_mi: int = StubMerger.GetSha1StoreCount()
stdio.printf("[DBG] PhaseB+ store_count=%d\n", store_count_mi)
stdio.fflush(0)
if store_count_mi > 0:
store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr()
store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
stdio.printf("[DBG] PhaseB+ arrs ok sha1=%p mod=%p rel=%p\n", store_sha1_arr_mi, store_mod_arr_mi, store_rel_arr_mi)
stdio.fflush(0)
for si_mi in range(store_count_mi):
# 获取当前条目的 SHA1 和 rel_path
inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17
inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN
stdio.printf("[DBG] PhaseB+ iter=%d sha1=%s rel=%s\n", si_mi, inc_sha1_mi, inc_rel_mi)
stdio.fflush(0)
# 检查 .obj 是否已存在于 includes.binary
ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir)
check_pat_mi: bytes = stdlib.malloc(ibd_len_mi + 35)
@@ -719,8 +675,6 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
VLogger.info(fb, "PhaseB+")
# === 4. Phase C: 链接所有 .obj → .exe ===
stdio.printf("[DBG] PhaseC start\n")
stdio.fflush(0)
if log is not None:
log.banner("Phase C: 链接")
@@ -754,14 +708,10 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
final_obj_paths[fop_pos] = '\0'
obj_paths_len: t.CSizeT = fop_pos
stdio.printf("[DBG] PhaseC before link_objs_to_exe len=%d\n", obj_paths_len)
stdio.fflush(0)
lret: int = BuildPipeline.link_objs_to_exe(
final_obj_paths, obj_paths_len,
linker_cmd, linker_flags, exe_path,
includes_binary_dir)
stdio.printf("[DBG] PhaseC link_objs_to_exe done lret=%d\n", lret)
stdio.fflush(0)
if lret == 0:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -772,13 +722,13 @@ def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "执行: %s", exe_path)
VLogger.info(fb, "run")
VLogger.info(fb, "run")
rp: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False)
if rp is not None:
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
if fb is not None:
viperlib.snprintf(fb, 1024, "退出码: %d", rp.returncode)
VLogger.info(fb, "run")
VLogger.info(fb, "run")
else:
VLogger.error("链接失败", "PhaseC")
stdlib.free(entries)

View File

@@ -35,7 +35,7 @@ import lib.Projectrans.Config as Config
# ============================================================
# 全局 mbuddy 指针
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 最大 includes SHA1 数(用于过滤)
MAX_INCLUDES_SHA1: t.CDefine = 256

View File

@@ -54,11 +54,12 @@ BACKGROUND_INTENSITY: t.CDefine = 0x0080
BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
@t.NoVTable
class Logger:
_level: int
_console_handle: w32base.HANDLE
_console_handle: win32base.HANDLE
_use_color: int
__mbuddy__: memhub.MemManager | t.CPtr
__mbuddy__: memhub.MemBuddy | t.CPtr
def __init__(self, level: int = 1):
self._level = level
@@ -67,8 +68,11 @@ class Logger:
self.__mbuddy__ = _mbuddy
def _set_color(self, attr: WORD) -> int:
if self._use_color:
return w32cmd.SetConsoleTextAttribute(self._console_handle, attr)
uc: int = self._use_color
if uc:
ch: win32base.HANDLE = self._console_handle
ret: int = w32cmd.SetConsoleTextAttribute(ch, attr)
return ret
return 0
def _reset_color(self) -> int:
@@ -88,23 +92,17 @@ class Logger:
def _log(self, level: int, prefix_sym: str, level_str: str, msg: str,
sym_color: WORD, level_color: WORD,
category: str = "") -> int:
if level < self._level:
return 0
# 前缀符号(如 ├)
# 前缀符号着色
self._set_color(sym_color)
stdio.printf("%s ", prefix_sym)
# LEVEL 标签(亮色)
# LEVEL 标签着色
self._set_color(level_color)
if category is not None:
if category[0] != 0:
stdio.printf("%s[%s]: ", level_str, category)
else:
stdio.printf("%s: ", level_str)
else:
stdio.printf("%s: ", level_str)
# 消息内容(默认色)
stdio.printf("%s", level_str)
self._reset_color()
stdio.printf("%s\n", msg)
# category 可选
if category is not None and category[0] != 0:
stdio.printf("[%s]", category)
stdio.printf(": %s\n", msg)
return 0
def debug(self, msg: str, category: str = "") -> int:
@@ -112,9 +110,10 @@ class Logger:
FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)
def info(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.INFO, "", "INFO", msg,
FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
ret: int = self._log(LogLevel.INFO, "", "INFO", msg,
FOREGROUND_GREEN,
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
return ret
def warning(self, msg: str, category: str = "") -> int:
return self._log(LogLevel.WARNING, "", "WARN", msg,
@@ -189,7 +188,7 @@ class Logger:
# 全局 mbuddy 指针(由 lib.InitLib 注入)
_mbuddy: memhub.MemManager | t.CPtr
_mbuddy: memhub.MemBuddy | t.CPtr
# 全局 logger 指针
_g_logger: Logger | t.CPtr
@@ -223,10 +222,8 @@ def get_logger() -> Logger | t.CPtr:
if raw is None:
return None
_g_logger = raw
_g_logger._level = LogLevel.INFO
_g_logger._console_handle = w32file.GetStdHandle(w32file.STD_OUTPUT_HANDLE)
_g_logger._use_color = 1
_g_logger.__mbuddy__ = _mbuddy
_g_logger.__before_init__()
_g_logger.__init__(LogLevel.INFO)
return _g_logger

View File

@@ -49,127 +49,70 @@ SRC_BUF_SIZE: t.CDefine = 1048576
def main() -> int:
w32cmd.SetConsoleOutputCP(CODE_PAGE)
w32cmd.SetConsoleCP(CODE_PAGE)
# 用 fflush(0) 刷新所有流确保崩溃前输出可见0=NULL 刷新所有输出流)
stdio.printf("[DBG] main enter\n")
stdio.fflush(0)
# 初始化 mbuddy 内存池
stdio.printf("[DBG] before malloc\n")
stdio.fflush(0)
arena: bytes = stdlib.malloc(POOL_SIZE)
stdio.printf("[DBG] after malloc arena=%p\n", arena)
stdio.fflush(0)
if arena is None:
stdio.printf("FAIL: malloc for arena failed\n")
return 1
stdio.printf("[DBG] before MemBuddy\n")
stdio.fflush(0)
mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE)
stdio.printf("[DBG] after MemBuddy mb=%p\n", mb)
stdio.fflush(0)
if mb is None:
stdio.printf("FAIL: MemBuddy init failed\n")
return 1
# 设置全局 mbuddy 指针sys 和 argparse 都需要)
stdio.printf("[DBG] before _mbuddy setup\n")
stdio.fflush(0)
sys._mbuddy = mb
stdio.printf("[DBG] sys._mbuddy ok\n")
stdio.fflush(0)
argparse._mbuddy = mb
ast._mbuddy = mb
lib._mbuddy = (memhub.MemManager | t.CPtr)(mb)
Config._mbuddy = (memhub.MemManager | t.CPtr)(mb)
Utils._mbuddy = (memhub.MemManager | t.CPtr)(mb)
lib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Config._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Utils._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
HandlesTranslator._mbuddy = mb
BuildPipeline._mbuddy = (memhub.MemManager | t.CPtr)(mb)
IncludesScanner._mbuddy = (memhub.MemManager | t.CPtr)(mb)
StubMerger._mbuddy = (memhub.MemManager | t.CPtr)(mb)
Phase1._mbuddy = (memhub.MemManager | t.CPtr)(mb)
Phase2._mbuddy = (memhub.MemManager | t.CPtr)(mb)
BuildPipeline._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
IncludesScanner._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
StubMerger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Phase1._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
Phase2._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
subprocess._mbuddy = mb
hashlib._mbuddy = (memhub.MemManager | t.CPtr)(mb)
VLogger._mbuddy = (memhub.MemManager | t.CPtr)(mb)
stdio.printf("[DBG] before InitLib\n")
stdio.fflush(0)
lib.InitLib((memhub.MemManager | t.CPtr)(mb))
stdio.printf("[DBG] after InitLib\n")
stdio.fflush(0)
hashlib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
VLogger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
lib.InitLib((memhub.MemBuddy | t.CPtr)(mb))
# 初始化 VLogger 并打印启动日志
log: VLogger.Logger | t.CPtr = VLogger.get_logger()
stdio.printf("[DBG] after get_logger log=%p\n", log)
stdio.fflush(0)
if log is not None:
log.info("TransPyV 启动")
stdio.printf("[DBG] after log.info\n")
stdio.fflush(0)
# 初始化命令行参数Windows: GetCommandLineA, POSIX: /proc/self/cmdline
stdio.printf("[DBG] before _init_argv\n")
stdio.fflush(0)
sys._init_argv()
stdio.printf("[DBG] after _init_argv\n")
stdio.fflush(0)
# 创建参数解析器
stdio.printf("[DBG] before ArgumentParser\n")
stdio.fflush(0)
parser: argparse.ArgumentParser | t.CPtr = argparse.ArgumentParser(
"TransPyV", "TransPyV 命令行参数解析", pool=mb)
stdio.printf("[DBG] after ArgumentParser parser=%p\n", parser)
stdio.fflush(0)
# 注册参数(与 Projectrans.py main() 一致)
stdio.printf("[DBG] before add_argument --project\n")
stdio.fflush(0)
parser.add_argument("--project", None, argparse.STRING, 0, None, False,
argparse.STORE, "project.json 路径(默认查找当前目录)")
stdio.printf("[DBG] after add_argument --project\n")
stdio.fflush(0)
parser.add_argument("--src", None, argparse.STRING, 0, None, False,
argparse.STORE, "源文件目录(覆盖 project.json")
stdio.printf("[DBG] after --src\n")
stdio.fflush(0)
parser.add_argument("--temp", None, argparse.STRING, 0, None, False,
argparse.STORE, "声明接口临时目录(覆盖 project.json")
stdio.printf("[DBG] after --temp\n")
stdio.fflush(0)
parser.add_argument("--output", None, argparse.STRING, 0, None, False,
argparse.STORE, "输出目录(覆盖 project.json")
stdio.printf("[DBG] after --output\n")
stdio.fflush(0)
parser.add_argument("--phase", None, argparse.STRING, 0, None, False,
argparse.STORE, "阶段: 1=生成声明, 2=翻译+编译, all=全部")
stdio.printf("[DBG] after --phase\n")
stdio.fflush(0)
parser.add_argument("--cc", None, argparse.STRING, 0, None, False,
argparse.STORE, "LLVM 编译器命令(覆盖 project.json")
stdio.printf("[DBG] after --cc\n")
stdio.fflush(0)
parser.add_argument("--clean", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "清理 output 和 temp 目录")
stdio.printf("[DBG] after --clean\n")
stdio.fflush(0)
parser.add_argument("--run", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "编译成功后立即执行生成的可执行文件")
stdio.printf("[DBG] after --run\n")
stdio.fflush(0)
parser.add_argument("--rebuild-includes", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "删除 includes.binary 预编译缓存并重新编译所有 includes")
stdio.printf("[DBG] after --rebuild-includes\n")
stdio.fflush(0)
parser.add_argument("--clear-cache", None, argparse.BOOL, 0, None, False,
argparse.STORE_TRUE, "清除 .transpyc_cache 全局缓存")
stdio.printf("[DBG] after --clear-cache\n")
stdio.fflush(0)
# 解析命令行参数
stdio.printf("[DBG] before parse_args\n")
stdio.fflush(0)
args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv)
stdio.printf("[DBG] after parse_args args=%p\n", args)
stdio.fflush(0)
if args is None:
if log is not None:
log.error("参数解析失败", "argparse")
@@ -244,13 +187,10 @@ def main() -> int:
proj_loaded: int = 0
proj_path: str = project
if proj_path is not None:
stdio.printf("[DBG] before Load_project_config path=%s\n", proj_path)
stdio.fflush(0)
if log is not None:
log.banner("工程配置")
if Config.Load_project_config(proj_path) == 0:
stdio.printf("[DBG] Load_project_config OK\n")
stdio.fflush(0)
cfg_ret: int = Config.Load_project_config(proj_path)
if cfg_ret == 0:
proj_loaded = 1
else:
if log is not None:
@@ -284,14 +224,8 @@ def main() -> int:
if proj_dir is not None:
string.memcpy(proj_dir, proj_path, slash_pos)
proj_dir[slash_pos] = '\0'
stdio.printf("[DBG] before resolve_paths dir=%s\n", proj_dir)
stdio.fflush(0)
Config.resolve_paths(proj_dir)
stdio.printf("[DBG] resolve_paths OK\n")
stdio.fflush(0)
Config.print_config()
stdio.printf("[DBG] print_config OK\n")
stdio.fflush(0)
# === --clean: 清理 temp 和 output 目录 ===
if _gb_clean:
@@ -321,9 +255,10 @@ def main() -> int:
phase_mode = "all"
do_phase1: int = 0
do_phase2: int = 0
if phase_mode == "1" or phase_mode == "all":
# 注意: 使用 string.strcmp 而非 ==,避免编译器 == 语义 bug
if string.strcmp(phase_mode, "1") == 0 or string.strcmp(phase_mode, "all") == 0:
do_phase1 = 1
if phase_mode == "2" or phase_mode == "all":
if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0:
do_phase2 = 1
if log is not None:
fb3: t.CChar | t.CPtr = VLogger.fmt_buf()
@@ -337,11 +272,7 @@ def main() -> int:
ph1_temp: str = Config.TempDir
if ph1_temp is None:
ph1_temp = "."
stdio.printf("[DBG] before Phase1.RunPhase1 inc=%s temp=%s\n", Config.IncludesDir, ph1_temp)
stdio.fflush(0)
Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log)
stdio.printf("[DBG] Phase1.RunPhase1 OK\n")
stdio.fflush(0)
# 如果仅 Phase1不执行 Phase2直接退出
if do_phase2 == 0:
if log is not None:
@@ -363,14 +294,10 @@ def main() -> int:
mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe"
mf_includes_bin: str = Config.get_includes_binary_dir()
stdio.printf("[DBG] before Phase2.RunMultiFileProject src=%s temp=%s out=%s\n", Config.SourceDir, mf_temp, mf_output)
stdio.fflush(0)
mf_ret: int = Phase2.RunMultiFileProject(
mb, Config.SourceDir, mf_temp, mf_output,
mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out,
mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args)
stdio.printf("[DBG] Phase2.RunMultiFileProject OK ret=%d\n", mf_ret)
stdio.fflush(0)
argparse.release(args)
if log is not None:
log.success("TransPyV 完成")

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,67 +0,0 @@
"""
Auto-generated Python stub file from ast.lexer.py
Module: ast.lexer
"""
import t, c
from stdint import *
import memhub
import string
from .tokens import Token, TokenType, TokOp, _init_tables, _kw_lookup, _op_head, OpEntry, new_token, token_set_str, token_set_str_literal
LEXER_MAX_INDENT: t.CDefine = 256
class Lexer:
src: str
pos: t.CSizeT
len: t.CSizeT
lineno: t.CInt
col: t.CInt
pool: memhub.MemManager | t.CPtr
indent_stack: t.CInt | t.CPtr
indent_top: t.CInt
paren_depth: t.CInt
tokens_head: Token | t.CPtr
tokens_tail: Token | t.CPtr
at_line_start: t.CInt
error_count: t.CInt
def __new__(self: Lexer, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
def new_lexer(pool: memhub.MemManager | t.CPtr) -> Lexer | t.CPtr: pass
def _lexer_init(lx: Lexer | t.CPtr, src: str, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar: pass
def _peek_cur(lx: Lexer | t.CPtr) -> t.CChar: pass
def _advance(lx: Lexer | t.CPtr) -> t.CChar: pass
def _is_alpha(ch: t.CChar) -> t.CInt: pass
def _is_digit(ch: t.CChar) -> t.CInt: pass
def _is_alnum(ch: t.CChar) -> t.CInt: pass
def _is_hex(ch: t.CChar) -> t.CInt: pass
def _is_space(ch: t.CChar) -> t.CInt: pass
def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr) -> t.CInt: pass
def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt, lineno: t.CInt, col: t.CInt) -> Token | t.CPtr: pass
def _handle_indent(lx: Lexer | t.CPtr) -> t.CInt: pass
def _read_name(lx: Lexer | t.CPtr) -> t.CInt: pass
def _read_number(lx: Lexer | t.CPtr) -> t.CInt: pass
def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT, start_lineno: t.CInt, start_col: t.CInt, is_float: t.CInt, is_complex: t.CInt, is_hex: t.CInt) -> t.CInt: pass
def _read_string(lx: Lexer | t.CPtr) -> t.CInt: pass
def _read_operator(lx: Lexer | t.CPtr) -> t.CInt: pass
def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr: pass

View File

@@ -26,7 +26,7 @@ class CompletedProcess:
def __new__(self: CompletedProcess, args: str, returncode: int, stdout: str, stderr: str) -> t.CPtr: pass
def __init__(self: CompletedProcess, args: str, returncode: int, stdout: str, stderr: str) -> t.CInt: pass
def run(args: str, capture_output: bool, text: bool) -> CompletedProcess | t.CPtr: pass
def run(args: str, capture_output: bool = True, text: bool = True) -> CompletedProcess | t.CPtr: pass
def _run_win32(args: str, capture_output: bool, text: bool) -> CompletedProcess | t.CPtr: pass

View File

@@ -1,26 +0,0 @@
"""
Auto-generated Python stub file from ast.__init__.py
Module: ast.__init__
"""
import t, c
from stdint import *
import memhub
import string
from .tokens import Token, TokenType, Keyword, TokOp, _init_tables
from .base import AST, ASTKind, ASTCtx, OpKind, ASTFlag, CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, FLAG_IS_ASYNC, FLAG_SIMPLE, FLAG_HAS_STAR, _init_ast, _copy_str, _set_pos, _inherit_pos, _set_parent_list, _binop_from_op, _augop_from_op, _cmpop_from_op, _emit, _emit_str, _emit_int, _dump_list, dump
from .stmts import Module, Expression, Interactive, FunctionType, FunctionDef, ClassDef, Return, Delete, Assign, AugAssign, AnnAssign, For, While, If, With, Raise, Try, Assert, Global, Nonlocal, Pass, Break, Continue, Expr, Import, ImportFrom, Match
from .exprs import BoolOp, BinOp, UnaryOp, Lambda, IfExp, Dict, Set, ListComp, SetComp, DictComp, GeneratorExp, Await, Yield, YieldFrom, FormattedValue, JoinedStr, Constant, NamedExpr, Attribute, Subscript, Starred, Name, List, Tuple, Slice, Call, Compare, OpNode
from .astaux import ExceptHandler, Arguments, Arg, Keyword, Alias, WithItem, Comprehension
from .match import MatchCase, MatchValue, MatchSingleton, MatchSequence, MatchMapping, MatchClass, MatchStar, MatchAs, MatchOr
from .visitor import ASTVisitor
from .lexer import Lexer, _lexer_init, tokenize, new_lexer
from .parser import Parser, _parser_init, parse_tokens, new_parser
from .parser import _parse_test
_mbuddy: t.CExtern | memhub.MemBuddy | t.CPtr
def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr: pass
def parse_expression(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr: pass

View File

@@ -1,241 +0,0 @@
"""
Auto-generated Python stub file from ast.exprs.py
Module: ast.exprs
"""
import t, c
from stdint import *
import memhub
import string
from .base import AST, ASTKind, ASTCtx, OpKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list, _dump_op_list, _op_name, CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE
class Name(AST):
id: str
ctx: t.CInt
def __new__(self: Name, pool: memhub.MemManager | t.CPtr, id: str, ctx: t.CInt) -> t.CInt: pass
def __init__(self: Name, pool: memhub.MemManager | t.CPtr, id: str, ctx: t.CInt) -> t.CInt: pass
def kind(self: Name) -> t.CInt: pass
def type_name(self: Name) -> str: pass
def dump(self: Name, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Constant(AST):
int_val: t.CInt64T
float_val: t.CDouble
str_val: str
const_kind: t.CInt
def __new__(self: Constant, pool: memhub.MemManager | t.CPtr, const_kind: t.CInt, int_val: t.CInt64T, float_val: t.CDouble, str_val: str, lineno: t.CInt, col: t.CInt) -> t.CInt: pass
def __init__(self: Constant, pool: memhub.MemManager | t.CPtr, const_kind: t.CInt, int_val: t.CInt64T, float_val: t.CDouble, str_val: str, lineno: t.CInt, col: t.CInt) -> t.CInt: pass
def kind(self: Constant) -> t.CInt: pass
def type_name(self: Constant) -> str: pass
def dump(self: Constant, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class BinOp(AST):
left: AST | t.CPtr
op: t.CInt
right: AST | t.CPtr
def __new__(self: BinOp, pool: memhub.MemManager | t.CPtr, left: AST | t.CPtr, op: t.CInt, right: AST | t.CPtr) -> t.CInt: pass
def __init__(self: BinOp, pool: memhub.MemManager | t.CPtr, left: AST | t.CPtr, op: t.CInt, right: AST | t.CPtr) -> t.CInt: pass
def kind(self: BinOp) -> t.CInt: pass
def type_name(self: BinOp) -> str: pass
def dump(self: BinOp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class UnaryOp(AST):
op: t.CInt
operand: AST | t.CPtr
def __new__(self: UnaryOp, pool: memhub.MemManager | t.CPtr, op: t.CInt, operand: AST | t.CPtr) -> t.CInt: pass
def __init__(self: UnaryOp, pool: memhub.MemManager | t.CPtr, op: t.CInt, operand: AST | t.CPtr) -> t.CInt: pass
def kind(self: UnaryOp) -> t.CInt: pass
def type_name(self: UnaryOp) -> str: pass
def dump(self: UnaryOp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Compare(AST):
left: AST | t.CPtr
ops: t.CPtr
comparators: list[AST | t.CPtr] | t.CPtr
def __new__(self: Compare, pool: memhub.MemManager | t.CPtr, left: AST | t.CPtr, ops: t.CPtr, comparators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: Compare, pool: memhub.MemManager | t.CPtr, left: AST | t.CPtr, ops: t.CPtr, comparators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: Compare) -> t.CInt: pass
def type_name(self: Compare) -> str: pass
def dump(self: Compare, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Call(AST):
func: AST | t.CPtr
args: list[AST | t.CPtr] | t.CPtr
keywords: list[AST | t.CPtr] | t.CPtr
def __new__(self: Call, pool: memhub.MemManager | t.CPtr, func: AST | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: Call, pool: memhub.MemManager | t.CPtr, func: AST | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: Call) -> t.CInt: pass
def type_name(self: Call) -> str: pass
def dump(self: Call, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class BoolOp(AST):
op: t.CInt
values: list[AST | t.CPtr] | t.CPtr
def __new__(self: BoolOp, pool: memhub.MemManager | t.CPtr, op: t.CInt, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: BoolOp, pool: memhub.MemManager | t.CPtr, op: t.CInt, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: BoolOp) -> t.CInt: pass
def type_name(self: BoolOp) -> str: pass
def dump(self: BoolOp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Lambda(AST):
args: AST | t.CPtr
body: AST | t.CPtr
def __new__(self: Lambda, pool: memhub.MemManager | t.CPtr, args: AST | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
def __init__(self: Lambda, pool: memhub.MemManager | t.CPtr, args: AST | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
def kind(self: Lambda) -> t.CInt: pass
def type_name(self: Lambda) -> str: pass
def dump(self: Lambda, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class IfExp(AST):
test: AST | t.CPtr
body: AST | t.CPtr
orelse: AST | t.CPtr
def __new__(self: IfExp, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, body: AST | t.CPtr, orelse: AST | t.CPtr) -> t.CInt: pass
def __init__(self: IfExp, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, body: AST | t.CPtr, orelse: AST | t.CPtr) -> t.CInt: pass
def kind(self: IfExp) -> t.CInt: pass
def type_name(self: IfExp) -> str: pass
def dump(self: IfExp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Dict(AST):
keys: list[AST | t.CPtr] | t.CPtr
values: list[AST | t.CPtr] | t.CPtr
def __new__(self: Dict, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: Dict, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: Dict) -> t.CInt: pass
def type_name(self: Dict) -> str: pass
def dump(self: Dict, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Set(AST):
elts: list[AST | t.CPtr] | t.CPtr
def __new__(self: Set, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: Set, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: Set) -> t.CInt: pass
def type_name(self: Set) -> str: pass
def dump(self: Set, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class ListComp(AST):
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
def __new__(self: ListComp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: ListComp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: ListComp) -> t.CInt: pass
def type_name(self: ListComp) -> str: pass
def dump(self: ListComp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class SetComp(AST):
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
def __new__(self: SetComp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: SetComp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: SetComp) -> t.CInt: pass
def type_name(self: SetComp) -> str: pass
def dump(self: SetComp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class DictComp(AST):
key: AST | t.CPtr
value: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
def __new__(self: DictComp, pool: memhub.MemManager | t.CPtr, key: AST | t.CPtr, value: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: DictComp, pool: memhub.MemManager | t.CPtr, key: AST | t.CPtr, value: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: DictComp) -> t.CInt: pass
def type_name(self: DictComp) -> str: pass
def dump(self: DictComp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class GeneratorExp(AST):
elt: AST | t.CPtr
generators: list[AST | t.CPtr] | t.CPtr
def __new__(self: GeneratorExp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: GeneratorExp, pool: memhub.MemManager | t.CPtr, elt: AST | t.CPtr, generators: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: GeneratorExp) -> t.CInt: pass
def type_name(self: GeneratorExp) -> str: pass
def dump(self: GeneratorExp, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Await(AST):
value: AST | t.CPtr
def __new__(self: Await, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def __init__(self: Await, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def kind(self: Await) -> t.CInt: pass
def type_name(self: Await) -> str: pass
def dump(self: Await, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Yield(AST):
value: AST | t.CPtr
def __new__(self: Yield, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def __init__(self: Yield, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def kind(self: Yield) -> t.CInt: pass
def type_name(self: Yield) -> str: pass
def dump(self: Yield, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class YieldFrom(AST):
value: AST | t.CPtr
def __new__(self: YieldFrom, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def __init__(self: YieldFrom, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def kind(self: YieldFrom) -> t.CInt: pass
def type_name(self: YieldFrom) -> str: pass
def dump(self: YieldFrom, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class FormattedValue(AST):
value: AST | t.CPtr
conversion: t.CInt
format_spec: AST | t.CPtr
def __new__(self: FormattedValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, conversion: t.CInt, format_spec: AST | t.CPtr) -> t.CInt: pass
def __init__(self: FormattedValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, conversion: t.CInt, format_spec: AST | t.CPtr) -> t.CInt: pass
def kind(self: FormattedValue) -> t.CInt: pass
def type_name(self: FormattedValue) -> str: pass
def dump(self: FormattedValue, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class JoinedStr(AST):
values: list[AST | t.CPtr] | t.CPtr
def __new__(self: JoinedStr, pool: memhub.MemManager | t.CPtr, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def __init__(self: JoinedStr, pool: memhub.MemManager | t.CPtr, values: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
def kind(self: JoinedStr) -> t.CInt: pass
def type_name(self: JoinedStr) -> str: pass
def dump(self: JoinedStr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Attribute(AST):
value: AST | t.CPtr
attr: str
ctx: t.CInt
def __new__(self: Attribute, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, attr: str, ctx: t.CInt) -> t.CInt: pass
def __init__(self: Attribute, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, attr: str, ctx: t.CInt) -> t.CInt: pass
def kind(self: Attribute) -> t.CInt: pass
def type_name(self: Attribute) -> str: pass
def dump(self: Attribute, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Subscript(AST):
value: AST | t.CPtr
slice: AST | t.CPtr
ctx: t.CInt
def __new__(self: Subscript, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, slice: AST | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def __init__(self: Subscript, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, slice: AST | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def kind(self: Subscript) -> t.CInt: pass
def type_name(self: Subscript) -> str: pass
def dump(self: Subscript, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Starred(AST):
value: AST | t.CPtr
ctx: t.CInt
def __new__(self: Starred, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def __init__(self: Starred, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def kind(self: Starred) -> t.CInt: pass
def type_name(self: Starred) -> str: pass
def dump(self: Starred, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class List(AST):
elts: list[AST | t.CPtr] | t.CPtr
ctx: t.CInt
def __new__(self: List, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def __init__(self: List, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def kind(self: List) -> t.CInt: pass
def type_name(self: List) -> str: pass
def dump(self: List, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Tuple(AST):
elts: list[AST | t.CPtr] | t.CPtr
ctx: t.CInt
def __new__(self: Tuple, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def __init__(self: Tuple, pool: memhub.MemManager | t.CPtr, elts: list[AST | t.CPtr] | t.CPtr, ctx: t.CInt) -> t.CInt: pass
def kind(self: Tuple) -> t.CInt: pass
def type_name(self: Tuple) -> str: pass
def dump(self: Tuple, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class Slice(AST):
lower: AST | t.CPtr
upper: AST | t.CPtr
step: AST | t.CPtr
def __new__(self: Slice, pool: memhub.MemManager | t.CPtr, lower: AST | t.CPtr, upper: AST | t.CPtr, step: AST | t.CPtr) -> t.CInt: pass
def __init__(self: Slice, pool: memhub.MemManager | t.CPtr, lower: AST | t.CPtr, upper: AST | t.CPtr, step: AST | t.CPtr) -> t.CInt: pass
def kind(self: Slice) -> t.CInt: pass
def type_name(self: Slice) -> str: pass
def dump(self: Slice, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class NamedExpr(AST):
target: AST | t.CPtr
value: AST | t.CPtr
def __new__(self: NamedExpr, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def __init__(self: NamedExpr, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
def kind(self: NamedExpr) -> t.CInt: pass
def type_name(self: NamedExpr) -> str: pass
def dump(self: NamedExpr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
class OpNode(AST):
op: t.CInt
def __new__(self: OpNode, pool: memhub.MemManager | t.CPtr, op: t.CInt) -> t.CInt: pass
def __init__(self: OpNode, pool: memhub.MemManager | t.CPtr, op: t.CInt) -> t.CInt: pass
def kind(self: OpNode) -> t.CInt: pass
def type_name(self: OpNode) -> str: pass
def dump(self: OpNode, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass

View File

@@ -1,182 +0,0 @@
"""
Auto-generated Python stub file from ast.base.py
Module: ast.base
"""
import t, c
from stdint import *
import memhub
import string
import viperlib
from .tokens import TokOp
class ASTKind(t.CEnum):
Module: t.State
FunctionDef: t.State
ClassDef: t.State
Assign: t.State
If: t.State
For: t.State
While: t.State
Return: t.State
Expr: t.State
Name: t.State
Constant: t.State
BinOp: t.State
UnaryOp: t.State
Call: t.State
Compare: t.State
Expression: t.State
Interactive: t.State
FunctionType: t.State
Delete: t.State
AugAssign: t.State
AnnAssign: t.State
With: t.State
Raise: t.State
Try: t.State
Assert: t.State
Global: t.State
Nonlocal: t.State
Pass: t.State
Break: t.State
Continue: t.State
Import: t.State
ImportFrom: t.State
Match: t.State
BoolOp: t.State
Lambda: t.State
IfExp: t.State
Dict: t.State
Set: t.State
ListComp: t.State
SetComp: t.State
DictComp: t.State
GeneratorExp: t.State
Await: t.State
Yield: t.State
YieldFrom: t.State
FormattedValue: t.State
JoinedStr: t.State
Attribute: t.State
Subscript: t.State
Starred: t.State
List: t.State
Tuple: t.State
Slice: t.State
NamedExpr: t.State
ExceptHandler: t.State
Arguments: t.State
Arg: t.State
Keyword: t.State
Alias: t.State
WithItem: t.State
Comprehension: t.State
OpNode: t.State
MatchCase: t.State
MatchValue: t.State
MatchSingleton: t.State
MatchSequence: t.State
MatchMapping: t.State
MatchClass: t.State
MatchStar: t.State
MatchAs: t.State
MatchOr: t.State
class ASTCtx(t.CEnum):
Load: t.State
Store: t.State
Del: t.State
class OpKind(t.CEnum):
Add: t.State
Sub: t.State
Mult: t.State
MatMult: t.State
Div: t.State
Mod: t.State
Pow: t.State
LShift: t.State
RShift: t.State
BitOr: t.State
BitXor: t.State
BitAnd: t.State
FloorDiv: t.State
And: t.State
Or: t.State
Eq: t.State
Ne: t.State
Lt: t.State
Le: t.State
Gt: t.State
Ge: t.State
Is: t.State
IsNot: t.State
In: t.State
NotIn: t.State
Not: t.State
UAdd: t.State
USub: t.State
Invert: t.State
NoneOp: t.State
CONST_INT: t.CDefine = 1
CONST_FLOAT: t.CDefine = 2
CONST_STR: t.CDefine = 3
CONST_BOOL: t.CDefine = 4
CONST_NONE: t.CDefine = 5
FLAG_IS_ASYNC: t.CDefine = 1
FLAG_SIMPLE: t.CDefine = 2
FLAG_HAS_STAR: t.CDefine = 4
class ASTFlag(t.CEnum):
IsAsync: t.State
Simple: t.State
HasStar: t.State
def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str: pass
def _set_pos(node: AST | t.CPtr, lineno: t.CInt, col_offset: t.CInt, end_lineno: t.CInt, end_col_offset: t.CInt) -> t.CInt: pass
def _inherit_pos(node: AST | t.CPtr, ref: AST | t.CPtr) -> t.CInt: pass
def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr, lineno: t.CInt, col: t.CInt) -> t.CInt: pass
def _set_parent_list(lst: list[AST | t.CPtr] | t.CPtr, parent: AST | t.CPtr) -> t.CInt: pass
def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
def _binop_from_op(op_id: t.CInt) -> t.CInt: pass
def _augop_from_op(op_id: t.CInt) -> t.CInt: pass
def _cmpop_from_op(op_id: t.CInt) -> t.CInt: pass
def _emit(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, text: str) -> t.CSizeT: pass
def _emit_str(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, text: str) -> t.CSizeT: pass
def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT, val: t.CInt64T) -> t.CSizeT: pass
def _op_name(op: t.CInt) -> str: pass
def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
def _dump_op_list(lst: t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
@t.CVTable
class AST:
parent: AST | t.CPtr
pool: memhub.MemManager | t.CPtr
lineno: t.CInt
col_offset: t.CInt
end_lineno: t.CInt
end_col_offset: t.CInt
children: list[AST | t.CPtr] | t.CPtr
def kind(self: AST) -> t.CInt: pass
def type_name(self: AST) -> str: pass
def dump(self: AST, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
def accept(self: AST, visitor: t.CPtr) -> t.CInt: pass
def append(self: AST, node: AST | t.CPtr) -> t.CInt: pass
def dump(node: AST | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT) -> t.CInt: pass

View File

@@ -104,8 +104,8 @@ class ClassDef(AST):
keywords: list[AST | t.CPtr] | t.CPtr
decorator_list: list[AST | t.CPtr] | t.CPtr
type_params: list[str] | t.CPtr
def __new__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr) -> t.CInt: pass
def __init__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr) -> t.CInt: pass
def __new__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass
def __init__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass
def kind(self: ClassDef) -> t.CInt: pass
def type_name(self: ClassDef) -> str: pass
def dump(self: ClassDef, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass

View File

@@ -1 +0,0 @@
{"TypeRegistry.Register": "注册一个 TypeInfo。ti.Name 字段必须已设置。\n\n Returns:\n 1 表示成功0 表示失败ti 为 None 或 Name 为 None\n ", "TypeRegistry.Lookup": "按名称查找 TypeInfo。\n\n Returns:\n 找到返回 TypeInfo*,找不到返回 None\n ", "TypeRegistry.Has": "检查类型是否已注册。", "Mixin": "所有 Handle 的非多态基类:持有 Translator 回指针 + 共享委托方法", "Mixin.InitMixin": "初始化 Mixin 字段(子类 __init__ 中调用)"}

View File

@@ -1,54 +0,0 @@
"""
Auto-generated Python stub file from lib.core.Handles.HandlesBase.py
Module: lib.core.Handles.HandlesBase
"""
import t, c
from stdint import *
import string
import viperlib
import memhub
import hashtable
import lib.core.Handles.HandlesTranslator as HT
class TypeKind(t.CEnum):
Basic: t.State
Pointer: t.State
Struct: t.State
Union: t.State
Enum: t.State
Typedef: t.State
Function: t.State
Array: t.State
Void: t.State
@t.NoVTable
class TypeInfo:
Kind: int
Name: str
Size: int
Align: int
IsSigned: int
PtrCount: int
IsConst: int
IsVolatile: int
class TypeRegistry:
_ht: hashtable.HashTable | t.CPtr
__mbuddy__: memhub.MemManager | t.CPtr
def Register(self: TypeRegistry, ti: TypeInfo | t.CPtr) -> int: pass
def Lookup(self: TypeRegistry, name: str) -> TypeInfo | t.CPtr: pass
def Has(self: TypeRegistry, name: str) -> int: pass
def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr: pass
def NewTypeRegistry(pool: memhub.MemManager | t.CPtr) -> TypeRegistry | t.CPtr: pass
def TypeToLLVM(buf: t.CChar | t.CPtr, buf_size: t.CSizeT, ti: TypeInfo | t.CPtr) -> int: pass
@t.NoVTable
class Mixin:
Trans: HT.Translator | t.CPtr
def InitMixin(self: Mixin, trans: HT.Translator | t.CPtr) -> int: pass
_mbuddy: t.CExtern | t.CVoid | t.CPtr

View File

@@ -1 +0,0 @@
{"InitLib": "初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。\n\n Args:\n mb: memhub.MemManager 实例指针MemBuddy 等子类通过多态传入)\n\n Returns:\n 0 表示成功,非 0 表示失败\n "}

View File

@@ -1,14 +0,0 @@
"""
Auto-generated Python stub file from lib.__init__.py
Module: lib.__init__
"""
import t, c
from stdint import *
import memhub
import lib.core.VLogger as VLogger
_mbuddy: t.CExtern | memhub.MemManager | t.CPtr
def InitLib(mb: memhub.MemManager | t.CPtr) -> int: pass

File diff suppressed because one or more lines are too long

View File

@@ -1,80 +1,80 @@
067c78e9f121dce3:includes/w32\win32process.py
06f53cc594b4ac6c:includes/w32\win32sync.py
0c212981c180e7fb:includes/ast\lexer.py
0c9a196ed8f137a8:includes/llvmlite\__function.py
0df65b8ed15664b0:includes/hashlib\__sha1.py
0f2ec5a0ea127bf7:includes/w32\win32base.py
1563f524ea59aee2:lib/core/Handles/HandlesMain.py
1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.py
134678d620920327:lib/core/Handles/HandlesImports.py
19f8024d10c828e8:includes/hashlib\__md5.py
1c6a2fbc52efb1eb:includes/ast\parser.py
20cd49775c100a38:includes/json\__writer.py
22bc0df83b3f0e62:includes/ast\base.py
240a9a4157959a9f:includes/json\__parser.py
26bbf0af9e538483:lib/core/Handles/HandlesExprCall.py
2703a899f26b771d:lib/core/Handles/HandlesReturn.py
271ea3decb810db2:includes/atom.py
273767e73e99360d:lib/core/Handles/HandlesFunctions.py
2d39c6c7d3557b3e:includes/linkedlist.py
2d8debefda779c40:includes/llvmlite\__types.py
2da636c61863c815:includes/subprocess.py
30a3729d9d006176:lib/core/Handles/HandlesStruct.py
31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.py
34548789d646f432:includes/ast\__init__.py
3bfb3d482babffea:lib/core/StubMerger.py
36f17e746044defb:lib/core/Handles/HandlesType.py
3a8870350b3cb1f7:lib/core/Handles/HandlesStruct.py
4337fb260448bbe2:includes/ast\astaux.py
47767b5026a8ee15:includes/ast\exprs.py
4650533467115342:lib/Projectrans/Utils.py
4dd6b3f1427d1cc5:includes/ast\match.py
518fd98d3ebec951:lib/core/BuildPipeline.py
51f0144d6e8188d9:lib/core/Handles/HandlesWhile.py
5618258560f966d9:lib/core/Handles/HandlesAnnAssign.py
57288496f7c2d1ad:includes/json\__init__.py
57f5af31fb28c259:lib/core/BuildPipeline.py
5dab8cb390496d22:includes/ast\base.py
6293eee0a5805aa5:lib/core/Handles/HandlesImports.py
6282c9b745a35b8f:lib/core/IncludesScanner.py
63a3d17e96a083ac:lib/core/Handles/HandlesBase.py
647c596aeb1fd27c:lib/core/Handles/HandlesExprCall.py
6503c97dde0c79c4:includes/posix.py
657e182b27c2a022:includes/ast\stmts.py
668790e6c9efdbae:includes/_list.py
66de93aaeebc0601:lib/core/Handles/HandlesIf.py
68ddd5cc3fecbb2e:lib/Projectrans/Utils.py
692919c5a194ac8d:includes/llvmlite\__module.py
6a19179426e9a883:lib/__init__.py
6b3bc463fd044545:includes/llvmlite\__verify.py
6cb15dde11ae2df1:lib/core/Handles/HandlesExpr.py
6be4daa5dc5fa7ce:includes/string.py
6d88e12d1fb0efee:lib/core/Phase2.py
6f62fe05c5ea1ceb:includes/stdio.py
6ff26590374ae6fc:includes/hashlib\__sha512.py
71e0a3ffcb3ebfad:includes/stdarg.py
727a218636fc49ab:lib/core/Handles/HandlesFor.py
769a4c9b8dda31e0:lib/core/IncludesScanner.py
72dbbb563aa943b0:includes/w32\fileio.py
81eb28ba912467a6:lib/core/Handles/HandlesBody.py
83ba314b4637eec9:lib/core/Handles/HandlesBase.py
86ed9b466210d090:includes/w32\fileio.py
8f12094c840be06a:lib/__init__.py
88811298a7b47d02:lib/core/Handles/HandlesMain.py
8cf4461e82a4ecf2:lib/core/Handles/HandlesAssign.py
90c53dd6db8d41cf:includes/stdlib.py
9335f9c689852ba5:includes/argparse.py
93c1d18e35d188d6:includes/platmacro.py
96837bcc64032444:includes/hashlib\__init__.py
a299b2ce21d25f48:lib/StubGen/Converter.py
a9f3c850055ba988:includes/llvmlite\__builder.py
aeb3b313894c4616:includes/memhub.py
adde71d4f0a1f628:includes/llvmlite\__builder.py
af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.py
b4d2098ceb689168:includes/ast\parser.py
b543bc1dfb592119:includes/ast\exprs.py
b547ac4f380bddb6:includes/ast\tokens.py
b5a965302cded36b:includes/sys.py
b8c66c8ff44eb874:includes/hashtable.py
ba12ed409d78139e:includes/string.py
bb6aff9d8496ec9f:lib/core/Phase2.py
bbc9ba0a1caf7acd:lib/core/Handles/HandlesAssign.py
ba2b074357dcd3b5:includes/memhub.py
bbdf3bbd4c3bc28c:includes/w32\win32console.py
bc03c843b00a8e64:lib/core/Phase1.py
be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.py
bfa1cc81748c0271:lib/core/Handles/HandlesClassDef.py
c0042adc0b7ec5df:lib/Projectrans/Config.py
c2010cffc6092ea2:main.py
c3b259b4059f8668:includes/viperlib.py
c8f9dfae54946053:lib/core/Handles/HandlesType.py
c6b0b8148dc63d5c:lib/core/Handles/HandlesExpr.py
c9d54a4158f7f5a8:includes/hashlib\__sha256.py
c9f4be41ca1cc2b4:includes/viperio.py
ca44e2bae615339f:includes/argparse.py
cb1aa3a78af6f362:lib/core/Handles/HandlesVar.py
eeaeebbc850a20f1:lib/Projectrans/Config.py
dda2d0326dda1ff5:lib/core/Handles/HandlesAnnAssign.py
e217def267d3d4a8:includes/ast\lexer.py
ec8cf4a355eb1a65:lib/core/Phase1.py
ede1b9cd3f28e8c8:lib/core/StubMerger.py
f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.py
f1aabfe4d0e2b893:lib/core/VLogger.py
f1e8dabe2ec63f05:lib/core/VLogger.py
f23f91ad42cb466f:includes/llvmlite\__init__.py
f2a3bab94f5087b8:main.py
f331c46316ec1dd3:lib/core/Handles/HandlesTranslator.py
f3444ec56937284f:includes/ast\__init__.py
f5522571bcce7bcb:includes/stdint.py
f6b51804a0ba8ff0:includes/w32\win32file.py
f9e36e2cd6fa659f:includes/llvmlite\__values.py
fd52aebc25e17276:lib/core/Handles/HandlesClassDef.py
fc980acec33d69a7:includes/w32\win32base.py

Binary file not shown.

View File

@@ -12,7 +12,7 @@ class Buf:
length: t.CSizeT
capacity: t.CSizeT
owned: bool
def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass
def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT = 0, owned: bool = False) -> t.CInt: pass
def clear(self: Buf) -> t.CInt: pass
def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass
def cstr(self: Buf) -> t.CChar | t.CPtr: pass

View File

@@ -127,33 +127,26 @@ class ArgumentParser:
def __new__(self, prog: str = "", description: str = "",
pool: memhub.MemBuddy | t.CPtr = None) -> t.CPtr:
stdio.printf("[DBG-argparse] __new__ enter pool=%p\n", pool)
stdio.fflush(0)
mb: memhub.MemBuddy | t.CPtr = pool
if mb is None: mb = _mbuddy
stdio.printf("[DBG-argparse] __new__ mb=%p\n", mb)
stdio.fflush(0)
ret: t.CPtr = mb.alloc(40)
stdio.printf("[DBG-argparse] __new__ ret=%p\n", ret)
stdio.fflush(0)
return ret
def __init__(self, prog: str = "", description: str = "",
pool: memhub.MemBuddy | t.CPtr = None):
stdio.printf("[DBG-argparse] __init__ enter self=%p pool=%p\n", self, pool)
stdio.fflush(0)
mb: memhub.MemBuddy | t.CPtr = pool
if mb is None: mb = _mbuddy
stdio.printf("[DBG-argparse] __init__ mb=%p\n", mb)
stdio.fflush(0)
self.__mbuddy__ = mb
self._prog = prog
self._description = description
self._arg_count = 0
stdio.printf("[DBG-argparse] __init__ before alloc\n")
stdio.fflush(0)
self._args = mb.alloc(MAX_ARGS * Argument.__sizeof__())
stdio.printf("[DBG-argparse] __init__ after alloc _args=%p\n", self._args)
stdio.fflush(0)
def add_argument(self, name: str = "", short: str = None,
arg_type: INT = 0, default: INT = 0,
@@ -172,17 +165,13 @@ class ArgumentParser:
help: 帮助文本
"""
stdio.printf("[DBG-argparse] enter add_argument name=%s args_ptr=%p\n", name, self._args)
stdio.fflush(0)
if self._arg_count >= MAX_ARGS: return
idx: INT = self._arg_count
stdio.printf("[DBG-argparse] idx=%d sizeof(Argument)=%d\n", idx, Argument.__sizeof__())
stdio.fflush(0)
arg: Argument | t.CPtr = t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())
stdio.printf("[DBG-argparse] arg ptr=%p\n", arg)
stdio.fflush(0)
arg.name = name
stdio.printf("[DBG-argparse] after arg.name=%s\n", arg.name)
stdio.fflush(0)
arg.short_name = short
arg.help_text = help
arg.arg_type = arg_type
@@ -191,7 +180,6 @@ class ArgumentParser:
arg.default_str = default_str
arg.required = required
stdio.printf("[DBG-argparse] before dest logic\n")
stdio.fflush(0)
# 判断是否位置参数
if name is not None and name[0] != '-':
arg.is_positional = True
@@ -203,10 +191,8 @@ class ArgumentParser:
else:
arg.dest = name + 1
stdio.printf("[DBG-argparse] after dest logic\n")
stdio.fflush(0)
self._arg_count = idx + 1
stdio.printf("[DBG-argparse] exit add_argument\n")
stdio.fflush(0)
def _get_arg(self, idx: INT) -> Argument | t.CPtr:
return t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())

View File

@@ -11,7 +11,7 @@ from .tokens import (
from .base import (
AST, ASTKind, ASTCtx, OpKind, ASTFlag,
# 常量
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE,
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR,
FLAG_IS_ASYNC, FLAG_SIMPLE, FLAG_HAS_STAR,
# 辅助函数
_init_ast, _copy_str, _set_pos, _inherit_pos, _set_parent_list,

View File

@@ -148,6 +148,7 @@ CONST_FLOAT: t.CDefine = 2
CONST_STR: t.CDefine = 3
CONST_BOOL: t.CDefine = 4
CONST_NONE: t.CDefine = 5
CONST_CHAR: t.CDefine = 6
# 标志位
FLAG_IS_ASYNC: t.CDefine = 1

View File

@@ -6,7 +6,7 @@ from .base import (
AST, ASTKind, ASTCtx, OpKind,
_init_ast, _copy_str, _set_parent_list,
_emit, _emit_str, _emit_int, _dump_list, _dump_op_list, _op_name,
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR
)
@@ -106,6 +106,11 @@ class Constant(AST):
else:
pos = _emit(buf, size, pos, "(null)")
pos = _emit(buf, size, pos, "'")
elif self.const_kind == CONST_CHAR:
# 单引号单字符 → 显示为字符 ASCII 值
pos = _emit(buf, size, pos, "char(")
pos = _emit_int(buf, size, pos, self.int_val)
pos = _emit(buf, size, pos, ")")
elif self.const_kind == CONST_BOOL:
if self.int_val != 0:
pos = _emit(buf, size, pos, "True")

View File

@@ -530,6 +530,8 @@ def _read_string(lx: Lexer | t.CPtr):
tok: Token | t.CPtr = new_token(lx.pool, TokenType.String, start_lineno, start_col)
if tok == None: return
content_len: t.CSizeT = content_end - content_buf_start
# esc_len: 转义后实际字节数(用于判断单字符)
esc_len: t.CSizeT = content_len
# 处理转义序列(非 raw 字符串)
if is_raw == 0 and content_len > 0:
@@ -572,15 +574,22 @@ def _read_string(lx: Lexer | t.CPtr):
rpos += 1
conv_buf[wpos] = '\0'
token_set_str_literal(lx.pool, tok, conv_buf)
esc_len = wpos
else:
token_set_str(lx.pool, tok, lx.src, content_buf_start, content_len)
tok.end_lineno = lx.lineno
tok.end_col_offset = lx.col
# flags 字段复用bit0=raw, bit1=bytes, bit2=fstring, bit3=triple
# flags 字段复用bit0=raw, bit1=bytes, bit2=fstring, bit3=triple, bit4=dquote, bit5=单字符候选
if is_raw: tok.kw_subtype = tok.kw_subtype | 1
if is_bytes: tok.kw_subtype = tok.kw_subtype | 2
if is_fstring: tok.kw_subtype = tok.kw_subtype | 4
if is_triple: tok.kw_subtype = tok.kw_subtype | 8
# bit4 (16) = 双引号0=单引号, 1=双引号)
if quote == '"': tok.kw_subtype = tok.kw_subtype | 16
# bit5 (32) = 单字符候选(非三引号、非 fstring、转义后正好 1 字节)
# 用于 CONST_CHAR 判定,避免 '\0' 等含 NUL 字节被 strlen 误判为空字符串
if is_triple == 0 and is_fstring == 0 and esc_len == 1:
tok.kw_subtype = tok.kw_subtype | 32
_emit(lx, tok)

View File

@@ -7,7 +7,7 @@ from .base import (
AST, ASTCtx, ASTKind, OpKind, ASTFlag,
_set_pos, _binop_from_op, _augop_from_op, _cmpop_from_op, _copy_str, _inherit_pos,
_init_ast,
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE,
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE, CONST_CHAR,
FLAG_IS_ASYNC,
)
from .exprs import (
@@ -169,7 +169,30 @@ def _new_const_float(pool: memhub.MemManager | t.CPtr, val: t.CDouble,
def _new_const_str(pool: memhub.MemManager | t.CPtr, val: str,
lineno: t.CInt, col: t.CInt) -> AST | t.CPtr:
lineno: t.CInt, col: t.CInt,
is_dquote: t.CInt = 1,
is_triple: t.CInt = 0,
is_char: t.CInt = 0) -> AST | t.CPtr:
"""创建字符串/字符常量节点
is_dquote: 0=单引号, 非0=双引号(默认双引号)
is_triple: 非0=三引号字符串
is_char: 非0=单字符候选lexer 已确认转义后正好 1 字节, 含 '\\0'
语义区分:
- 'x' (单引号单字符, 非三引号) → CONST_CHAR (i8 值)
- "x" (双引号, 含\\0终止符) → CONST_STR (i8* 指针, i8 x 2)
- 'ab' (单引号多字符) → CONST_STR (i8* 指针)
- '''x''' / \"\"\"x\"\"\" (三引号) → CONST_STR (i8* 指针)
- '' / \"\" (空字符串) → CONST_STR (i8* 指针)
"""
# 单引号、非三引号、lexer 标记的单字符候选 → CONST_CHAR
# 用 is_char 标记而非 strlen(val),因为 '\0' 转义后是 NUL 字节strlen 会返回 0
if is_dquote == 0 and is_triple == 0 and is_char != 0:
# 单字符 → CONST_CHARint_val 存储字符 ASCII 值
# val[0] 即使是 NUL 也是合法值 0
ch_val: t.CInt64T = val[0]
return Constant(pool, CONST_CHAR, ch_val, 0.0, val, lineno, col)
# 其他情况 → CONST_STR
return Constant(pool, CONST_STR, 0, 0.0, val, lineno, col)
@@ -751,10 +774,13 @@ def _parse_atom(ps: Parser | t.CPtr) -> AST | t.CPtr:
if ttype == TokenType.String:
sval: str = _cur_str(ps)
is_fstr: t.CInt = ps.cur.kw_subtype & 4
is_triple: t.CInt = ps.cur.kw_subtype & 8
is_dquote: t.CInt = ps.cur.kw_subtype & 16
is_char: t.CInt = ps.cur.kw_subtype & 32
_advance(ps)
if is_fstr:
return _parse_fstring(ps, sval, lineno, col)
return _new_const_str(ps.pool, sval, lineno, col)
return _new_const_str(ps.pool, sval, lineno, col, is_dquote, is_triple, is_char)
if _match_op(ps, TokOp.Ellipsis):
_advance(ps)
@@ -1551,12 +1577,14 @@ def _parse_from_import(ps: Parser | t.CPtr) -> AST | t.CPtr:
level += 3
_advance(ps)
module_name: str = None
if _cur_type(ps) == TokenType.Name:
# 关键字(如 import的 token type 也是 Name必须通过 kw_subtype 排除,
# 否则 `from . import` 中的 `import` 会被误认为 module_name
if _cur_type(ps) == TokenType.Name and _cur_kw(ps) == Keyword.NotKeyword:
module_name = _cur_str(ps)
_advance(ps)
while _match_op(ps, TokOp.Dot):
_advance(ps)
if _cur_type(ps) == TokenType.Name:
if _cur_type(ps) == TokenType.Name and _cur_kw(ps) == Keyword.NotKeyword:
next_name: str = _cur_str(ps)
mlen: t.CInt = string.strlen(module_name)
nlen: t.CInt = string.strlen(next_name)
@@ -1571,6 +1599,7 @@ def _parse_from_import(ps: Parser | t.CPtr) -> AST | t.CPtr:
ps.error_count += 1
return None
_advance(ps)
_skip_nl(ps)
# import *
if _match_op(ps, TokOp.Star):
_advance(ps)
@@ -2058,8 +2087,9 @@ def _parse_closed_pattern(ps: Parser | t.CPtr) -> AST | t.CPtr:
# 字符串字面量 pattern
if ttype == TokenType.String:
sval = _cur_str(ps)
is_dquote_m: t.CInt = ps.cur.kw_subtype & 16
_advance(ps)
val = _new_const_str(ps.pool, sval, lineno, col)
val = _new_const_str(ps.pool, sval, lineno, col, is_dquote_m)
node = MatchValue(ps.pool, val)
_set_pos(node, lineno, col, 0, 0)
return node

View File

@@ -847,10 +847,28 @@ def build_ui2fp(builder: IRBuilder | t.CPtr, val: Value | t.CPtr,
# ============================================================
# GEP 指令
# ============================================================
def _is_ptr_type(ty: LLVMType | t.CPtr) -> int:
"""检查 ty 是否是 Ptr 类型(独立函数,避免嵌套 match 的编译器 BUG"""
if ty is None:
return 0
match ty:
case LLVMType.Ptr(pointee):
return 1
case _:
return 0
def build_gep(builder: IRBuilder | t.CPtr, elem_ty: LLVMType | t.CPtr,
ptr: Value | t.CPtr, idx: Value | t.CPtr) -> Value | t.CPtr:
"""%N = getelementptr <elem_ty>, <ptr_ty> <ptr>, <idx_ty> <idx>"""
if builder is None or ptr is None or idx is None: return None
# 防御性检查: ptr.Ty 必须是指针类型,否则 llc 报错
# "base of getelementptr must be a pointer"
# 当 translate_value 返回非指针值(如 i32 常量 0
# 直接 GEP 会导致 llc 编译失败
if _is_ptr_type(ptr.Ty) == 0:
stdio.printf("[GEP-ERR] base not pointer, skip GEP\n")
return None
pool: memhub.MemBuddy | t.CPtr = builder.Pool
name: t.CChar | t.CPtr = _alloc_ssa_name(builder)
elem_ty_s: t.CChar | t.CPtr = _type_str(builder, elem_ty)
@@ -918,7 +936,6 @@ def build_gep_struct(builder: IRBuilder | t.CPtr, struct_ty: LLVMType | t.CPtr,
line: t.CChar | t.CPtr = pool.alloc(2048)
if line is None:
stdio.printf("[BGS] line alloc None\n")
stdio.fflush(0)
return None
viperlib.snprintf(line, 2048, "%s = getelementptr %s, %s %s, i32 0, i32 %d",
name, struct_ty_s, ptr_ty_s, ptr.Name, field_idx)
@@ -928,14 +945,12 @@ def build_gep_struct(builder: IRBuilder | t.CPtr, struct_ty: LLVMType | t.CPtr,
result_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if result_ty is None:
stdio.printf("[BGS] result_ty alloc None\n")
stdio.fflush(0)
else:
string.memset(result_ty, 0, LLVMType.__sizeof__())
c.DerefAs(result_ty, LLVMType.Ptr(field_ty))
rv: Value | t.CPtr = SSAValue(pool, result_ty, name)
if rv is None:
stdio.printf("[BGS] SSAValue None\n")
stdio.fflush(0)
return rv

View File

@@ -435,7 +435,6 @@ class MemBuddy(MemManager):
ub: t.CSizeT = self.usable_size - fb
stdio.printf("[MEM-FAIL] alloc(%zu) failed: total=%zu used=%zu free=%zu free_blocks=%zu\n",
size, self.usable_size, ub, fb, self.free_count())
stdio.fflush(0)
self._unlock()
return result
@@ -534,7 +533,6 @@ class MemBuddy(MemManager):
label, self.usable_size, ub,
(ub * 100) / self.usable_size if self.usable_size > 0 else 0,
fb, self.free_count())
stdio.fflush(0)
def self_check(self) -> t.CInt:
# 验证伙伴分配器内部一致性,返回 0=OK非 0=损坏

View File

@@ -262,11 +262,30 @@ def atoll(src: str) -> t.CInt64T:
s += 1
elif s[0] == '+':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
d: t.CInt = ch - '0'
digit: t.CInt64T = t.CInt64T(d)
num = num * 10 + digit
# 十六进制前缀 0x / 0X
is_hex: t.CInt = 0
if s[0] == '0' and (s[1] == 'x' or s[1] == 'X'):
is_hex = 1
s += 2
if is_hex:
for ch in s:
d: t.CInt = 0
if ch >= '0' and ch <= '9':
d = ch - '0'
elif ch >= 'a' and ch <= 'f':
d = ch - 'a' + 10
elif ch >= 'A' and ch <= 'F':
d = ch - 'A' + 10
else:
break
digit: t.CInt64T = t.CInt64T(d)
num = num * 16 + digit
else:
for ch in s:
if ch < '0' or ch > '9': break
d: t.CInt = ch - '0'
digit: t.CInt64T = t.CInt64T(d)
num = num * 10 + digit
return num * sign

View File

@@ -20,13 +20,11 @@ def begin(name: str):
SetConsoleOutputCP(CP_UTF8)
SetConsoleCP(CP_UTF8)
stdio.printf("=== %s ===\n\n", name)
stdio.fflush(None)
def section(name: str):
"""打印分节标题"""
stdio.printf("--- %s ---\n", name)
stdio.fflush(None)
def ok(msg: str):
@@ -34,7 +32,6 @@ def ok(msg: str):
global _pass_count
_pass_count += 1
stdio.printf("PASS: %s\n", msg)
stdio.fflush(None)
def fail(msg: str):
@@ -42,7 +39,6 @@ def fail(msg: str):
global _fail_count
_fail_count += 1
stdio.printf("FAIL: %s\n", msg)
stdio.fflush(None)
def check(cond: t.CInt, ok_msg: str, fail_msg: str):
@@ -56,7 +52,6 @@ def check(cond: t.CInt, ok_msg: str, fail_msg: str):
def info(msg: str):
"""打印信息消息(不计入 PASS/FAIL"""
stdio.printf("%s\n", msg)
stdio.fflush(None)
def end() -> t.CInt:
@@ -66,7 +61,6 @@ def end() -> t.CInt:
_total_fail += _fail_count
stdio.printf("\n--- Summary ---\n")
stdio.printf("PASS: %d, FAIL: %d\n", _pass_count, _fail_count)
stdio.fflush(None)
return _fail_count
@@ -74,5 +68,4 @@ def summary() -> t.CInt:
"""打印所有套件的总计汇总,返回总失败数"""
stdio.printf("\n=== Total Summary ===\n")
stdio.printf("Total PASS: %d, Total FAIL: %d\n", _total_pass, _total_fail)
stdio.fflush(None)
return _total_fail

View File

@@ -51,9 +51,6 @@ class File:
self.is_append = False
self._share_mode = share
stdio.printf("[FILE] __init__ filename=%s mode=%d share=%d\n", filename, mode, share)
stdio.fflush(0)
access: ULONG = 0
disposition: ULONG = w32.win32file.OPEN_EXISTING
@@ -100,18 +97,12 @@ class File:
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
stdio.printf("[FILE] before CreateFileA access=%d disp=%d share=%d\n", access, disposition, self._share_mode)
stdio.fflush(0)
self.handle = w32.win32file.CreateFileA(
filename, access, self._share_mode,
None, disposition, w32.win32file.FILE_ATTRIBUTE_NORMAL, None
)
stdio.printf("[FILE] after CreateFileA handle=%p\n", self.handle)
stdio.fflush(0)
if self.handle == w32.win32base.INVALID_HANDLE_VALUE:
stdio.printf("[FILE] FAIL: handle == INVALID_HANDLE_VALUE\n")
stdio.fflush(0)
self.closed = True
return
@@ -202,21 +193,16 @@ class File:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
if max_count < 2: return FRESULT.ERR
# stdio.printf("[DBG read_all] before size()\n")
file_size: LONGLONG = self.size()
# stdio.printf("[DBG read_all] after size(), file_size=%lld\n", file_size)
if file_size < 0: return FRESULT.ERR_IO
to_read: ULONG = 0
if file_size < max_count - 1:
to_read = ULONG(file_size)
else:
to_read = max_count - 1
# stdio.printf("[DBG read_all] to_read=%u, before seek\n", to_read)
self.seek(0, SEEK_SET)
# stdio.printf("[DBG read_all] after seek, before ReadFile\n")
bytes_read: ULONG = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf, to_read, t.CPtr(c.Addr(bytes_read)), None)
# stdio.printf("[DBG read_all] after ReadFile, result=%d, bytes_read=%u\n", result, bytes_read)
if result == 0: return FRESULT.ERR_IO
if bytes_read < max_count:
buf[bytes_read] = 0

View File

@@ -5,7 +5,7 @@ HANDLE: t.CTypedef = VOIDPTR
LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr
LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr
INVALID_HANDLE_VALUE: t.CDefine = 0xFFFFFFFF
INVALID_HANDLE_VALUE: t.CDefine = -1
NULL: t.CDefine = 0
TRUE: t.CDefine = 1
FALSE: t.CDefine = 0

View File

@@ -23,7 +23,18 @@ from StubGen import PythonToStubConverter
def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object]) -> None:
"""从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。"""
"""从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。
治本修复:原实现只支持 ast.Constant 和 float() 调用,
无法处理 t.CUnsignedLong(-11)ast.Call
FOREGROUND_GREEN | FOREGROUND_INTENSITYast.BinOp等复杂表达式。
现使用 ConstEvaluator.eval_full 统一求值,支持:
- ast.Constant: 简单常量 (0x0002)
- ast.Call: 类型构造 (t.CUnsignedLong(-11))
- ast.BinOp: 位运算 (FOREGROUND_RED | FOREGROUND_GREEN)
- ast.UnaryOp: 一元运算 (-11)
- ast.Name: 引用其他 CDefine 常量
"""
if not os.path.exists(pyi_path):
return
try:
@@ -31,16 +42,25 @@ def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object]) ->
_, tree = parse_python_file(pyi_path)
if tree is None:
return
# 治本修复:使用 ConstEvaluator 处理复杂表达式
# 创建 mock Gen 对象,其 _define_constants 指向 all_dc
# 使 ConstEvaluator 能查找同文件中已提取的常量(如 FOREGROUND_RED 引用 FOREGROUND_BLUE
from lib.core.ConstEvaluator import ConstEvaluator, EvalContext
class _MockGen:
"""轻量 mock仅提供 _define_constants 供 ConstEvaluator 查找"""
def __init__(self) -> None:
self._define_constants: dict[str, object] = all_dc
mock_gen: _MockGen = _MockGen()
ctx: EvalContext = EvalContext(Gen=mock_gen)
for node in ast.iter_child_nodes(tree):
if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name):
if AnnotationContainsName(node.annotation, 'CDefine') and node.value:
val = None
if isinstance(node.value, ast.Constant):
val = node.value.value
elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], ast.Constant):
val = node.value.args[0].value
if val is not None:
all_dc[f"{node.target.id}"] = val
val: object = ConstEvaluator.eval_full(node.value, ctx)
if val is not None and isinstance(val, (int, float, str)):
all_dc[node.target.id] = val
except Exception as e:
_vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e)

View File

@@ -477,16 +477,34 @@ class PythonToStubConverter:
lines.append(f'{IndentStr}@{DecoratorStr}')
# 构建参数列表
# 治本修复:原实现只遍历 node.args.args完全忽略 node.args.defaults
# 导致带默认值的参数(如 category: str = "")在 .pyi 中丢失默认值。
# 下游 DeclarationGenerator 据此生成 stub.ll 时,会因缺少默认参数而
# 生成参数数量不足的 declare进而造成调用方 ABI 不匹配崩溃。
# 修复:按 Python AST 语义defaults 从右向左对应 args 末尾的参数,
# 对有默认值的参数附加 '= <default_value>'。
params: list[str] = []
NumDefaults: int = len(node.args.defaults) if node.args.defaults else 0
DefaultsStart: int = len(node.args.args) - NumDefaults
for arg_idx, arg in enumerate(node.args.args):
ArgName: str = arg.arg
if arg.annotation:
TypeStr: str = PythonToStubConverter._GetTypeString(arg.annotation)
params.append(f'{ArgName}: {TypeStr}')
ParamPart: str = f'{ArgName}: {TypeStr}'
elif class_name and arg_idx == 0 and ArgName == 'self':
params.append(f'self: {class_name}')
ParamPart = f'self: {class_name}'
else:
params.append(ArgName)
ParamPart = ArgName
# 附加默认值defaults[i] 对应 args[DefaultsStart + i]
if NumDefaults > 0 and arg_idx >= DefaultsStart:
DefaultIdx: int = arg_idx - DefaultsStart
try:
DefaultStr: str = ast.unparse(node.args.defaults[DefaultIdx])
ParamPart = f'{ParamPart} = {DefaultStr}'
except Exception:
# unparse 失败时保留无默认值形式,避免阻塞生成
pass
params.append(ParamPart)
# 处理 *args
if node.args.vararg:

View File

@@ -20,6 +20,9 @@ from typing import Any, Callable, Optional, TYPE_CHECKING
import llvmlite.ir as ir
from lib.core.Handles.HandlesBase import CTypeInfo
# 治本修复:导入 t 模块和 CType 基类,用于类型构造调用求值(如 t.CUnsignedLong(-11)
from lib.includes import t as _t_module
from lib.includes.t import CType as _CType_base
if TYPE_CHECKING:
from lib.core.LlvmCodeGenerator import LlvmCodeGenerator
@@ -36,7 +39,7 @@ class ConstEvaluator:
def eval_with_symtab(node: ast.AST, symtab: Any) -> Optional[Any]:
"""求值常量表达式,支持从 SymbolTable 查找 define 值。
支持: Constant, BinOp, UnaryOp, Name(define), Attribute(define)
支持: Constant, BinOp, UnaryOp, Name(define), Attribute(define), Call(类型构造)
"""
if isinstance(node, ast.Constant):
return node.value
@@ -52,8 +55,68 @@ class ConstEvaluator:
if size_val is not None:
return size_val
return ConstEvaluator._eval_attribute_define(node, symtab)
# 治本修复:支持 t.CUnsignedLong(-11) 等类型构造调用
if isinstance(node, ast.Call):
return ConstEvaluator._eval_ctype_ctor_call(node, symtab)
return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_with_symtab(n, symtab))
@staticmethod
def _eval_ctype_ctor_call(node: ast.Call, symtab: Any) -> Optional[Any]:
"""求值类型构造调用,如 t.CUnsignedLong(-11)、CInt(42)。
在无 ctxEvalContext的场景下通过 symtab 和 t 模块直接求值。
按类型的 Size 和 IsSigned 应用位掩码。
"""
func: ast.expr = node.func
func_name: str | None = None
module_name: str | None = None
if isinstance(func, ast.Attribute):
if isinstance(func.value, ast.Name):
module_name = func.value.id
func_name = func.attr
elif isinstance(func, ast.Name):
func_name = func.id
ctype_cls: Any = None
if module_name == 't' and func_name:
ctype_cls = getattr(_t_module, func_name, None)
elif func_name and not module_name:
ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is None and symtab:
t_type_syms = getattr(symtab, '_t_type_symbols', {})
cls_candidate = t_type_syms.get(func_name)
if cls_candidate is not None:
ctype_cls = cls_candidate
if ctype_cls is None or not (isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base)):
return None
if not node.args:
return None
arg_val: Any = ConstEvaluator.eval_with_symtab(node.args[0], symtab)
if arg_val is None:
return None
size: int | None = None
is_signed: bool | None = None
try:
tmp_inst = ctype_cls()
size = getattr(tmp_inst, 'Size', None)
is_signed = getattr(tmp_inst, 'IsSigned', None)
except Exception:
pass
if isinstance(arg_val, int) and size and size > 0:
mask: int = (1 << size) - 1
if is_signed:
masked: int = arg_val & mask
if masked >= (1 << (size - 1)):
masked -= (1 << size)
return masked
else:
return arg_val & mask
return arg_val
# ==================================================================
# Level 3: + Gen._define_constants / _all_define_constants / 平台宏
# ==================================================================
@@ -147,7 +210,7 @@ class ConstEvaluator:
@staticmethod
def _eval_compile_time_call(node: ast.Call, ctx: 'EvalContext') -> Optional[Any]:
"""处理编译时函数调用,如 ctraits.isptr(x)"""
"""处理编译时函数调用,如 ctraits.isptr(x)、t.CUnsignedLong(-11)"""
func: ast.expr = node.func
func_name: str | None = None
module_name: str | None = None
@@ -200,6 +263,60 @@ class ConstEvaluator:
return None
except Exception:
return None
# 治本修复:支持 t.CUnsignedLong(-11) 等类型构造调用
# 当 t.CUnsignedLong(value) / CUnsignedInt(value) / CInt(value) 等被用作常量表达式时,
# 求值参数并返回(按类型的无符号/有符号语义应用位掩码)。
# 这修复了 stdint.py 中 INFINITE = t.CUnsignedLong(-1) 等常量无法被求值的问题。
is_ctype_ctor: bool = False
ctype_cls: Any = None
if module_name == 't' and func_name:
ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is not None and isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base):
is_ctype_ctor = True
elif func_name and not module_name:
# from t import CUnsignedLong 形式
ctype_cls = getattr(_t_module, func_name, None)
if ctype_cls is not None and isinstance(ctype_cls, type) and issubclass(ctype_cls, _CType_base):
is_ctype_ctor = True
# 也检查 _t_type_symbols符号表中的 t 模块类型符号)
if not is_ctype_ctor and ctx.symtab:
t_type_syms = getattr(ctx.symtab, '_t_type_symbols', {})
cls_candidate = t_type_syms.get(func_name)
if cls_candidate is not None and isinstance(cls_candidate, type) and issubclass(cls_candidate, _CType_base):
ctype_cls = cls_candidate
is_ctype_ctor = True
if is_ctype_ctor and node.args:
try:
arg_node: ast.expr = node.args[0]
arg_val: Any = ConstEvaluator.eval_full(arg_node, ctx)
if arg_val is None:
return None
# 按类型的 Size 和 IsSigned 应用位掩码
size: int | None = getattr(ctype_cls, '_Size', None)
is_signed: bool | None = getattr(ctype_cls, '_IsSigned', None)
# 尝试创建临时实例获取 Size/IsSigned
try:
tmp_inst = ctype_cls()
size = getattr(tmp_inst, 'Size', size)
is_signed = getattr(tmp_inst, 'IsSigned', is_signed)
except Exception:
pass
if isinstance(arg_val, int) and size and size > 0:
mask: int = (1 << size) - 1
if is_signed:
# 有符号类型:解释为补码
masked: int = arg_val & mask
if masked >= (1 << (size - 1)):
masked -= (1 << size)
return masked
else:
# 无符号类型:直接掩码
return arg_val & mask
return arg_val
except Exception:
return None
return None
@staticmethod

View File

@@ -328,9 +328,14 @@ class ExprHandle(BaseHandle):
def _HandleNameLlvm(self, Node: ast.Name, VarType: ir.Type | str | None = None) -> ir.Value:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
VarName: str = Node.id
# [CD] 诊断仅对关键常量输出FOREGROUND_*, BACKGROUND_*, STD_*, *HANDLE*
import sys as _sys
_is_cd_key: bool = isinstance(VarName, str) and (VarName.startswith('FOREGROUND_') or VarName.startswith('BACKGROUND_') or 'STD_' in VarName or 'HANDLE' in VarName)
define_constants: dict[str, Any] = getattr(Gen, '_define_constants', {})
if VarName in define_constants:
val: Any = define_constants[VarName]
if _is_cd_key:
print(f"[CD] lookup: '{VarName}' found in _define_constants val={val}", file=_sys.stderr, flush=True)
if isinstance(val, int):
# Use VarType hint if available to avoid unnecessary type mismatch
if VarType is not None and isinstance(VarType, ir.IntType):
@@ -347,11 +352,13 @@ class ExprHandle(BaseHandle):
elif isinstance(val, str):
return Gen._create_string_global(val)
# 如果 _define_constants 中没有,尝试从符号表查找
if VarName not in getattr(Gen, '_define_constants', {}):
if VarName not in define_constants:
try:
sym_info: Any = self.translator.SymbolTable.lookup(VarName)
sym_info: Any = self.Trans.SymbolTable.lookup(VarName)
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
val = sym_info.DefineValue
if _is_cd_key:
print(f"[CD] lookup: '{VarName}' found in SymbolTable val={val}", file=_sys.stderr, flush=True)
if isinstance(val, int):
# Use VarType hint if available
if VarType is not None and isinstance(VarType, ir.IntType):
@@ -363,9 +370,32 @@ class ExprHandle(BaseHandle):
return ir.Constant(ir.DoubleType(), val)
elif isinstance(val, str):
return Gen._create_string_global(val)
elif _is_cd_key:
print(f"[CD] lookup: '{VarName}' NOT in SymbolTable", file=_sys.stderr, flush=True)
except Exception as _e:
if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}")
# 治本修复:如果符号表也没有,回退查询 _all_define_constants
# _all_define_constants 由 Phase2Translator 从所有 .pyi 文件预提取,
# 包含跨模块导入的 CDefine 常量(如 FOREGROUND_GREEN、STD_OUTPUT_HANDLE
if VarName not in define_constants:
all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {}
if VarName in all_dc:
val: Any = all_dc[VarName]
if _is_cd_key:
print(f"[CD] lookup: '{VarName}' found in _all_define_constants val={val}", file=_sys.stderr, flush=True)
if isinstance(val, int):
if VarType is not None and isinstance(VarType, ir.IntType):
return ir.Constant(VarType, val & ((1 << VarType.width) - 1))
if val < -(1 << 31) or val > 0xFFFFFFFF:
return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF)
return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF)
elif isinstance(val, float):
return ir.Constant(ir.DoubleType(), val)
elif isinstance(val, str):
return Gen._create_string_global(val)
elif _is_cd_key:
print(f"[CD] lookup: '{VarName}' NOT found in ANY CDefine table", file=_sys.stderr, flush=True)
# 优先检查 variablesalloca因为变量可能已被 += 等操作迁移到 variables
if VarName in Gen.variables and Gen.variables[VarName] is not None:
VarPtr: Any = Gen.variables[VarName]
@@ -410,7 +440,18 @@ class ExprHandle(BaseHandle):
return GVar
return Gen._load(GVar, name=VarName)
if VarName == 'self':
return Gen.GetVarPtr('self')
# 治本修复:方法名为 _get_var_ptr小写原 GetVarPtr 不存在会抛 AttributeError。
# 当 self 未注册到 variables 时(如 opaque struct 参数走了 else 分支),
# 通过 _get_var_ptr 兜底返回 None由调用方处理。
SelfPtr: ir.Value | None = Gen._get_var_ptr('self')
if SelfPtr is not None:
return SelfPtr
# 最终兜底:若 _get_var_ptr 返回 Noneself 既不在 _reg_values 也不在 variables
# 直接返回函数参数本身LLVM Argument。这避免了 AttributeError 导致的异常路径。
for arg in getattr(Gen.func, 'args', []):
if getattr(arg, 'name', None) == 'self':
return arg
return ir.Constant(ir.IntType(32), 0)
if Gen._has_function(VarName):
func: Any = Gen._get_function(VarName)
if func:

View File

@@ -2045,6 +2045,21 @@ class ExprCallHandle(BaseHandle):
arg = Gen.builder.sext(arg, ir.IntType(64), name=f"sext_vararg_{FuncName}")
else:
arg = Gen.builder.zext(arg, ir.IntType(64), name=f"zext_vararg_{FuncName}")
elif isinstance(arg.type, (ir.LiteralStructType, ir.IdentifiedStructType)):
# 治本修复:变参函数(如 printf不支持 struct by value 传递。
# 当 self 等 struct 值被错误地 load 为值(而非指针)传入变参时,
# ABI 不匹配会导致崩溃。修复:将 struct 值通过 alloca + bitcast
# 转换为 i8* 指针传递,确保与 %p / %s 等格式说明符兼容。
try:
alloca_tmp = Gen.builder.alloca(arg.type, name=f"vararg_struct_{FuncName}_{i}")
Gen.builder.store(arg, alloca_tmp)
arg = Gen.builder.bitcast(alloca_tmp, ir.IntType(8).as_pointer(), name=f"vararg_struct_ptr_{FuncName}_{i}")
except Exception:
# 回退alloca/store 失败时,尝试 ptrtoint 为 i64
try:
arg = Gen.builder.ptrtoint(arg, ir.IntType(64), name=f"vararg_struct_i64_{FuncName}_{i}")
except Exception:
pass # 最终回退:保留原值(可能仍会导致崩溃,但至少不阻塞编译)
adjusted.append(arg)
result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}")
else:
@@ -2851,15 +2866,33 @@ class ExprCallHandle(BaseHandle):
if class_sha1 and ClassName in Gen.structs:
struct_type = Gen.structs[ClassName]
self_ptr_type = ir.PointerType(struct_type)
param_types = [self_ptr_type] + [a.type for a in CallArgs]
func_type = ir.FunctionType(ir.IntType(32), param_types)
# 修复 Bug 4: 从符号表获取完整参数列表(含默认参数)和正确返回类型,
# 而非仅使用 CallArgs漏掉默认参数和硬编码 i32 返回类型。
# 这避免了 main.py 中 declare Logger.info(...,i8*) 2参数
# 与 VLogger 中 define Logger.info(...,i8*,i8*) 3参数的签名冲突。
ret_type: Any = ir.IntType(32)
param_types: list[Any] = [self_ptr_type] + [a.type for a in CallArgs]
SymInfoFallback = self.LookupFunctionSymbol(MethodName, module_path=ClassName)
if SymInfoFallback and SymInfoFallback.IsFunction:
sig = self.BuildLLVMFuncTypeFromSig(SymInfoFallback, Gen)
if sig is not None:
sig_ret, sig_params, _ = sig
ret_type = sig_ret
is_static_fb = FuncMeta.STATIC_METHOD in SymInfoFallback.MetaList
if not is_static_fb:
sig_params = [self_ptr_type] + sig_params
param_types = sig_params
func_type = ir.FunctionType(ret_type, param_types)
func = ir.Function(Gen.module, func_type, name=FullMethodName)
Gen.functions[FullMethodName] = func
if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == struct_type:
call_self = ObjVal
else:
call_self = Gen.builder.bitcast(ObjVal, self_ptr_type, name=f"method_self_{ClassName}")
adjusted = Gen._adjust_args([call_self] + CallArgs, func)
call_args_fb = [call_self] + CallArgs
self._fill_default_args(call_args_fb, func, FullMethodName)
self._append_eh_msg_out_arg(call_args_fb, func, Gen)
adjusted = Gen._adjust_args(call_args_fb, func)
result = Gen.builder.call(func, adjusted, name=f"call_{FullMethodName}")
return result
raise Exception(f"Undefined method '{MethodName}' in class '{ClassName}' (no function declaration found for '{FullMethodName}')")

View File

@@ -112,20 +112,26 @@ class ImportHandle(BaseHandle):
# For 'from X import Y' (no asname), register CDefine constants
# into _define_constants so they can be found by _HandleNameLlvm
if not asname or asname == name:
define_constants = vars(Gen).setdefault('_define_constants', {})
# Check if this name is a CDefine constant in SymbolTable
sym_info = self.Trans.SymbolTable.lookup(name)
if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None:
define_constants = vars(Gen).setdefault('_define_constants', {})
if name not in define_constants:
define_constants[name] = sym_info.DefineValue
# Also check with module prefix
for prefix_key in [f"{module}.{name}", name]:
sym_info2 = self.Trans.SymbolTable.lookup(prefix_key)
if sym_info2 and sym_info2.IsDefine and sym_info2.DefineValue is not None:
define_constants = vars(Gen).setdefault('_define_constants', {})
if name not in define_constants:
define_constants[name] = sym_info2.DefineValue
break
# 治本修复:如果符号表中没有,回退查询 _all_define_constants
# _all_define_constants 由 Phase2Translator 从所有 .pyi 文件预提取,
# 包含跨模块导入的 CDefine 常量(如 FOREGROUND_GREEN、STD_OUTPUT_HANDLE
if name not in define_constants:
all_dc: dict = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {}
if name in all_dc:
define_constants[name] = all_dc[name]
continue
if not hasattr(self.Trans, '_t_c_imported_names'):
self.Trans._t_c_imported_names = {}

View File

@@ -211,6 +211,11 @@ class HandlesTypeMerge(BaseHandle):
elif TypeClass:
Info = CTypeInfo()
Info.BaseType = TypeClass
# 治本修复t.CDefine 注解必须设置 IsDefine=True
# 否则预扫描 (LlvmGenerator.py) 和主处理 (HandlesAnnAssign.py)
# 都无法识别 CDefine 常量,导致 FOREGROUND_GREEN 等解析为 0
if isinstance(TypeClass, type) and issubclass(TypeClass, t.CDefine):
Info.IsDefine = True
return Info
elif CTypeHelper.GetCName(TypeName):
return self._MakeCTypeInfoFromName(CTypeHelper.GetCName(TypeName))

View File

@@ -12,6 +12,8 @@ from lib.constants.config import mode as _config_mode
from lib.core.VLogger import get_logger as _vlog
from lib.core.DecoratorPass import run as _run_decorator_pass
from lib.core.SymbolUtils import IsTModule, AnnotationContainsName
# 治本修复:导入 ConstEvaluator 用于预扫描 CDefine 常量的复杂表达式求值
from lib.core.ConstEvaluator import ConstEvaluator
class LlvmGeneratorMixin:
@@ -59,26 +61,31 @@ class LlvmGeneratorMixin:
Gen.known_return_types[Node.name] = ir.PointerType(ir.IntType(8))
# 首先收集所有 CDefine 常量,确保类定义中可以引用
def _extract_call_const_val(node: ast.AST) -> int | str | float | None:
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute):
if getattr(node.func.value, 'id', None) == 't':
if node.args and isinstance(node.args[0], ast.Constant):
return node.args[0].value
elif isinstance(node.func, ast.Name):
if node.args and isinstance(node.args[0], ast.Constant):
return node.args[0].value
return None
def _extract_const_value(node: ast.AST) -> int | str | float | None:
"""求值 CDefine 常量表达式,支持 Constant、BinOp、UnaryOp、Name(引用其他 define)、Call(类型构造)。
治本修复:原 _extract_call_const_val 只支持 t.XxxType(Constant) 形式,
无法处理 FOREGROUND_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
等引用其他 CDefine 的 BinOp 表达式,导致依赖常量无法被预扫描。
现使用 ConstEvaluator.eval_with_symtab 统一求值。
"""
if isinstance(node, ast.Constant):
return node.value
# 使用 ConstEvaluator 处理 BinOp/UnaryOp/Name/Attribute/Call
return ConstEvaluator.eval_with_symtab(node, self.SymbolTable)
for Node in ast.iter_child_nodes(Tree):
if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value:
TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation)
if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)):
val: int | str | float | None = None
if isinstance(Node.value, ast.Constant):
val = Node.value.value
else:
val = _extract_call_const_val(Node.value)
# 治本修复:检查 BaseType 是否为 t.CDefine 实例/子类,或 IsDefine 标志
# IsDefine 由 GetCTypeInfo 对 t.CDefine 注解自动设置
if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine) or TypeInfo.IsDefine):
val: int | str | float | None = _extract_const_value(Node.value)
import sys as _sys
_nm = Node.target.id
# [CD] 仅输出关键常量FOREGROUND_*, STD_OUTPUT_HANDLE, BACKGROUND_*
if isinstance(_nm, str) and (_nm.startswith('FOREGROUND_') or _nm.startswith('BACKGROUND_') or 'STD_' in _nm or 'HANDLE' in _nm):
print(f"[CD] extract: '{_nm}' IsDefine={TypeInfo.IsDefine} val={val}", file=_sys.stderr, flush=True)
if val is not None:
if not hasattr(Gen, '_define_constants'):
Gen._define_constants: dict[str, int | str | float | bool] = {}
@@ -89,6 +96,8 @@ class LlvmGeneratorMixin:
sym_info.IsDefine = True
sym_info.DefineValue = val
self.SymbolTable.insert(Node.target.id, sym_info)
else:
print(f"[CD] extract: WARN val is None for '{_nm}'", file=_sys.stderr, flush=True)
elif isinstance(Node, ast.Assign):
for target in Node.targets:
if isinstance(target, ast.Name):
@@ -102,11 +111,7 @@ class LlvmGeneratorMixin:
raise
_vlog().warning(f"解析类型注释失败: {_e}", "Exception")
if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)):
val: int | str | float | None = None
if isinstance(Node.value, ast.Constant):
val = Node.value.value
else:
val = _extract_call_const_val(Node.value)
val: int | str | float | None = _extract_const_value(Node.value)
if val is not None:
if not hasattr(Gen, '_define_constants'):
Gen._define_constants: dict[str, int | str | float | bool] = {}

View File

@@ -711,19 +711,45 @@ class TypeAnnotationResolver:
if FullName in SymbolTable:
Info: CTypeInfo = SymbolTable[FullName]
if Info and Info.IsTypedef:
OriginalType: str = Info.get('OriginalType', '')
if OriginalType and 'typedef' in OriginalType:
parts: list[str] = OriginalType.split()
if len(parts) >= 2:
BaseType_name: str = parts[1]
if not BaseType_name.startswith('C'):
BaseType_name = 'C' + BaseType_name
CNAME: str | None = CTypeHelper.GetCName(BaseType_name)
if CNAME:
return TypeAnnotationResolver.from_type_name(CNAME)
# 优先用 BaseType 解析(如 VOIDPTR 已解析为 BaseType=CVoid, PtrCount=1
if Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0):
Result = Info.Copy()
Result.IsTypedef = True
Result.Name = FullName
return Result
# 再用 OriginalType 解析(字符串如 'void *',或 CTypeInfo
if Info.OriginalType:
if isinstance(Info.OriginalType, CTypeInfo) and Info.OriginalType.IsFuncPtr:
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = Info.OriginalType.FuncPtrReturn or CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = list(Info.OriginalType.FuncPtrParams) if Info.OriginalType.FuncPtrParams else []
Result.IsTypedef = True
Result.Name = FullName
return Result
elif isinstance(Info.OriginalType, CTypeInfo):
Resolved: CTypeInfo = Info.OriginalType.Copy()
elif isinstance(Info.OriginalType, str) and Info.OriginalType == 'Callable':
Result = CTypeInfo()
Result.IsFuncPtr = True
Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo()
Result.FuncPtrParams = []
Result.IsTypedef = True
Result.Name = FullName
return Result
elif isinstance(Info.OriginalType, str):
Resolved = TypeAnnotationResolver.from_type_name(Info.OriginalType)
else:
Resolved = Info.OriginalType
if Resolved and Resolved.BaseType:
Resolved.IsTypedef = True
Resolved.Name = FullName
return Resolved
# 回退:保持原逻辑但设置 Name = FullName供后续 TypeConvert 查找)
Result: CTypeInfo = CTypeInfo()
Result.BaseType = t._CTypedef(TypeName)
Result.IsTypedef = True
Result.Name = FullName
return Result
if Info:
Result: CTypeInfo = Info.Copy()