直接移动+改调用方:~100 个委托函数按功能移至 6 个子模块,主文件 保留 _g_gen/set_global_gen/顶层常量/4 个类(AsmOperand、FuncEntry、 FuncDefaultsEntry、ExprCallHandle——CallGenLeafKit/HandlesTranslator 仍以 HandlesExprCall.类名 引用)。 - 子模块函数体内 _g_gen/常量/类裸引用 → HandlesExprCall.xxx 跨模块访问 - 28 个调用方 HandlesExprCall.func( → 子模块前缀并补 import - 全 App 语法/引用/import 验证通过
623 lines
35 KiB
Plaintext
623 lines
35 KiB
Plaintext
import t, c
|
||
from stdint import *
|
||
import ast
|
||
import llvmlite
|
||
import memhub
|
||
import string
|
||
import stdio
|
||
import stdlib
|
||
import sys
|
||
import viperlib
|
||
import w32.fileio as fileio
|
||
import lib.core.VLogger as VLogger
|
||
import lib.core.Handles.HandlesBase as HandlesBase
|
||
import lib.core.Handles.HandlesTranslator as HT
|
||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||
import lib.core.Handles.HandlesVar as HandlesVar
|
||
import lib.core.Handles.HandlesType as HandlesType
|
||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||
import lib.core.Handles.HandlesImports as HandlesImports
|
||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||
import lib.core.StubMerger as StubMerger
|
||
|
||
|
||
import lib.core.Handles.ExprCallBase as ExprCallBase
|
||
import lib.core.Handles.ExprCallDeref as ExprCallDeref
|
||
import lib.core.Handles.ExprCallCall as ExprCallCall
|
||
import lib.core.Handles.ExprCallTable as ExprCallTable
|
||
import lib.core.Handles.ExprCallHandle as ExprCallHandle
|
||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||
|
||
# ============================================================
|
||
# ExprCallCtor - HandlesExprCall 拆分(阶段 E):ExprCallCtor
|
||
#
|
||
# 直接移动模式:委托函数迁至此模块,原 HandlesExprCall.vp 仅
|
||
# 保留 _g_gen/常量/类;调用方经本模块前缀访问。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# _apply_struct_defaults — 应用结构体字段的默认值
|
||
#
|
||
# 在 zeroinitializer 之后、显式参数之前调用
|
||
# 遍历所有字段,对有默认值的字段翻译并 store
|
||
# 显式参数(位置/关键字)后续会覆盖默认值
|
||
# ============================================================
|
||
def _apply_struct_defaults(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str,
|
||
tmp: llvmlite.Value | t.CPtr,
|
||
trans: HT.Translator | t.CPtr):
|
||
"""应用结构体字段的默认值(委托到 gen._apply_struct_defaults)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
g._apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans)
|
||
# ============================================================
|
||
# _translate_struct_ctor — 结构体构造函数 Point(10, 20)
|
||
#
|
||
# 生成:
|
||
# %tmp = alloca {i32, i32}
|
||
# store {i32, i32} zeroinitializer, {i32, i32}* %tmp
|
||
# %f0 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 0
|
||
# store i32 10, i32* %f0
|
||
# %f1 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 1
|
||
# store i32 20, i32* %f1
|
||
# %result = load {i32, i32}, {i32, i32}* %tmp
|
||
# ============================================================
|
||
def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str,
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||
can: t.CSizeT,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""结构体构造函数:按字段顺序 store 参数值,返回结构体值(委托到 gen._translate_struct_ctor)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_struct_ctor(pool, builder, mod, struct_ty, class_name, cargs, can, trans)
|
||
return None
|
||
# ============================================================
|
||
# _translate_renum_construct — REnum 变体构造函数
|
||
#
|
||
# 语法: ClassName.VariantName(args...)
|
||
# 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体,__tag=0,_p1=1
|
||
#
|
||
# 生成 IR:
|
||
# %tmp = alloca {i32, i32, ...} ; REnum 类型
|
||
# store zeroinitializer, %tmp ; 清零
|
||
# %tag_ptr = gep %tmp, 0, 0 ; __tag 字段
|
||
# store i32 <tag_value>, %tag_ptr ; 写入 tag
|
||
# %p1_ptr = gep %tmp, 0, 1 ; _p1 字段
|
||
# store <coerced_arg0>, %p1_ptr ; 写入 payload[0]
|
||
# ... (更多 payload 字段)
|
||
# return %tmp ; 返回指针
|
||
#
|
||
# 对应 TPC 的 _HandleREnumConstructLlvm
|
||
# ============================================================
|
||
def _translate_renum_construct(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
variant_name: str,
|
||
tag_value: int,
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||
can: t.CSizeT,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""构造 REnum 变体实例,返回指向 alloca 的指针(委托到 gen._translate_renum_construct)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_renum_construct(pool, builder, mod, class_name, variant_name,
|
||
tag_value, cargs, can, trans)
|
||
return None
|
||
# ============================================================
|
||
# _do_virtual_call — 通过虚表间接调用虚方法
|
||
#
|
||
# IR 模式:
|
||
# %1 = getelementptr StructTy, StructTy* %self, i32 0, i32 0 ; i8**
|
||
# %2 = load i8*, i8** %1 ; i8* (vtable ptr)
|
||
# %3 = bitcast i8* %2 to {i8*, ...}* ; vtable typed ptr
|
||
# %4 = getelementptr {i8*, ...}, {i8*, ...}* %3, i32 0, i32 N ; i8**
|
||
# %5 = load i8*, i8** %4 ; i8* (func ptr)
|
||
# %6 = bitcast i8* %5 to RetTy(Params)* ; func typed ptr
|
||
# call RetTy %6(Params %self, ...)
|
||
#
|
||
# 参数:
|
||
# args_head — 已构建好的参数链表头(self_ptr 为首节点)
|
||
# args_count — 参数总数(含 self)
|
||
# found_func — 方法对应的 Function 对象(用于推断函数签名)
|
||
# ret_ty — 返回类型
|
||
# ============================================================
|
||
def _do_virtual_call(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
method_name: str,
|
||
self_ptr: llvmlite.Value | t.CPtr,
|
||
args_head: llvmlite.Value | t.CPtr,
|
||
args_count: int,
|
||
found_func: llvmlite.Function | t.CPtr,
|
||
ret_ty: llvmlite.LLVMType | t.CPtr,
|
||
vtable_base: llvmlite.Value | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||
"""通过虚表间接调用虚方法,返回 call 结果(void 方法返回 None)(委托到 gen._do_virtual_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._do_virtual_call(pool, builder, mod, class_name, method_name,
|
||
self_ptr, args_head, args_count, found_func, ret_ty, vtable_base)
|
||
return None
|
||
# ============================================================
|
||
# _call_method_on_ptr — 在结构体指针上调用方法
|
||
#
|
||
# 辅助函数:构造 ClassName.method_name 调用,self 指针为首个参数
|
||
# 如果该方法在虚表中,则走虚方法分发路径(间接调用)
|
||
# ============================================================
|
||
def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
method_name: str,
|
||
self_ptr: llvmlite.Value | t.CPtr,
|
||
extra_args: t.CSizeT | t.CPtr,
|
||
extra_count: int,
|
||
trans: HT.Translator | t.CPtr,
|
||
node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||
"""在结构体指针上调用方法,返回 call 结果(void 方法返回 None)(委托到 gen._call_method_on_ptr)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._call_method_on_ptr(pool, builder, mod, class_name, method_name,
|
||
self_ptr, extra_args, extra_count, trans, node)
|
||
return None
|
||
# ============================================================
|
||
# _ensure_method_declare - 为跨模块方法调用创建 declare 声明
|
||
#
|
||
# 当 found_func 为 None(stub 未注入或跨模块调用)时,
|
||
# 在当前模块中创建函数声明,避免 llc 报 undefined value。
|
||
# ============================================================
|
||
def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
call_name: str,
|
||
ret_ty: llvmlite.LLVMType | t.CPtr,
|
||
param_head: llvmlite.ParamNode | t.CPtr,
|
||
param_count: int):
|
||
"""为跨模块方法调用创建 declare 声明(委托到 gen._ensure_method_declare)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
g._ensure_method_declare(pool, mod, call_name, ret_ty, param_head, param_count)
|
||
# ============================================================
|
||
# _lookup_method_ret_ty_via_vpi - 从 vpi stub 返回注解缓存精确获取方法返回类型
|
||
#
|
||
# 方法定义处(.vpi stub)的返回注解(如 json.JsonValue._pool_alloc →
|
||
# "str")在 stub 注入时由 VpiReader 缓存(_cache_vpi_return_annots_text)。
|
||
# 此函数按 模块SHA1 + 类名 + 方法名 查缓存并纯字符串解析为 LLVMType。
|
||
# 无需硬编码白名单——返回类型始终来自方法定义处。
|
||
# ============================================================
|
||
def _lookup_method_ret_ty_via_vpi(pool: memhub.MemBuddy | t.CPtr,
|
||
cls_sha1: str,
|
||
cls_name: str,
|
||
method_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||
"""从 vpi stub 返回注解缓存获取方法返回类型,未命中返回 None(委托到 gen._lookup_method_ret_ty_via_vpi)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._lookup_method_ret_ty_via_vpi(pool, cls_sha1, cls_name, method_name)
|
||
return None
|
||
# ============================================================
|
||
# _special_method_ret_ty - 编译器内置特殊方法的固定返回类型
|
||
#
|
||
# __before_init__ / __init__:编译器生成/约定返回 void
|
||
# __new__:返回 Ptr(StructTy)(存储空间指针)
|
||
#
|
||
# 这些方法不存在于源码(vpi stub 无条目),跨模块调用时
|
||
# found_func/text.ll/vpi 缓存必然未命中,但返回类型是编译器
|
||
# 确定性语义(与 HandlesClassDef._translate_method 3543-3548 一致),
|
||
# 在此直接固定,不触发 fail-fast 误报。非特殊方法返回 None。
|
||
# ============================================================
|
||
def _special_method_ret_ty(pool: memhub.MemBuddy | t.CPtr,
|
||
class_name: str,
|
||
method_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||
"""编译器内置特殊方法的固定返回类型;非特殊返回 None(委托到 gen._special_method_ret_ty)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._special_method_ret_ty(pool, class_name, method_name)
|
||
return None
|
||
# ============================================================
|
||
# _fail_method_ret_ty - 方法返回类型无法精确获取时 fail-fast
|
||
#
|
||
# 返回类型来源(按序):当前模块函数 → text.ll define → vpi stub 返回注解缓存。
|
||
# 全部未命中时立即 ERROR + 错误堆栈终止,绝不按名推断白名单/静默默认 i32。
|
||
#
|
||
# node: 调用点 AST 节点(可选,用于 ERROR 堆栈定位)
|
||
# ============================================================
|
||
def _fail_method_ret_ty(method_name: str,
|
||
node: ast.AST | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr:
|
||
"""方法返回类型无法精确获取时 fail-fast(ERROR + 错误堆栈)(委托到 gen._fail_method_ret_ty)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._fail_method_ret_ty(method_name, node)
|
||
return None
|
||
# ============================================================
|
||
# 跨模块方法返回类型查找(从 text.ll)
|
||
#
|
||
# Phase A 翻译每个源文件后生成 text.ll,其中 define 行包含
|
||
# 方法的实际返回类型。当 Phase A 翻译后续文件调用跨模块方法时,
|
||
# 方法调用默认返回 i32,导致指针返回值被截断。
|
||
# _LookupMethodRetTyFromTextLL 读取依赖模块的 text.ll,从 define
|
||
# 行提取实际返回类型,避免指针截断(未命中时回退 vpi stub 缓存)。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# SetTempDir - 设置 temp 目录路径
|
||
#
|
||
# 在 Phase2.py 的 Phase A 翻译前调用,使 CallGenMixin
|
||
# 能够读取依赖模块的 text.ll 文件。
|
||
# ============================================================
|
||
def SetTempDir(temp_dir: str):
|
||
"""设置 temp 目录路径(供跨模块方法返回类型查找使用)(委托到 gen.SetTempDir)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
g.SetTempDir(temp_dir)
|
||
# ============================================================
|
||
# _ParseLLVMRetTyStr - 将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType
|
||
#
|
||
# 从 define 行中提取的返回类型字符串(define 与 @ 之间的内容),
|
||
# 转换为 llvmlite.LLVMType 对象。
|
||
#
|
||
# 支持的类型:
|
||
# void → Void
|
||
# i8/i16/i32/i64 → Int8/Int16/Int32/Int64
|
||
# double → Double, float → Float
|
||
# 任何含 * 的类型 → Ptr(Int8)(通用指针,保留 64 位地址)
|
||
#
|
||
# Args:
|
||
# pool: 内存池
|
||
# buf: 包含类型字符串的缓冲区
|
||
# start: 类型字符串起始位置
|
||
# end: 类型字符串结束位置(不含)
|
||
#
|
||
# Returns:
|
||
# LLVM 类型对象,或 None(无法解析)
|
||
# ============================================================
|
||
def _ParseLLVMRetTyStr(pool: memhub.MemBuddy | t.CPtr,
|
||
buf: bytes,
|
||
start: t.CSizeT,
|
||
end: t.CSizeT) -> llvmlite.LLVMType | t.CPtr:
|
||
"""将 LLVM IR 返回类型字符串转换为 llvmlite.LLVMType(委托到 gen._ParseLLVMRetTyStr)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._ParseLLVMRetTyStr(pool, buf, start, end)
|
||
return None
|
||
# ============================================================
|
||
# _LookupMethodRetTyFromTextLL - 从依赖模块的 text.ll 查找方法返回类型
|
||
#
|
||
# 读取 {temp_dir}/{sha1[0:2]}/{sha1}.text.ll(level=1),搜索
|
||
# define 行中包含 "{sha1}.{class_name}.{method_name}" 的函数,
|
||
# 提取返回类型并转换为 llvmlite.LLVMType。
|
||
#
|
||
# 解决问题: 旧实现 _infer_method_ret_ty(已移除)默认返回 i32,导致指针返回值
|
||
# 被 inttoptr 截断为 32 位(coerce_to_type line 238-239)。
|
||
# 本函数从 text.ll 获取实际返回类型,避免截断。
|
||
#
|
||
# Args:
|
||
# pool: 内存池
|
||
# class_sha1: 类所属模块的 SHA1
|
||
# class_name: 类名
|
||
# method_name: 方法名
|
||
#
|
||
# Returns:
|
||
# LLVM 类型对象,或 None(未找到/text.ll 不存在)
|
||
# ============================================================
|
||
def _LookupMethodRetTyFromTextLL(pool: memhub.MemBuddy | t.CPtr,
|
||
class_sha1: str,
|
||
class_name: str,
|
||
method_name: str,
|
||
use_bare: int = 0) -> llvmlite.LLVMType | t.CPtr:
|
||
"""从依赖模块的 text.ll 中查找方法返回类型(委托到 gen._LookupMethodRetTyFromTextLL)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._LookupMethodRetTyFromTextLL(pool, class_sha1, class_name, method_name, use_bare)
|
||
return None
|
||
# ============================================================
|
||
# 属性方法(@property/@x.setter/@x.deleter)与静态/类方法调用辅助
|
||
#
|
||
# 元数据表由 HandlesClassDef 在类翻译/预注册阶段填充,
|
||
# 这里负责把 obj.prop / obj.prop=v / del obj.prop / Class.method()
|
||
# 翻译为对应的 {sha1}.ClassName.prop 系列函数调用。
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# _translate_property_call — 翻译属性方法调用
|
||
#
|
||
# 与 _translate_method_call 的调用名/返回类型解析逻辑一致:
|
||
# 1. 优先用模块中已有的函数(精确/后缀匹配,来自 stub 注入)
|
||
# 2. 否则用类所属模块的 SHA1 构造 "{sha1}.ClassName.method" 调用名
|
||
# 3. 返回类型:函数实类型 → text.ll 查找 → 按方法名推断(默认 i32)
|
||
#
|
||
# call_head/call_count: 已构建好的参数链表(如 getter 只有 obj 一个参数)
|
||
# ============================================================
|
||
def _translate_property_call(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
method_name: str,
|
||
call_head: llvmlite.Value | t.CPtr,
|
||
call_count: int,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""翻译属性/静态方法调用,返回 call 结果 Value(委托到 gen._translate_property_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_property_call(pool, builder, mod, class_name, method_name,
|
||
call_head, call_count, trans)
|
||
return None
|
||
# ============================================================
|
||
# _resolve_obj_class_name — 解析对象表达式的类名(短名)
|
||
#
|
||
# 优先从变量注解(AnnotClassName)解析(如 "memhub.MemBuddy" → "MemBuddy"),
|
||
# 失败时从 LLVM 类型解析(Ptr(Struct) → 类名)。
|
||
# 供属性访问/赋值/删除识别 property 时使用。
|
||
# ============================================================
|
||
def _resolve_obj_class_name(pool: memhub.MemBuddy | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
obj_node: ast.AST | t.CPtr) -> str:
|
||
"""解析对象表达式的类名(短名),失败返回 None(委托到 gen._resolve_obj_class_name)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._resolve_obj_class_name(pool, trans, obj_node)
|
||
return None
|
||
# ============================================================
|
||
# _try_property_getter_attr — 尝试将 obj.attr 翻译为 property getter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @property/@x.getter 的 attr 方法;
|
||
# 若有则生成 call Class.attr(obj) 并返回调用结果 Value;否则返回 None。
|
||
# ============================================================
|
||
def _try_property_getter_attr(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
at_node: ast.Attribute | t.CPtr,
|
||
obj_ptr: llvmlite.Value | t.CPtr,
|
||
trans: HT.Translator | t.CPtr,
|
||
fallback_class_name: str = None) -> llvmlite.Value | t.CPtr:
|
||
"""尝试 property getter 属性访问,返回调用结果 Value;非 getter 返回 None(委托到 gen._try_property_getter_attr)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._try_property_getter_attr(pool, builder, mod, at_node, obj_ptr,
|
||
trans, fallback_class_name)
|
||
return None
|
||
# ============================================================
|
||
# _try_property_setter — 尝试将 obj.attr = v 翻译为 property setter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @x.setter 的 attr 方法;
|
||
# 若有则生成 call Class.attr$set(obj, v),返回 1;否则返回 0。
|
||
# ============================================================
|
||
def _try_property_setter(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
target_attr: ast.Attribute | t.CPtr,
|
||
rhs_val: llvmlite.Value | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> int:
|
||
"""尝试 property setter 赋值,返回 1=已处理(生成调用)(委托到 gen._try_property_setter)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._try_property_setter(pool, builder, mod, target_attr, rhs_val, trans)
|
||
return 0
|
||
# ============================================================
|
||
# _try_property_deleter — 尝试将 del obj.attr 翻译为 property deleter 调用
|
||
#
|
||
# 检查 obj 的类是否有 @x.deleter 的 attr 方法;
|
||
# 若有则生成 call Class.attr$del(obj),返回 1;否则返回 0。
|
||
# ============================================================
|
||
def _try_property_deleter(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
target_attr: ast.Attribute | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> int:
|
||
"""尝试 property deleter 删除,返回 1=已处理(生成调用)(委托到 gen._try_property_deleter)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._try_property_deleter(pool, builder, mod, target_attr, trans)
|
||
return 0
|
||
# ============================================================
|
||
# _translate_static_class_call — 翻译 ClassName.method(args) 静态/类方法调用
|
||
#
|
||
# @staticmethod: 直接 call Class.method(args...),无 self
|
||
# @classmethod: 在参数前插入栈上分配的类实例指针(与 TPC 一致)
|
||
# ============================================================
|
||
def _translate_static_class_call(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
method_name: str,
|
||
cl: ast.Call | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""翻译类名静态/类方法调用,返回 call 结果 Value;非静态/类方法返回 None(委托到 gen._translate_static_class_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_static_class_call(pool, builder, mod, class_name, method_name, cl, trans)
|
||
return None
|
||
# ============================================================
|
||
# _translate_method_call - 翻译方法调用 obj.method(args)
|
||
#
|
||
# 生成: call <ret_ty> @SHA1.ClassName.method_name(Ptr(StructTy) %obj, args...)
|
||
#
|
||
# obj_ptr 是对象变量的 alloca(Ptr(StructTy)),作为 self 参数传入
|
||
# ============================================================
|
||
def _translate_method_call(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
class_name: str,
|
||
method_name: str,
|
||
obj_ptr: llvmlite.Value | t.CPtr,
|
||
cl: ast.Call | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""翻译方法调用,返回 call 结果 Value(委托到 gen._translate_method_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_method_call(pool, builder, mod, class_name, method_name,
|
||
obj_ptr, cl, trans)
|
||
return None
|
||
# ============================================================
|
||
# _kwarg_name_matches — 检查关键字参数名是否匹配函数参数名
|
||
#
|
||
# 函数参数名在 LLVM IR 中带 % 前缀(如 "%a"),关键字参数名无前缀(如 "a")
|
||
# 跳过 % 前缀后逐字符比较
|
||
# ============================================================
|
||
def _kwarg_name_matches(kw_arg: str,
|
||
param_name: str) -> int:
|
||
"""检查关键字参数名 kw_arg 是否匹配参数名 param_name(跳过 % 前缀)(委托到 gen._kwarg_name_matches)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._kwarg_name_matches(kw_arg, param_name)
|
||
return 0
|
||
# ============================================================
|
||
# _translate_struct_ctor_kw — 结构体构造函数(关键字参数)
|
||
#
|
||
# 支持两种语法:
|
||
# Point(x=10, y=20) — 全关键字
|
||
# Point(10, y=20) — 混合(位置 + 关键字)
|
||
#
|
||
# 位置参数按字段索引赋值,关键字参数按字段名查找赋值
|
||
# ============================================================
|
||
def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
struct_ty: llvmlite.LLVMType | t.CPtr,
|
||
class_name: str,
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||
can: t.CSizeT,
|
||
keywords: list[ast.AST | t.CPtr] | t.CPtr,
|
||
kw_count: t.CSizeT,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""结构体构造函数(关键字参数版本)(委托到 gen._translate_struct_ctor_kw)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_struct_ctor_kw(pool, builder, mod, struct_ty, class_name,
|
||
cargs, can, keywords, kw_count, trans)
|
||
return None
|
||
# ============================================================
|
||
# _translate_call_with_kwargs — 带关键字参数的函数调用
|
||
#
|
||
# 支持两种语法:
|
||
# add(b=4, a=3) — 全关键字乱序
|
||
# greet("Hello", name="World") — 位置 + 关键字混合
|
||
#
|
||
# 策略: 遍历 found_func.Params 链表,对每个参数:
|
||
# 1. 若位置参数仍有剩余(param_idx < can),取位置参数
|
||
# 2. 否则按参数名匹配关键字参数
|
||
# 3. 按参数顺序构建调用参数链表
|
||
# ============================================================
|
||
def _translate_call_with_kwargs(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
func_name: str,
|
||
found_func: llvmlite.Function | t.CPtr,
|
||
cargs: list[ast.AST | t.CPtr] | t.CPtr,
|
||
can: t.CSizeT,
|
||
keywords: list[ast.AST | t.CPtr] | t.CPtr,
|
||
kw_count: t.CSizeT,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""带关键字参数的函数调用,按参数顺序构建调用链表(委托到 gen._translate_call_with_kwargs)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_call_with_kwargs(pool, builder, mod, func_name, found_func,
|
||
cargs, can, keywords, kw_count, trans)
|
||
return None
|
||
# ============================================================
|
||
# _translate_t_type_cast - 翻译 t.XXX(value) 类型转换
|
||
#
|
||
# 当 func 是 t.XXX 形式且 XXX 是已知类型名(map_t_type 能映射)时,
|
||
# 将 value 转换为目标类型:
|
||
# - 指针 → 整数: ptrtoint(如 t.CUInt64T(ptr) → i64)
|
||
# - 整数 → 指针: inttoptr(如 t.CPtr(int_val) → i8*)
|
||
# - 整数 → 整数: trunc/zext(如 t.CInt8T(i32_val) → i8)
|
||
# - 指针 → 指针: bitcast(如 t.CPtr(ptr_val) → i8*)
|
||
# - 整数 → 浮点: sitofp(如 t.CDouble(i32_val) → double)
|
||
# - 浮点 → 整数: fptosi(如 t.CInt(double_val) → i32)
|
||
# - 浮点 → 浮点: fpext/fptrunc(如 t.CFloat(double_val) → float)
|
||
# ============================================================
|
||
def _translate_t_type_cast(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
val: llvmlite.Value | t.CPtr,
|
||
target_ty: llvmlite.LLVMType | t.CPtr,
|
||
target_name: str = None,
|
||
src_node: ast.AST | t.CPtr = None,
|
||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||
"""类型转换:根据参数类型和目标类型选择转换方式(委托到 gen._translate_t_type_cast)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_t_type_cast(pool, builder, val, target_ty,
|
||
target_name, src_node, trans)
|
||
return None
|
||
# ============================================================
|
||
# 泛型实例化辅助:从 Subscript slice 提取类型实参名
|
||
# ============================================================
|
||
# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute)
|
||
# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用
|
||
|
||
def _extract_type_args_from_slice(pool: memhub.MemBuddy | t.CPtr,
|
||
slice_node: ast.AST | t.CPtr) -> list[str] | t.CPtr:
|
||
"""从 Subscript.slice 提取类型实参名列表(委托到 gen._extract_type_args_from_slice)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._extract_type_args_from_slice(pool, slice_node)
|
||
return None
|
||
# ============================================================
|
||
# 泛型类构造调用辅助: list[str](pool, 8) → __new__ + __before_init__ + __init__
|
||
#
|
||
# 复用 translate_list_literal 的构造逻辑:
|
||
# 1. alloca tmp(特化类临时空间,作为 __new__ 的 self)
|
||
# 2. 翻译 cl.args 为参数指针数组
|
||
# 3. call __new__(tmp, *args) → storage_ptr
|
||
# 4. call __before_init__(storage_ptr)
|
||
# 5. call __init__(storage_ptr, *args)
|
||
# 6. return storage_ptr
|
||
#
|
||
# 必须独立于 translate_call 的普通函数路径:spec_name 是类名不是函数名,
|
||
# 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1
|
||
# 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。
|
||
# ============================================================
|
||
def _infer_generic_ctor_type_arg(pool: memhub.MemBuddy | t.CPtr,
|
||
arg_node: ast.AST | t.CPtr,
|
||
class_name: str) -> str:
|
||
"""从构造实参 AST 推断泛型类型实参名;无法推断时默认 "int"(与 TPC 一致)(委托到 gen._infer_generic_ctor_type_arg)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._infer_generic_ctor_type_arg(pool, arg_node, class_name)
|
||
return "int"
|
||
def _translate_generic_ctor_call(pool: memhub.MemBuddy | t.CPtr,
|
||
builder: llvmlite.IRBuilder | t.CPtr,
|
||
mod: llvmlite.LLVMModule | t.CPtr,
|
||
spec_name: str,
|
||
cl: ast.Call | t.CPtr,
|
||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||
"""泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__(委托到 gen._translate_generic_ctor_call)"""
|
||
import lib.core.Gen.Generator as Generator
|
||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(HandlesExprCall._g_gen, t.CPtr))
|
||
if g is not None:
|
||
return g._translate_generic_ctor_call(pool, builder, mod, spec_name, cl, trans)
|
||
return None
|