chore: 纳入 toast 脚本、Sequential 回归测试与诊断产物文件
_toast_gen.py(完成通知 toast 脚本)、Test/SequentialRegressionTest.py (TPV bootstrap 回归测试脚本)、handles_expr_HEAD.vp 与 output.s (历史诊断/反汇编产物)入库保存。
This commit is contained in:
1 parent
2f0b741d55
commit
921820b26a
4 files changed
+2349
No files matched your search
@@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python3
|
||||
"""TransPyC 顺序回归测试脚本
|
||||
|
||||
与 regression_test.py 的区别:
|
||||
1. 按 Test/TestsOverview.md「建议实现顺序」节(难度升序,68 个项目)逐个编译
|
||||
2. 每个项目编译成功后立即运行其可执行文件
|
||||
3. 编译或运行失败立刻结束(fail-fast),退出码非 0
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
# 强制 stdout/stderr 使用 UTF-8 编码,避免 Windows GBK 编码在打印含替换字符的输出时崩溃
|
||||
try:
|
||||
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
||||
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ============================================================
|
||||
# 路径
|
||||
# ============================================================
|
||||
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
# 项目根目录(Projectrans.py 所在位置)
|
||||
PROJECT_ROOT = os.path.dirname(TEST_DIR)
|
||||
# Projectrans.py 路径
|
||||
PROJECTRANS = os.path.join(PROJECT_ROOT, "Projectrans.py")
|
||||
# TestsOverview.md 路径(顺序来源)
|
||||
OVERVIEW = os.path.join(TEST_DIR, "TestsOverview.md")
|
||||
|
||||
# 编译超时(秒)
|
||||
COMPILE_TIMEOUT = 300
|
||||
# 运行超时(秒)
|
||||
RUN_TIMEOUT = 30
|
||||
|
||||
|
||||
def read_test_order():
|
||||
"""从 TestsOverview.md「建议实现顺序」节提取项目名(难度升序)"""
|
||||
with open(OVERVIEW, encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
m = re.search(r'##\s*二、\s*建议实现顺序(.*?)##\s*三、', text, re.S)
|
||||
if not m:
|
||||
raise SystemExit("TestsOverview.md 中找不到「建议实现顺序」节")
|
||||
section = m.group(1)
|
||||
order = []
|
||||
for line in section.splitlines():
|
||||
mm = re.match(r'\s*\d+\.\s*\*\*(.+?)\*\*', line)
|
||||
if mm:
|
||||
order.append(mm.group(1))
|
||||
if not order:
|
||||
raise SystemExit("「建议实现顺序」节中未解析到任何项目名")
|
||||
return order
|
||||
|
||||
|
||||
def build_compile_cmd(args):
|
||||
"""根据 --exe/--compiler 构建编译命令模板({project} 为项目 json 路径占位)
|
||||
|
||||
--exe 指定编译器可执行文件(如 TransPyV.exe),优先于 --compiler;
|
||||
两者都未指定时使用 TPC(python Projectrans.py)。
|
||||
--rebuild-includes 时追加 --rebuild-includes(全量重编 includes,
|
||||
修复 includes.binary 缓存不一致导致的 undefined symbol)。
|
||||
"""
|
||||
suffix = " --rebuild-includes" if args.rebuild_includes else ""
|
||||
if args.exe:
|
||||
return f'"{args.exe}" --project {{project}} --clean{suffix}'
|
||||
if args.compiler:
|
||||
return args.compiler
|
||||
return f'D:\\Python312\\python.exe -u "{PROJECTRANS}" --project {{project}} --clean{suffix}'
|
||||
|
||||
|
||||
def compile_project(cmd, proj_dir):
|
||||
"""编译单个测试项目,返回 (success, elapsed, combined_output)"""
|
||||
start = time.time()
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
shell=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding='utf-8',
|
||||
errors='replace',
|
||||
cwd=proj_dir,
|
||||
timeout=COMPILE_TIMEOUT,
|
||||
)
|
||||
elapsed = time.time() - start
|
||||
|
||||
combined = (result.stdout or "") + (result.stderr or "")
|
||||
return (result.returncode == 0, elapsed, combined)
|
||||
|
||||
|
||||
def find_executables(output_dir):
|
||||
"""在 output 目录中查找可执行文件"""
|
||||
exes = []
|
||||
if not os.path.isdir(output_dir):
|
||||
return exes
|
||||
for f in os.listdir(output_dir):
|
||||
fpath = os.path.join(output_dir, f)
|
||||
if os.path.isfile(fpath) and (f.endswith('.exe') or f.endswith('.bin')):
|
||||
exes.append(fpath)
|
||||
return exes
|
||||
|
||||
|
||||
def find_output_dirs(proj_dir, proj_config):
|
||||
"""收集候选输出目录(兼容 TPC 与 TPV 布局)
|
||||
|
||||
- project.json 显式 output_dir(TPC 常用)
|
||||
- project.json build_dir + '/output'(TPV 布局:.tpv_build/output)
|
||||
- 兜底 ./output
|
||||
保序去重返回。
|
||||
"""
|
||||
dirs = []
|
||||
od = proj_config.get('output_dir')
|
||||
if od:
|
||||
dirs.append(os.path.abspath(os.path.join(proj_dir, od)))
|
||||
bd = proj_config.get('build_dir')
|
||||
if bd:
|
||||
dirs.append(os.path.abspath(os.path.join(proj_dir, bd, 'output')))
|
||||
if not dirs:
|
||||
dirs.append(os.path.abspath(os.path.join(proj_dir, './output')))
|
||||
seen = set()
|
||||
uniq = []
|
||||
for d in dirs:
|
||||
if d not in seen:
|
||||
seen.add(d)
|
||||
uniq.append(d)
|
||||
return uniq
|
||||
|
||||
|
||||
def run_executable(exe_path):
|
||||
"""运行单个可执行文件,返回 (returncode, stdout, stderr, timed_out)
|
||||
|
||||
超时 RUN_TIMEOUT 秒强制结束。
|
||||
使用 CREATE_NO_WINDOW 避免弹出 cmd 窗口,通过管道捕获 stdout/stderr。
|
||||
"""
|
||||
try:
|
||||
CREATE_NO_WINDOW = 0x08000000
|
||||
result = subprocess.run(
|
||||
[exe_path],
|
||||
cwd=os.path.dirname(exe_path),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding='utf-8',
|
||||
errors='replace',
|
||||
timeout=RUN_TIMEOUT,
|
||||
creationflags=CREATE_NO_WINDOW,
|
||||
)
|
||||
return (result.returncode, result.stdout or "", result.stderr or "", False)
|
||||
except subprocess.TimeoutExpired:
|
||||
return (-1, "", "超时(强制终止)", True)
|
||||
except Exception as e:
|
||||
return (-1, "", str(e), False)
|
||||
|
||||
|
||||
def print_tail(output, max_lines=40):
|
||||
"""打印输出尾部(编译/运行失败时的诊断信息)"""
|
||||
lines = output.strip().splitlines()
|
||||
if len(lines) > max_lines:
|
||||
print(f" ... (省略前 {len(lines) - max_lines} 行) ...")
|
||||
lines = lines[-max_lines:]
|
||||
for line in lines:
|
||||
print(f" {line}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="TransPyC 顺序回归测试(按 TestsOverview.md 顺序,失败即停)")
|
||||
parser.add_argument("--exe", default=None,
|
||||
help="编译器可执行文件(如 TransPyV.exe),用它编译测试项目(替代 TPC)")
|
||||
parser.add_argument("--compiler", default=None,
|
||||
help="自定义编译命令模板,用 {project} 表示项目 json 路径;默认 TPC python")
|
||||
parser.add_argument("--rebuild-includes", action="store_true",
|
||||
help="每次编译追加 --rebuild-includes:清空 includes.binary 全量重编(修复缓存不一致)")
|
||||
parser.add_argument("--number", type=int, default=1,
|
||||
help="从第几个案例开始(1 开始编号),编译该编号及之后的项目;默认 1")
|
||||
args = parser.parse_args()
|
||||
compile_cmd = build_compile_cmd(args)
|
||||
|
||||
print("=" * 70)
|
||||
print("TransPyC 顺序回归测试(按 TestsOverview.md 顺序,失败即停)")
|
||||
print("=" * 70)
|
||||
print()
|
||||
|
||||
order = read_test_order()
|
||||
total = len(order)
|
||||
|
||||
start = max(1, args.number)
|
||||
if start > total:
|
||||
print(f"错误: --number {args.number} 超出总项目数 {total}")
|
||||
return 1
|
||||
print(f"按顺序共 {total} 个项目,从第 {start} 个({order[start - 1]})开始")
|
||||
print(f"编译命令: {compile_cmd}\n")
|
||||
|
||||
passed = 0
|
||||
for idx, name in enumerate(order, 1):
|
||||
if idx < start:
|
||||
continue
|
||||
proj_dir = os.path.join(TEST_DIR, name)
|
||||
proj_json = os.path.join(proj_dir, "project.json")
|
||||
|
||||
if not os.path.isfile(proj_json):
|
||||
print(f"[{idx}/{total}] {name}: 缺少 project.json,跳过")
|
||||
continue
|
||||
|
||||
# ---------- 编译 ----------
|
||||
print(f"[{idx}/{total}] 编译 {name} ...", end=" ", flush=True)
|
||||
cmd = compile_cmd.format(project=proj_json)
|
||||
try:
|
||||
compile_ok, elapsed, output = compile_project(cmd, proj_dir)
|
||||
except subprocess.TimeoutExpired:
|
||||
print("编译超时(5 分钟)")
|
||||
print_tail("编译超时(5 分钟)")
|
||||
print(f"\n在 {name} 编译超时,立即终止。")
|
||||
return 1
|
||||
except Exception as e:
|
||||
print(f"异常: {e}")
|
||||
print_tail(str(e))
|
||||
print(f"\n在 {name} 编译异常,立即终止。")
|
||||
return 1
|
||||
|
||||
if not compile_ok:
|
||||
print(f"失败 ({elapsed:.1f}s)")
|
||||
print_tail(output)
|
||||
print(f"\n在 {name} 编译失败,立即终止。")
|
||||
return 1
|
||||
print(f"通过 ({elapsed:.1f}s)")
|
||||
|
||||
# ---------- 编译成功后立即运行 ----------
|
||||
try:
|
||||
with open(proj_json, 'r', encoding='utf-8') as f:
|
||||
proj_config = json.load(f)
|
||||
except Exception:
|
||||
proj_config = {}
|
||||
|
||||
output_dirs = find_output_dirs(proj_dir, proj_config)
|
||||
exes = []
|
||||
for od in output_dirs:
|
||||
exes = find_executables(od)
|
||||
if exes:
|
||||
break
|
||||
|
||||
if not exes:
|
||||
print(f" [运行] 未找到可执行文件(候选: {'; '.join(output_dirs)}),视为运行失败")
|
||||
return 1
|
||||
|
||||
run_ok = True
|
||||
for exe_path in exes:
|
||||
exe_name = os.path.basename(exe_path)
|
||||
print(f" [运行] {exe_name} ...", end=" ", flush=True)
|
||||
returncode, stdout, stderr, timed_out = run_executable(exe_path)
|
||||
|
||||
if timed_out:
|
||||
print("超时")
|
||||
print_tail(stdout + stderr)
|
||||
run_ok = False
|
||||
elif returncode == 0:
|
||||
print("通过")
|
||||
else:
|
||||
print(f"失败(退出码 {returncode})")
|
||||
print_tail(stdout + stderr)
|
||||
run_ok = False
|
||||
|
||||
if not run_ok:
|
||||
break
|
||||
|
||||
if not run_ok:
|
||||
print(f"\n在 {name} 运行失败,立即终止。")
|
||||
return 1
|
||||
|
||||
passed += 1
|
||||
|
||||
print()
|
||||
print("=" * 70)
|
||||
print(f"全部 {passed} 个项目编译并运行通过!")
|
||||
print("=" * 70)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""生成并发送 toast 通知"""
|
||||
import base64, subprocess
|
||||
|
||||
ps = (
|
||||
"Add-Type -AssemblyName System.Runtime.WindowsRuntime\n"
|
||||
"[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null\n"
|
||||
"[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null\n"
|
||||
"$t = 'TransPyC 治本修复:联合转换属性访问'\n"
|
||||
"$b = 'TPC _handle_attr_call_result 现从 (X|t.CPtr)(arg) 提取真实类并 bitcast,修复属性访问被丢弃;已提交 6a67203(TPV 侧 9f7333b 双保险)'\n"
|
||||
"$xml = [Windows.Data.Xml.Dom.XmlDocument]::new()\n"
|
||||
"$xml.LoadXml('<toast><visual><binding template=\"ToastText02\"><text id=\"1\">' + $t + '</text><text id=\"2\">' + $b + '</text></binding></visual></toast>')\n"
|
||||
"$toast = [Windows.UI.Notifications.ToastNotification]::new($xml)\n"
|
||||
"[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('TraeCode').Show($toast)\n"
|
||||
)
|
||||
b64 = base64.b64encode(ps.encode('utf-16-le')).decode()
|
||||
r = subprocess.run(['powershell', '-NoProfile', '-EncodedCommand', b64],
|
||||
capture_output=True, text=True)
|
||||
print('rc=', r.returncode)
|
||||
@@ -0,0 +1,767 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import llvmlite
|
||||
import stdlib
|
||||
import stdio
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesEnum as HandlesEnum
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesExpr - 表达式处理(P3 对象化后的委托层)
|
||||
#
|
||||
# 全部模块级函数已迁移为 lib.core.Gen.ExprGenMixin 的方法
|
||||
# (全局状态迁入 gen 字段),本模块保留同名模块级函数作为
|
||||
# "一行委托":延迟 import Gen 取全局单例(BuildPipeline/main
|
||||
# 创建后 set_global_gen 注册),再调用 gen 的对应方法。签名与
|
||||
# 旧函数完全一致,调用方零改动。
|
||||
#
|
||||
# ExprHandle 类及其 NewExprHandle 工厂保留(translator handler 模式)。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 gen 单例(模块级镜像,同 HandlesType/HandlesStruct 模式)
|
||||
#
|
||||
# 由 BuildPipeline/main 在 gen 创建后调用 set_global_gen 注入。
|
||||
# P3 委托函数用本地 _g_gen(cast 成 Generator 类型)调
|
||||
# ExprGenMixin 方法,避免函数体 import 包模块与类/模块名歧义。
|
||||
# ============================================================
|
||||
_g_gen: t.CVoid | t.CPtr = None
|
||||
|
||||
|
||||
def set_global_gen(gen: t.CVoid | t.CPtr) -> None:
|
||||
"""注入全局 gen 单例(BuildPipeline/main 调用)"""
|
||||
global _g_gen
|
||||
_g_gen = gen
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 委托函数:延迟 import Gen 取全局单例 → 调 gen 方法
|
||||
# (gen 未注册时正常流程不会发生;有返回值函数返回默认值)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 从 AST 节点提取函数名
|
||||
# ============================================================
|
||||
def get_func_name(func_node: ast.AST | t.CPtr) -> str:
|
||||
"""从函数节点提取函数名(委托到 gen.get_func_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_func_name(func_node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 转义 LLVM IR 字符串字面量
|
||||
# ============================================================
|
||||
def escape_llvm_string(pool: memhub.MemBuddy | t.CPtr,
|
||||
src: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
|
||||
"""将字符串转换为 LLVM IR 字符串字面量 c"...\\00"(委托到 gen.escape_llvm_string)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.escape_llvm_string(pool, src)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取 LLVM 整数类型的位宽
|
||||
# ============================================================
|
||||
def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""获取 LLVM 整数类型的位宽,非整数类型返回 0(委托到 gen.get_llvm_type_bits)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_llvm_type_bits(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取 LLVM 浮点类型的位宽
|
||||
# ============================================================
|
||||
def get_llvm_float_bits(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""获取 LLVM 浮点类型的位宽,非浮点类型返回 0(委托到 gen.get_llvm_float_bits)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_llvm_float_bits(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_ptr_type - 检查类型是否为 Ptr
|
||||
#
|
||||
# 返回 1=是, 0=否。作为类型检查工具函数被广泛使用(50+ 处调用)。
|
||||
# ============================================================
|
||||
def is_ptr_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""检查 ty 是否是 Ptr 类型,返回 1=是, 0=否(委托到 gen.is_ptr_type)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_ptr_type(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_ptr_level - 计算指针层级
|
||||
#
|
||||
# 返回值:
|
||||
# 0 = 非指针(数值/结构体等)
|
||||
# 1 = 一级指针(如 i8*, Struct*)
|
||||
# 2 = 二级指针(如 i8**, Struct**)
|
||||
# 3+ = 更高级指针
|
||||
# ============================================================
|
||||
def get_ptr_level(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""计算指针层级,0=非指针, 1=一级指针, 2=二级指针...(委托到 gen.get_ptr_level)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_ptr_level(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_array_type - 检查类型是否为 Array
|
||||
#
|
||||
# 返回 1=是, 0=否。类型检查工具函数。
|
||||
# ============================================================
|
||||
def is_array_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""检查 ty 是否是 Array 类型,返回 1=是, 0=否(委托到 gen.is_array_type)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_array_type(ty)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _zext_index_to_i32 - 数组下标索引零扩展
|
||||
#
|
||||
# LLVM GEP 对窄整数索引默认符号扩展:i8 0xE2(226) 会被当成 -30,
|
||||
# 导致数组下标越界读(字节 >= 128 的乱码根因)。
|
||||
# 数组下标语义为非负,<32 位整数索引一律 zext 到 i32。
|
||||
# ============================================================
|
||||
def _zext_index_to_i32(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
idx_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""将 <32 位整数下标零扩展到 i32(数组下标非负语义)(委托到 gen._zext_index_to_i32)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._zext_index_to_i32(builder, idx_val)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_custom_struct_cls_nm - 检查类型是否为已注册的自定义结构体
|
||||
#
|
||||
# 处理两种情况:
|
||||
# - ty 直接是 Struct → 检查是否注册
|
||||
# - ty 是 Ptr(Struct) → 检查 pointee 是否注册
|
||||
# ============================================================
|
||||
def _get_custom_struct_cls_nm(pool: memhub.MemBuddy | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> str:
|
||||
"""检查 ty 或 ty 的 pointee 是否是已注册的自定义结构体,返回类名或 None(委托到 gen._get_custom_struct_cls_nm)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_custom_struct_cls_nm(pool, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_list_subscript_base - 判断下标基座是否为 list[T] 变量
|
||||
# ============================================================
|
||||
def _is_list_subscript_base(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
sub_node: ast.AST | t.CPtr) -> int:
|
||||
"""判断下标基座是否为 list[T] 变量(1=是)(委托到 gen._is_list_subscript_base)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_list_subscript_base(pool, trans, sub_node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _sub_base_class_name - 解析下标基座变量的结构体类名
|
||||
# ============================================================
|
||||
def _sub_base_class_name(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
sub_node: ast.AST | t.CPtr) -> str:
|
||||
"""解析下标基座变量的结构体类名(无则 None)(委托到 gen._sub_base_class_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._sub_base_class_name(pool, trans, sub_node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _sub_base_uses_getitem - 下标基座是否应走 __getitem__ 语义
|
||||
# ============================================================
|
||||
def _sub_base_uses_getitem(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
sub_node: ast.AST | t.CPtr) -> int:
|
||||
"""下标基座应走 __getitem__ 语义时返回 1,否则 0(应走 GEP 地址语义)(委托到 gen._sub_base_uses_getitem)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._sub_base_uses_getitem(pool, mod, trans, sub_node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _deref_if_ptr_ptr - 如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用
|
||||
# ============================================================
|
||||
def _deref_if_ptr_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
obj_ptr: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用获取内层指针(委托到 gen._deref_if_ptr_ptr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._deref_if_ptr_ptr(builder, obj_ptr)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 类型强制转换:整数 sext/trunc,浮点 fpext/fptrunc,int↔float si2fp/fp2si
|
||||
# ============================================================
|
||||
def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
val: llvmlite.Value | t.CPtr,
|
||||
target_ty: llvmlite.LLVMType | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""将 val 强制转换为 target_ty(委托到 gen.coerce_to_type)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.coerce_to_type(builder, val, target_ty, node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_ptr_arith - 指针算术: ptr + int / ptr - int
|
||||
#
|
||||
# 用 getelementptr(按 pointee 元素大小缩放索引),对齐 TPC
|
||||
# ExprGen.emit_binary_op / HandlesAugAssign.py。
|
||||
# ============================================================
|
||||
def translate_ptr_arith(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ptr_val: llvmlite.Value | t.CPtr,
|
||||
int_val: llvmlite.Value | t.CPtr,
|
||||
op: int) -> llvmlite.Value | t.CPtr:
|
||||
"""指针算术: ptr + int / ptr - int → GEP(按元素大小缩放索引)(委托到 gen.translate_ptr_arith)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_ptr_arith(pool, builder, ptr_val, int_val, op)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 创建全局字符串常量
|
||||
# ============================================================
|
||||
def create_global_string(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
str_val: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""创建全局字符串常量并返回 i8* bitcast(委托到 gen.create_global_string)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.create_global_string(builder, pool, mod, str_val, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译常量表达式
|
||||
# ============================================================
|
||||
def translate_constant(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译常量(int/str/bool)(委托到 gen.translate_constant)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_constant(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名
|
||||
# ============================================================
|
||||
def _infer_elem_type_from_value(pool: memhub.MemBuddy | t.CPtr,
|
||||
value: llvmlite.Value | t.CPtr) -> str:
|
||||
"""从 LLVM Value 的类型推断 list 元素类型名(委托到 gen._infer_elem_type_from_value)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._infer_elem_type_from_value(pool, value)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _find_pool_var — 查找上下文中的 pool 变量
|
||||
#
|
||||
# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb"
|
||||
# ============================================================
|
||||
def _find_pool_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找上下文中的 pool 变量,返回 alloca 或 None(委托到 gen._find_pool_var)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._find_pool_var(trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_list_literal — 翻译 list 字面量 [a, b, c]
|
||||
#
|
||||
# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列
|
||||
# ============================================================
|
||||
def translate_list_literal(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
elem_type_name: str,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列(委托到 gen.translate_list_literal)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_list_literal(builder, pool, mod, node, elem_type_name, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译值表达式(RHS 分派)— 模块级版本
|
||||
# ============================================================
|
||||
def translate_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr = None,
|
||||
func_count: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译值表达式为 LLVM Value(委托到 gen.translate_value)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_value(builder, pool, mod, node, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译三元表达式 IfExp(test, body, orelse)
|
||||
# ============================================================
|
||||
def translate_ifexp(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译三元表达式 (body if test else orelse),返回 phi 结果 Value(委托到 gen.translate_ifexp)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_ifexp(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译比较表达式 Compare(left, ops, comparators)
|
||||
# ============================================================
|
||||
def should_zext_widen(pool: memhub.MemBuddy | t.CPtr,
|
||||
narrow_val: llvmlite.Value | t.CPtr,
|
||||
wide_val: llvmlite.Value | t.CPtr,
|
||||
narrow_node: ast.AST | t.CPtr = None) -> int:
|
||||
"""判断整数拓宽方向:1=zext(无符号语义),0=sext(委托到 gen.should_zext_widen)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.should_zext_widen(pool, narrow_val, wide_val, narrow_node)
|
||||
return 0
|
||||
|
||||
|
||||
def _node_type_unsigned(pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> int:
|
||||
"""轻量判断 AST 节点是否解析为无符号整数类型(1=是,0=否/未知)(委托到 gen._node_type_unsigned)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._node_type_unsigned(pool, node, trans)
|
||||
return 0
|
||||
|
||||
|
||||
def _type_name_unsigned(type_name: str) -> int:
|
||||
"""类型名是否为无符号整数类型(精确匹配,避免子串误伤如 nUIntCount)(委托到 gen._type_name_unsigned)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._type_name_unsigned(type_name)
|
||||
return 0
|
||||
|
||||
|
||||
def translate_compare(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译比较表达式,返回 i1 结果(委托到 gen.translate_compare)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_compare(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译一元运算表达式 UnaryOp(op, operand)
|
||||
# ============================================================
|
||||
def translate_unaryop(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译一元运算(-x, +x, not x, ~x)(委托到 gen.translate_unaryop)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_unaryop(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译布尔运算 BoolOp(op, values) — 短路求值,返回 i1
|
||||
# ============================================================
|
||||
def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
funcs_ptr: t.CPtr = None,
|
||||
func_count: int = 0,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译布尔运算(and/or)的短路求值,返回 i1(委托到 gen.translate_boolop)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_boolop(builder, pool, mod, node, funcs_ptr, func_count, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_source_path_from_sha1 - 通过 SHA1 从存储器构建源 .vp/.py 文件路径
|
||||
# ============================================================
|
||||
def _build_source_path_from_sha1(sha1: str) -> str:
|
||||
"""通过 SHA1 从全局存储器构建源 .py 文件路径(委托到 gen._build_source_path_from_sha1)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._build_source_path_from_sha1(sha1)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _lookup_cross_module_cdefine - 跨模块查找 CDefine 常量
|
||||
# ============================================================
|
||||
def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
from_imports: str,
|
||||
imported_modules: str = None) -> int:
|
||||
"""跨模块查找 CDefine 常量,返回值或 -1(未找到)(委托到 gen._lookup_cross_module_cdefine)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._lookup_cross_module_cdefine(pool, name, from_imports, imported_modules)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定
|
||||
# ============================================================
|
||||
def _is_cdefine_name_pattern(name: str) -> int:
|
||||
"""检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)(委托到 gen._is_cdefine_name_pattern)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_cdefine_name_pattern(name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译变量引用(Name 节点)→ load
|
||||
# ============================================================
|
||||
def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译变量引用(Name 节点)→ load(委托到 gen.translate_name_value)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_name_value(builder, pool, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ExprHandle - 表达式处理器(Mixin 继承模式)
|
||||
#
|
||||
# HandleValue 提供 trans 接口,委托到模块级 translate_value
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ExprHandle(HandlesBase.Mixin):
|
||||
"""表达式处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# HandleValue - 翻译值表达式为 LLVM Value
|
||||
# ============================================================
|
||||
def HandleValue(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译值表达式,从 self.Trans 获取共享状态"""
|
||||
return translate_value(
|
||||
self.Trans._cur_builder, self.Trans.Pool, self.Trans.Module,
|
||||
node,
|
||||
self.Trans._funcs, self.Trans._func_count, self.Trans)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewExprHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewExprHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ExprHandle | t.CPtr:
|
||||
h: ExprHandle | t.CPtr = pool.alloc(ExprHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ExprHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
|
||||
|
||||
# ============================================================
|
||||
# list_getitem_inline — 内联生成 list[T] __getitem__ 逻辑
|
||||
#
|
||||
# list 结构布局 (6 字段 × 8 字节):
|
||||
# __data__(0) __count__(8) __capacity__(16) __pool__(24) __elem_size__(32) __iter_index__(40)
|
||||
# 返回元素地址 (i8*),调用方根据元素类型 load 正确的值
|
||||
# ============================================================
|
||||
def list_getitem_inline(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
lm_obj: llvmlite.Value | t.CPtr,
|
||||
idx_val: llvmlite.Value | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""内联生成 list __getitem__ 逻辑,返回元素地址 (i8*)(委托到 gen.list_getitem_inline)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.list_getitem_inline(builder, pool, lm_obj, idx_val, node)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _list_elem_type_from_name — 从 list 类型名提取元素 LLVM 类型
|
||||
# ============================================================
|
||||
def _list_elem_type_from_name(pool: memhub.MemBuddy | t.CPtr,
|
||||
struct_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""从 list 类型名提取元素 LLVM 类型(委托到 gen._list_elem_type_from_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._list_elem_type_from_name(pool, struct_name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# list_setitem_inline — 内联生成 list[T] __setitem__ 逻辑
|
||||
# ============================================================
|
||||
def list_setitem_inline(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
lm_obj: llvmlite.Value | t.CPtr,
|
||||
idx_val: llvmlite.Value | t.CPtr,
|
||||
rhs_val: llvmlite.Value | t.CPtr,
|
||||
node: ast.AST | t.CPtr = None) -> int:
|
||||
"""内联生成 list __setitem__ 逻辑,返回 0(委托到 gen.list_setitem_inline)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.list_setitem_inline(builder, pool, lm_obj, idx_val, rhs_val, node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_list_subscript — 检查 Subscript 节点是否是 list[T] 类型
|
||||
#
|
||||
# 返回 list 对象指针 (Ptr(list[T])) 或 None
|
||||
# ============================================================
|
||||
def is_list_subscript(node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""检查 Subscript 节点是否是 list[T] 类型,返回 list 对象指针或 None(委托到 gen.is_list_subscript)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.is_list_subscript(node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译下标表达式 Subscript(value, slice, ctx) — ptr[i] / arr[i]
|
||||
# ============================================================
|
||||
def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译下标表达式,返回加载的元素值(委托到 gen.translate_subscript)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_subscript(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_global_in_module - 在模块全局变量链表中按名称查找
|
||||
#
|
||||
# 查找策略:
|
||||
# 1. 精确匹配 (如 "_mbuddy" 匹配 @_mbuddy)
|
||||
# 2. 后缀匹配 (如 "_mbuddy" 匹配 @"sha1._mbuddy")
|
||||
# ============================================================
|
||||
def find_global_in_module(mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str) -> llvmlite.GlobalVariable | t.CPtr:
|
||||
"""在模块全局变量链表中按名称查找全局变量(委托到 gen.find_global_in_module)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.find_global_in_module(mod, name)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# make_global_ref - 创建全局变量引用 (@name,类型为 ty*)
|
||||
# ============================================================
|
||||
def make_global_ref(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""创建全局变量引用 (类型为 ty*,名称为 @name)(委托到 gen.make_global_ref)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.make_global_ref(pool, name, ty)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_t_type_object_name - 检查 name 是否是 t.py 中的类型对象名
|
||||
# ============================================================
|
||||
def _is_t_type_object_name(name: str) -> int:
|
||||
"""检查 name 是否是 t.py 中的类型对象名(CPtr/CInt/CDouble 等)(委托到 gen._is_t_type_object_name)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._is_t_type_object_name(name)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _resolve_module_attribute_global - 解析模块属性访问的全局变量引用
|
||||
# ============================================================
|
||||
def _resolve_module_attribute_global(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
at: ast.Attribute | t.CPtr,
|
||||
ty_hint: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""解析模块属性访问,返回全局变量引用 (用于跨模块 global 访问)(委托到 gen._resolve_module_attribute_global)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._resolve_module_attribute_global(pool, mod, trans, at, ty_hint)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_cderef_attr_base - c.Deref(ptr).attr 属性访问的 base 指针
|
||||
# ============================================================
|
||||
def _get_cderef_attr_base(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
at_value: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""检测 at.value 是否为 c.Deref(ptr) 调用,返回 ptr 指针(不做 load)(委托到 gen._get_cderef_attr_base)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g._get_cderef_attr_base(builder, pool, mod, at_value, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译属性访问 Attribute(value, attr, ctx) — obj.field
|
||||
# ============================================================
|
||||
def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译属性访问,返回加载的字段值(委托到 gen.translate_attribute)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.translate_attribute(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取下标表达式的元素指针(不加载值,用于赋值)
|
||||
# ============================================================
|
||||
def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""获取下标表达式的元素指针(用于赋值 lhs)(委托到 gen.get_subscript_ptr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_subscript_ptr(builder, pool, mod, node, trans)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取属性访问的字段指针(不加载值,用于赋值)
|
||||
# ============================================================
|
||||
def get_attribute_ptr(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""获取属性访问的字段指针(用于赋值 lhs)(委托到 gen.get_attribute_ptr)"""
|
||||
import lib.core.Gen.Generator as Generator
|
||||
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
|
||||
if g is not None:
|
||||
return g.get_attribute_ptr(builder, pool, mod, node, trans)
|
||||
return None
|
||||
Reference in new issue
Block a user