Some simple information syncing
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -16,7 +16,7 @@ import w32.win32base
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemManager | t.CPtr
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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 表示失败
|
||||
|
||||
@@ -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 合并到 stdout(si.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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
# ============================================================
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
# 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc
|
||||
double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
return llvmlite.ConstFloat(pool, double_ty, cn.float_val)
|
||||
elif cn.const_kind == ast.CONST_CHAR:
|
||||
# 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8
|
||||
cv: t.CInt64T = cn.int_val
|
||||
return llvmlite.const_int32(pool, cv)
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
sv: str = cn.str_val
|
||||
if sv is None:
|
||||
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 可能是 i8(X|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 可能是 i8,ensure 无效)
|
||||
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)
|
||||
|
||||
@@ -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(整数):既可安全截断为 i32(trunc),也可转换为指针(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_entry(find_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__ 字段(偏移 8,i64)
|
||||
# __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct
|
||||
# 注意: 必须用 translate_value 而非 translate_name_value,因为 len_at.value
|
||||
# 可能是 Attribute 节点(如 md_ags.args),translate_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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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=2(import扫描模式)时跳过,只处理 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 分派
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
# 当前模块 SHA1(Phase1 在模块开始翻译前设置,供报错使用)
|
||||
# ============================================================
|
||||
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 跨模块 typedef(win32base.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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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__ 中调用)"}
|
||||
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
{"InitLib": "初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。\n\n Args:\n mb: memhub.MemManager 实例指针(MemBuddy 等子类通过多态传入)\n\n Returns:\n 0 表示成功,非 0 表示失败\n "}
|
||||
@@ -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
@@ -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.
@@ -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
|
||||
|
||||
@@ -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__())
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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_CHAR,int_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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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=损坏
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_INTENSITY(ast.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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)。
|
||||
|
||||
在无 ctx(EvalContext)的场景下,通过 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
|
||||
|
||||
@@ -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)
|
||||
# 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 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 返回 None(self 既不在 _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:
|
||||
|
||||
@@ -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}')")
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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] = {}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user