Files
ViperC/App/lib/core/Handles/ExprCallCtor.vp
T
TermiNexus 2cb974ae5a refactor(handles): HandlesExprCall 拆 6 组(Base/Deref/Ctor/Call/Table/Handle,2041→241 行)
直接移动+改调用方:~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 验证通过
2026-08-17 08:10:55 +08:00

623 lines
35 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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