将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名
This commit is contained in:
1 parent
f79c8ca643
commit
cfc30d735c
322 files changed
+246
-31772
No files matched your search
@@ -1,397 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
from json.__parser import parse as json_parse
|
||||
from json import JsonValue, JSON_OBJECT, JSON_INT
|
||||
import w32.fileio as fileio
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Config - 工程配置
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemManager | t.CPtr
|
||||
|
||||
# 配置值(从 project.vpj 加载)
|
||||
SourceDir: str
|
||||
BuildDir: str
|
||||
TempDir: str # = {BuildDir}/temp(自动计算)
|
||||
OutputDir: str # = {BuildDir}/output(自动计算)
|
||||
ProjectName: str
|
||||
ProjectVersion: str
|
||||
CompilerCmd: str
|
||||
CompilerFlags: str # 编译器参数(空格分隔,从 compiler.flags 数组拼接)
|
||||
LinkerCmd: str
|
||||
LinkerFlags: str # 链接器参数(空格分隔,从 linker.flags 数组拼接)
|
||||
LinkerOutput: str
|
||||
TargetTriple: str
|
||||
TargetDataLayout: str
|
||||
Sha1SliceLevel: t.CInt # SHA1 切片层数(目录分散等级)
|
||||
StrictMode: t.CInt
|
||||
IncludesDir: str # includes 目录路径(从 includes 数组首元素)
|
||||
|
||||
|
||||
def Load_project_config(path: str) -> int:
|
||||
"""加载工程配置文件(project.vpj)
|
||||
|
||||
Args:
|
||||
path: 配置文件路径
|
||||
|
||||
Returns:
|
||||
0 表示成功,非 0 表示失败
|
||||
"""
|
||||
global SourceDir, BuildDir, TempDir, OutputDir, ProjectName, ProjectVersion
|
||||
global CompilerCmd, CompilerFlags, LinkerCmd, LinkerFlags, LinkerOutput
|
||||
global TargetTriple, TargetDataLayout, Sha1SliceLevel, StrictMode
|
||||
global IncludesDir
|
||||
|
||||
if path is None:
|
||||
return 1
|
||||
if _mbuddy is None:
|
||||
return 1
|
||||
|
||||
# 打开文件
|
||||
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R)
|
||||
if f is None:
|
||||
return 1
|
||||
if f.closed:
|
||||
return 1
|
||||
|
||||
# 分配读取缓冲区
|
||||
CFG_BUF_SIZE: t.CSizeT = 8192
|
||||
buf: bytes = _mbuddy.alloc(CFG_BUF_SIZE)
|
||||
if buf is None:
|
||||
f.close()
|
||||
return 1
|
||||
|
||||
bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE)
|
||||
f.close()
|
||||
|
||||
if bytes_read <= 0:
|
||||
return 1
|
||||
|
||||
# 解析 JSON
|
||||
root: JsonValue | t.CPtr = json_parse(_mbuddy, buf)
|
||||
if root is None:
|
||||
return 1
|
||||
if not root.is_object():
|
||||
return 1
|
||||
|
||||
# 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制)
|
||||
sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir")
|
||||
SourceDir = sd_val.as_string() if sd_val is not None else None
|
||||
# build_dir: 统一构建目录(默认 ./.tpv_build),temp 和 output 作为其子目录
|
||||
bd_val: JsonValue | t.CPtr = root.__getitem__("build_dir")
|
||||
if bd_val is not None and bd_val.is_string():
|
||||
BuildDir = bd_val.as_string()
|
||||
else:
|
||||
BuildDir = "./.tpv_build"
|
||||
name_val: JsonValue | t.CPtr = root.__getitem__("name")
|
||||
ProjectName = name_val.as_string() if name_val is not None else None
|
||||
ver_val: JsonValue | t.CPtr = root.__getitem__("version")
|
||||
ProjectVersion = ver_val.as_string() if ver_val is not None else None
|
||||
|
||||
# 读取 compiler 子对象
|
||||
compiler: JsonValue | t.CPtr = root.__getitem__("compiler")
|
||||
if compiler is not None and compiler.is_object():
|
||||
cc_cmd_val: JsonValue | t.CPtr = compiler.__getitem__("cmd")
|
||||
CompilerCmd = cc_cmd_val.as_string() if cc_cmd_val is not None else None
|
||||
# 读取 compiler.flags 数组,拼接成空格分隔的字符串
|
||||
cc_flags_val: JsonValue | t.CPtr = compiler.__getitem__("flags")
|
||||
CompilerFlags = _join_flags_array(cc_flags_val)
|
||||
|
||||
# 读取 linker 子对象
|
||||
linker: JsonValue | t.CPtr = root.__getitem__("linker")
|
||||
if linker is not None and linker.is_object():
|
||||
ld_cmd_val: JsonValue | t.CPtr = linker.__getitem__("cmd")
|
||||
LinkerCmd = ld_cmd_val.as_string() if ld_cmd_val is not None else None
|
||||
ld_out_val: JsonValue | t.CPtr = linker.__getitem__("output")
|
||||
LinkerOutput = ld_out_val.as_string() if ld_out_val is not None else None
|
||||
# 读取 linker.flags 数组,拼接成空格分隔的字符串
|
||||
ld_flags_val: JsonValue | t.CPtr = linker.__getitem__("flags")
|
||||
LinkerFlags = _join_flags_array(ld_flags_val)
|
||||
|
||||
# 读取 target 子对象
|
||||
target: JsonValue | t.CPtr = root.__getitem__("target")
|
||||
if target is not None and target.is_object():
|
||||
tgt_triple_val: JsonValue | t.CPtr = target.__getitem__("triple")
|
||||
TargetTriple = tgt_triple_val.as_string() if tgt_triple_val is not None else None
|
||||
tgt_dl_val: JsonValue | t.CPtr = target.__getitem__("datalayout")
|
||||
TargetDataLayout = tgt_dl_val.as_string() if tgt_dl_val is not None else None
|
||||
|
||||
# 读取 options 子对象
|
||||
# Sha1SliceLevel: SHA1 切片层数(默认 1,每层取 SHA1 前 2 字符作为子目录)
|
||||
# level=0 → 不切片,文件直接放 base_dir
|
||||
# level=1 → b7/{sha1}.ext
|
||||
# level=2 → b7/90/{sha1}.ext
|
||||
options: JsonValue | t.CPtr = root.__getitem__("options")
|
||||
Sha1SliceLevel = 1
|
||||
StrictMode = 1
|
||||
if options is not None and options.is_object():
|
||||
sl: JsonValue | t.CPtr = options.__getitem__("sha1_slice_level")
|
||||
if sl is not None and sl.is_int():
|
||||
Sha1SliceLevel = sl.as_int()
|
||||
sm: JsonValue | t.CPtr = options.__getitem__("strict_mode")
|
||||
if sm is not None and sm.is_bool():
|
||||
StrictMode = 1 if sm.as_bool() else 0
|
||||
|
||||
# 读取 includes 数组(取首个元素作为 includes 目录)
|
||||
includes_val: JsonValue | t.CPtr = root.__getitem__("includes")
|
||||
if includes_val is not None and includes_val.is_array():
|
||||
arr_len: t.CSizeT = includes_val.__len__()
|
||||
if arr_len > 0:
|
||||
first_inc: JsonValue | t.CPtr = includes_val.get_item(0)
|
||||
if first_inc is not None and first_inc.is_string():
|
||||
IncludesDir = first_inc.as_string()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str:
|
||||
"""将 JSON 字符串数组拼接成空格分隔的字符串
|
||||
|
||||
用于 linker.flags 和 compiler.flags 数组。
|
||||
用 while + 索引遍历,避免 list 迭代器 bug。
|
||||
|
||||
Args:
|
||||
flags_val: JsonValue,应为字符串数组
|
||||
|
||||
Returns:
|
||||
空格分隔的字符串,或 None 如果 flags_val 为 None 或非数组或空数组
|
||||
"""
|
||||
if flags_val is None:
|
||||
return None
|
||||
if not flags_val.is_array():
|
||||
return None
|
||||
|
||||
arr_len: t.CSizeT = flags_val.__len__()
|
||||
if arr_len == 0:
|
||||
return None
|
||||
|
||||
# 第一遍:计算总长度(所有 flag 长度 + 空格分隔符)
|
||||
total_len: t.CSizeT = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < arr_len:
|
||||
item: JsonValue | t.CPtr = flags_val.get_item(i)
|
||||
if item is not None and item.is_string():
|
||||
s: str = item.as_string()
|
||||
if s is not None:
|
||||
total_len += string.strlen(s) + 1 # +1 for space
|
||||
i += 1
|
||||
|
||||
if total_len == 0:
|
||||
return None
|
||||
|
||||
# 分配缓冲区(total_len 已含每个 flag 后的空格,最后一个是 '\0')
|
||||
buf: str = _mbuddy.alloc(total_len + 1)
|
||||
if buf is None:
|
||||
return None
|
||||
|
||||
# 第二遍:拼接(flag 之间用空格分隔)
|
||||
pos: t.CSizeT = 0
|
||||
i = 0
|
||||
while i < arr_len:
|
||||
item = flags_val.get_item(i)
|
||||
if item is not None and item.is_string():
|
||||
s = item.as_string()
|
||||
if s is not None:
|
||||
slen: t.CSizeT = string.strlen(s)
|
||||
if pos > 0:
|
||||
buf[pos] = ' '
|
||||
pos += 1
|
||||
string.strcpy(buf + pos, s)
|
||||
pos += slen
|
||||
i += 1
|
||||
buf[pos] = '\0'
|
||||
return buf
|
||||
|
||||
|
||||
def _join_path(rel: str, project_dir: str) -> str:
|
||||
"""将相对路径与 project_dir 拼接为绝对路径
|
||||
|
||||
- ./App + Test → Test/App
|
||||
- ./temp + Test → Test/temp
|
||||
- ../includes + Test → Test/../includes(OS 解析为 includes)
|
||||
- 绝对路径保持不变
|
||||
- None 返回 None
|
||||
"""
|
||||
if rel is None:
|
||||
return None
|
||||
# 绝对路径(以 / 或 \ 开头)保持不变
|
||||
if rel[0] == '/' or rel[0] == '\\':
|
||||
return rel
|
||||
|
||||
rel_len: t.CSizeT = string.strlen(rel)
|
||||
dir_len: t.CSizeT = string.strlen(project_dir)
|
||||
|
||||
# 处理 ../ 或 ..\\ 前缀:拼接 project_dir/../...
|
||||
if rel_len >= 3 and rel[0] == '.' and rel[1] == '.':
|
||||
if rel[2] == '/' or rel[2] == '\\':
|
||||
if dir_len == 0:
|
||||
return rel
|
||||
total_len: t.CSizeT = dir_len + 1 + rel_len + 1
|
||||
buf: str = _mbuddy.alloc(total_len)
|
||||
if buf is None:
|
||||
return rel
|
||||
viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel)
|
||||
return buf
|
||||
|
||||
# 处理 ./ 或 .\\ 前缀:拼接 project_dir + rel[2:]
|
||||
rel_off: t.CSizeT = 0
|
||||
if rel_len >= 2 and rel[0] == '.':
|
||||
if rel[1] == '/' or rel[1] == '\\':
|
||||
rel_off = 2
|
||||
else:
|
||||
return rel # 不是 ./ 开头,保持不变
|
||||
else:
|
||||
return rel # 不是 . 开头,保持不变
|
||||
|
||||
if dir_len == 0:
|
||||
# project_dir 为空(当前目录),去掉 ./ 前缀即可
|
||||
return rel + rel_off
|
||||
# 拼接: project_dir + "/" + rel[rel_off:]
|
||||
total_len = dir_len + 1 + (rel_len - rel_off) + 1
|
||||
buf = _mbuddy.alloc(total_len)
|
||||
if buf is None:
|
||||
return rel # 分配失败,返回原路径
|
||||
viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel + rel_off)
|
||||
return buf
|
||||
|
||||
|
||||
def resolve_paths(project_dir: str) -> int:
|
||||
"""解析并规范化工程路径(src/build/includes)
|
||||
|
||||
将 project.vpj 中的相对路径(以 ./ 开头)转换为基于 project_dir 的路径。
|
||||
BuildDir 解析后,TempDir = {BuildDir}/temp,OutputDir = {BuildDir}/output。
|
||||
|
||||
Args:
|
||||
project_dir: 工程根目录(project.vpj 所在目录)
|
||||
|
||||
Returns:
|
||||
0 表示成功,非 0 表示失败
|
||||
"""
|
||||
global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir
|
||||
if project_dir is None:
|
||||
return 1
|
||||
if _mbuddy is None:
|
||||
return 1
|
||||
|
||||
SourceDir = _join_path(SourceDir, project_dir)
|
||||
BuildDir = _join_path(BuildDir, project_dir)
|
||||
|
||||
# TempDir = {BuildDir}/temp
|
||||
if BuildDir is not None:
|
||||
bd_len: t.CSizeT = string.strlen(BuildDir)
|
||||
temp_buf: str = _mbuddy.alloc(bd_len + 8)
|
||||
if temp_buf is not None:
|
||||
viperlib.snprintf(temp_buf, bd_len + 8, "%s/temp", BuildDir)
|
||||
TempDir = temp_buf
|
||||
# OutputDir = {BuildDir}/output
|
||||
output_buf: str = _mbuddy.alloc(bd_len + 8)
|
||||
if output_buf is not None:
|
||||
viperlib.snprintf(output_buf, bd_len + 8, "%s/output", BuildDir)
|
||||
OutputDir = output_buf
|
||||
|
||||
# includes 路径可能是 ../includes 形式,需要基于 project_dir 解析
|
||||
if IncludesDir is not None:
|
||||
IncludesDir = _join_path(IncludesDir, project_dir)
|
||||
return 0
|
||||
|
||||
|
||||
def get_includes_binary_dir() -> str:
|
||||
"""获取 includes.binary 目录路径(includes 目录 + .binary 后缀)
|
||||
|
||||
includes 目录如 ../includes,则 includes.binary 为 ../includes.binary
|
||||
"""
|
||||
if IncludesDir is None:
|
||||
return None
|
||||
inc_len: t.CSizeT = string.strlen(IncludesDir)
|
||||
buf: str = _mbuddy.alloc(inc_len + 8)
|
||||
if buf is None:
|
||||
return None
|
||||
viperlib.snprintf(buf, inc_len + 8, "%s.binary", IncludesDir)
|
||||
return buf
|
||||
|
||||
|
||||
def print_config():
|
||||
"""打印当前配置"""
|
||||
buf: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if buf is None:
|
||||
return
|
||||
if ProjectName is not None:
|
||||
viperlib.snprintf(buf, 1024, "project: %s v%s", ProjectName,
|
||||
ProjectVersion if ProjectVersion is not None else "?")
|
||||
VLogger.info(buf, "config")
|
||||
if SourceDir is not None:
|
||||
viperlib.snprintf(buf, 1024, "source_dir: %s", SourceDir)
|
||||
VLogger.info(buf, "config")
|
||||
if BuildDir is not None:
|
||||
viperlib.snprintf(buf, 1024, "build_dir: %s", BuildDir)
|
||||
VLogger.info(buf, "config")
|
||||
if TempDir is not None:
|
||||
viperlib.snprintf(buf, 1024, "temp_dir: %s", TempDir)
|
||||
VLogger.info(buf, "config")
|
||||
if OutputDir is not None:
|
||||
viperlib.snprintf(buf, 1024, "output_dir: %s", OutputDir)
|
||||
VLogger.info(buf, "config")
|
||||
if CompilerCmd is not None:
|
||||
viperlib.snprintf(buf, 1024, "compiler: %s", CompilerCmd)
|
||||
VLogger.info(buf, "config")
|
||||
if LinkerCmd is not None:
|
||||
viperlib.snprintf(buf, 1024, "linker: %s -> %s", LinkerCmd,
|
||||
LinkerOutput if LinkerOutput is not None else "?")
|
||||
VLogger.info(buf, "config")
|
||||
if IncludesDir is not None:
|
||||
viperlib.snprintf(buf, 1024, "includes: %s", IncludesDir)
|
||||
VLogger.info(buf, "config")
|
||||
viperlib.snprintf(buf, 1024, "sha1_slice_level: %d", Sha1SliceLevel)
|
||||
VLogger.info(buf, "config")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# slice_subdir - 根据 SHA1 和切片层数返回子目录路径
|
||||
#
|
||||
# 每层取 SHA1 的 2 个字符作为子目录名:
|
||||
# level=0 → None(不切片)
|
||||
# level=1 → "b7"
|
||||
# level=2 → "b7/90"
|
||||
# level=3 → "b7/90/23"
|
||||
#
|
||||
# Args:
|
||||
# sha1: SHA1 字符串(至少 2*level 字符)
|
||||
# level: 切片层数
|
||||
#
|
||||
# Returns:
|
||||
# 子目录路径字符串(mbuddy 分配,无需释放),level<=0 时返回 None
|
||||
# ============================================================
|
||||
def slice_subdir(sha1: str, level: int) -> str:
|
||||
"""根据 SHA1 和切片层数返回子目录路径"""
|
||||
if level <= 0 or sha1 is None:
|
||||
return None
|
||||
if _mbuddy is None:
|
||||
return None
|
||||
# 每层 2 字符 + 分隔符,最后无分隔符 + null
|
||||
# buf 大小: level * 2 + (level - 1) + 1 = level * 3
|
||||
buf_len: t.CSizeT = t.CSizeT(level * 3)
|
||||
buf: str = _mbuddy.alloc(buf_len)
|
||||
if buf is None:
|
||||
return None
|
||||
pos: int = 0
|
||||
i: int = 0
|
||||
while i < level:
|
||||
if i > 0:
|
||||
buf[pos] = '/'
|
||||
pos += 1
|
||||
idx: int = i * 2
|
||||
buf[pos] = sha1[idx]
|
||||
buf[pos + 1] = sha1[idx + 1]
|
||||
pos += 2
|
||||
i += 1
|
||||
buf[pos] = '\0'
|
||||
return buf
|
||||
@@ -1,130 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import hashlib
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Utils - 工程工具函数
|
||||
#
|
||||
# 提供 SHA1 计算和目录清理等通用工具函数。
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# compute_sha1 - 计算字符串的 SHA1,返回前 16 个十六进制字符
|
||||
#
|
||||
# 使用 includes/hashlib 库的 sha1 类计算摘要,转为十六进制字符串。
|
||||
# 参考 Projectrans.py 的 compute_sha1(hashlib.sha1().hexdigest()[:16])。
|
||||
# ============================================================
|
||||
def compute_sha1(pool: memhub.MemBuddy | t.CPtr, content: str) -> str:
|
||||
"""计算字符串的 SHA1,返回前 16 个十六进制字符(用于文件命名)"""
|
||||
if content is None or pool is None:
|
||||
return None
|
||||
|
||||
# 构造 sha1 对象(__init__ 会初始化 state/count/buf)
|
||||
# ctx 在栈上分配(alloca),函数内使用完即丢弃,无需堆分配
|
||||
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
|
||||
if ctx is None:
|
||||
return None
|
||||
|
||||
# 计算摘要
|
||||
ctx.update(content)
|
||||
digest: bytes = pool.alloc(hashlib.SHA1_DIGEST_LEN)
|
||||
if digest is None:
|
||||
return None
|
||||
ctx.final(digest)
|
||||
|
||||
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
|
||||
hex_buf: str = pool.alloc(17)
|
||||
if hex_buf is None:
|
||||
return None
|
||||
for i in range(8):
|
||||
hi: int = (digest[i] >> 4) & 0xF
|
||||
lo: int = digest[i] & 0xF
|
||||
if hi < 10:
|
||||
hex_buf[i * 2] = '0' + hi
|
||||
else:
|
||||
hex_buf[i * 2] = 'a' + (hi - 10)
|
||||
if lo < 10:
|
||||
hex_buf[i * 2 + 1] = '0' + lo
|
||||
else:
|
||||
hex_buf[i * 2 + 1] = 'a' + (lo - 10)
|
||||
hex_buf[16] = '\0'
|
||||
return hex_buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# CleanDir - 递归删除目录中所有文件和子目录(保留 dir_path 本身)
|
||||
#
|
||||
# 用于 --clean 选项:清理 temp_dir 和 output_dir 中的旧文件。
|
||||
# SHA1 分片目录结构(如 temp/1c/、temp/7a/)需要递归清理,
|
||||
# 否则旧的截断文件(如 256KB text.ll)会被 Phase1 跳过逻辑复用。
|
||||
# ============================================================
|
||||
def CleanDir(dir_path: str) -> int:
|
||||
"""递归删除目录中所有文件和子目录,保留 dir_path 本身,返回删除的文件数,-1 表示错误"""
|
||||
if dir_path is None:
|
||||
return -1
|
||||
dir_len: t.CSizeT = string.strlen(dir_path)
|
||||
pattern: bytes = stdlib.malloc(dir_len + 8)
|
||||
if pattern is None:
|
||||
return -1
|
||||
viperlib.snprintf(pattern, dir_len + 8, "%s/*", dir_path)
|
||||
|
||||
find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
if find_data is None:
|
||||
stdlib.free(pattern)
|
||||
return -1
|
||||
string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
|
||||
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data)
|
||||
if handle == w32.win32base.INVALID_HANDLE_VALUE:
|
||||
stdlib.free(pattern)
|
||||
stdlib.free(find_data)
|
||||
return 0
|
||||
|
||||
deleted: int = 0
|
||||
while 1:
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
# 跳过 . 和 ..
|
||||
if fname[0] == '.':
|
||||
if fname[1] == '\0':
|
||||
fname = None
|
||||
elif fname[1] == '.' and fname[2] == '\0':
|
||||
fname = None
|
||||
if fname is not None:
|
||||
fname_len: t.CSizeT = string.strlen(fname)
|
||||
full_path: bytes = stdlib.malloc(dir_len + fname_len + 2)
|
||||
if full_path is not None:
|
||||
viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", dir_path, fname)
|
||||
# 检查是否为目录(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
is_dir: t.CUInt32T = find_data.dwFileAttributes & w32.win32file.FILE_ATTRIBUTE_DIRECTORY
|
||||
if is_dir != 0:
|
||||
# 递归清理子目录中的文件
|
||||
sub_deleted: int = CleanDir(full_path)
|
||||
if sub_deleted > 0:
|
||||
deleted += sub_deleted
|
||||
# 删除空子目录(RemoveDirectoryA 要求目录为空)
|
||||
w32.win32file.RemoveDirectoryA(full_path)
|
||||
else:
|
||||
# 删除文件
|
||||
if w32.win32file.DeleteFileA(full_path) != 0:
|
||||
deleted += 1
|
||||
stdlib.free(full_path)
|
||||
|
||||
if w32.win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
|
||||
w32.win32file.FindClose(handle)
|
||||
stdlib.free(pattern)
|
||||
stdlib.free(find_data)
|
||||
return deleted
|
||||
@@ -1,12 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
from .Config import Load_project_config, resolve_paths
|
||||
from .Utils import compute_sha1, CleanDir
|
||||
|
||||
__all__ = [
|
||||
'Load_project_config',
|
||||
'resolve_paths',
|
||||
'compute_sha1',
|
||||
'CleanDir',
|
||||
]
|
||||
@@ -1,28 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import lib.core.VLogger as VLogger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lib 包入口 - 声明全局 _mbuddy 内存池指针
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 内存池指针(由 App/main.py 初始化后注入)
|
||||
# 注意: 使用 MemBuddy 类型而非 MemManager,避免虚函数分派不工作时调用父类 alloc 返回 None
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
|
||||
def InitLib(mb: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。
|
||||
|
||||
Args:
|
||||
mb: memhub.MemBuddy 实例指针
|
||||
|
||||
Returns:
|
||||
0 表示成功,非 0 表示失败
|
||||
"""
|
||||
if mb is None:
|
||||
return 1
|
||||
VLogger._mbuddy = mb
|
||||
return 0
|
||||
@@ -1,624 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import subprocess
|
||||
import viperlib
|
||||
import ast
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
# ============================================================
|
||||
# BuildPipeline - 编译管线
|
||||
#
|
||||
# 负责将 LLVM IR 编译为可执行文件:
|
||||
# 1. 写 .ll 文件到 temp 目录
|
||||
# 2. 调用 llc 编译 .ll → .obj
|
||||
# 3. 调用 clang++ 链接 .obj → .exe
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 源代码缓冲区大小(1MB)
|
||||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TranslateFileGetTrans - 翻译单个文件,返回 Translator 对象
|
||||
#
|
||||
# 读取文件 → AST 解析 → LLVM IR 翻译,返回 Translator 对象供
|
||||
# 调用者 dump_ir。命名空间隔离:includes 文件宽松模式(全部可见),
|
||||
# 用户文件严格模式(仅本地+import)。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# file_path: 源文件路径
|
||||
# sha1_val: 文件内容的 SHA1 前16字符(用于函数名混淆)
|
||||
#
|
||||
# Returns:
|
||||
# Translator 对象(None 失败)
|
||||
# ============================================================
|
||||
def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str,
|
||||
sha1_val: str,
|
||||
current_package: str = None,
|
||||
declare_only: int = 0) -> HandlesTranslator.Translator | t.CPtr:
|
||||
"""翻译文件,返回 Translator 对象(调用者负责 dump_ir),None 失败
|
||||
|
||||
current_package: 当前文件所属包名(用于解析相对导入),None 表示顶级模块
|
||||
declare_only: 0=全量翻译(默认),1=仅注册 struct/enum/union(不翻译方法体)
|
||||
"""
|
||||
if file_path is None:
|
||||
return None
|
||||
f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
return None
|
||||
src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||||
if src_buf is None:
|
||||
f.close()
|
||||
return None
|
||||
bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE)
|
||||
f.close()
|
||||
if bytes_read <= 0:
|
||||
stdlib.free(src_buf)
|
||||
return None
|
||||
if bytes_read < SRC_BUF_SIZE:
|
||||
src_buf[bytes_read] = 0
|
||||
else:
|
||||
src_buf[SRC_BUF_SIZE - 1] = 0
|
||||
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||||
ast._lexer_init(lx, src_buf, mb)
|
||||
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
|
||||
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
|
||||
# parse 完成后 AST 树已独立,释放源代码缓冲区(避免 1MB/文件泄漏)
|
||||
stdlib.free(src_buf)
|
||||
if tree is None:
|
||||
return None
|
||||
tr: HandlesTranslator.Translator | t.CPtr = mb.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
tr.__before_init__()
|
||||
tr.__init__()
|
||||
tr.ModuleSha1 = sha1_val
|
||||
tr.CurrentPackage = current_package
|
||||
tr._declare_only = declare_only
|
||||
# 设置当前文件名(供报错使用)
|
||||
HandlesType.set_current_file(file_path)
|
||||
# 模块切换:清空 CDefine 常量表,确保每个模块的 CDefine 常量正确隔离
|
||||
HandlesType.clear_cdefine_constants()
|
||||
# 命名空间隔离:includes 文件宽松模式(全部可见),用户文件严格模式(仅本地+import)
|
||||
strict_mode: int = 1
|
||||
if string.strstr(file_path, "includes") is not None:
|
||||
strict_mode = 0
|
||||
HandlesStruct.reset_visible_structs(mb, strict_mode)
|
||||
ret: int = tr.translate(tree)
|
||||
if ret != 0:
|
||||
return None
|
||||
return tr
|
||||
|
||||
|
||||
class BuildResult:
|
||||
Success: t.CInt
|
||||
OutputPath: str
|
||||
ErrorMsg: str
|
||||
|
||||
def __new__(self) -> t.CPtr:
|
||||
return t.CPtr(_mbuddy.alloc(BuildResult.__sizeof__()))
|
||||
|
||||
def __init__(self):
|
||||
self.Success = 0
|
||||
self.OutputPath = None
|
||||
self.ErrorMsg = None
|
||||
|
||||
|
||||
def ensure_dir(path: str) -> int:
|
||||
"""递归创建目录(类似 mkdir -p),目录已存在视为成功
|
||||
|
||||
Args:
|
||||
path: 目录路径(支持 / 或 \\ 分隔符)
|
||||
|
||||
Returns:
|
||||
0 成功(包括目录已存在),非 0 失败
|
||||
"""
|
||||
if path is None:
|
||||
return 1
|
||||
|
||||
path_len: t.CSizeT = string.strlen(path)
|
||||
if path_len == 0:
|
||||
return 0
|
||||
|
||||
# 复制路径到可写缓冲区(逐级截断用)
|
||||
buf: bytes = _mbuddy.alloc(path_len + 1)
|
||||
if buf is None:
|
||||
return 1
|
||||
string.strcpy(buf, path)
|
||||
|
||||
# 遇到分隔符时临时截断,创建每一层目录
|
||||
# CreateDirectoryA 在目录已存在时返回 0(失败),忽略即可
|
||||
i: int = 0
|
||||
plen: int = path_len
|
||||
while i < plen:
|
||||
ch: int = buf[i]
|
||||
if ch == 47 or ch == 92: # '/' = 47, '\\' = 92
|
||||
saved: int = ch
|
||||
buf[i] = '\0'
|
||||
w32.win32file.CreateDirectoryA(buf, None)
|
||||
buf[i] = saved
|
||||
i += 1
|
||||
|
||||
# 创建最终目录
|
||||
w32.win32file.CreateDirectoryA(buf, None)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# build_sliced_path - 构建切片路径并确保目录存在
|
||||
#
|
||||
# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录:
|
||||
# level=0 → {base_dir}/{sha1}.{ext}
|
||||
# level=1 → {base_dir}/b7/{sha1}.{ext}
|
||||
# level=2 → {base_dir}/b7/90/{sha1}.{ext}
|
||||
#
|
||||
# 自动调用 ensure_dir 创建子目录。
|
||||
#
|
||||
# Args:
|
||||
# base_dir: 基础目录(如 temp_dir)
|
||||
# sha1: SHA1 字符串
|
||||
# ext: 文件扩展名(如 "stub.ll")
|
||||
#
|
||||
# Returns:
|
||||
# 完整文件路径(mbuddy 分配),None 失败
|
||||
# ============================================================
|
||||
def build_sliced_path(base_dir: str, sha1: str, ext: str) -> str:
|
||||
"""构建切片路径并确保目录存在"""
|
||||
if base_dir is None or sha1 is None or ext is None:
|
||||
return None
|
||||
|
||||
subdir: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel)
|
||||
base_len: t.CSizeT = string.strlen(base_dir)
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
ext_len: t.CSizeT = string.strlen(ext)
|
||||
|
||||
if subdir is not None:
|
||||
sub_len: t.CSizeT = string.strlen(subdir)
|
||||
# ensure_dir({base_dir}/{subdir})
|
||||
dir_path: str = _mbuddy.alloc(base_len + sub_len + 2)
|
||||
if dir_path is not None:
|
||||
viperlib.snprintf(dir_path, base_len + sub_len + 2, "%s/%s", base_dir, subdir)
|
||||
ensure_dir(dir_path)
|
||||
# 文件路径: {base_dir}/{subdir}/{sha1}.{ext}
|
||||
path_len: t.CSizeT = base_len + sub_len + sha1_len + ext_len + 4
|
||||
path: str = _mbuddy.alloc(path_len)
|
||||
if path is None:
|
||||
return None
|
||||
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", base_dir, subdir, sha1, ext)
|
||||
return path
|
||||
else:
|
||||
# 无切片: {base_dir}/{sha1}.{ext}
|
||||
path_len = base_len + sha1_len + ext_len + 3
|
||||
path = _mbuddy.alloc(path_len)
|
||||
if path is None:
|
||||
return None
|
||||
viperlib.snprintf(path, path_len, "%s/%s.%s", base_dir, sha1, ext)
|
||||
return path
|
||||
|
||||
|
||||
def write_ir_to_file(ir_buf: bytes, ir_len: t.CSizeT, output_dir: str, module_name: str) -> int:
|
||||
"""将 IR 缓冲区写入 .ll 文件
|
||||
|
||||
Args:
|
||||
ir_buf: IR 文本缓冲区
|
||||
ir_len: IR 文本长度
|
||||
output_dir: 输出目录(temp 或 output)
|
||||
module_name: 模块名(SHA1)
|
||||
|
||||
Returns:
|
||||
0 成功,非 0 失败
|
||||
"""
|
||||
if ir_buf is None or output_dir is None or module_name is None:
|
||||
return 1
|
||||
|
||||
# 构造切片路径: output_dir/{sha1前缀}/{module_name}.ll
|
||||
path: str = build_sliced_path(output_dir, module_name, "ll")
|
||||
if path is None:
|
||||
return 1
|
||||
|
||||
# 打开文件写入
|
||||
f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.W)
|
||||
if f.closed:
|
||||
return 1
|
||||
|
||||
written: t.CInt64T = f.write(ir_buf, ir_len)
|
||||
f.close()
|
||||
if written < 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: str, cc_flags: str) -> int:
|
||||
"""调用 llc 将 .ll 编译为 .obj
|
||||
|
||||
Args:
|
||||
ir_path: .ll 文件路径
|
||||
output_dir: 输出目录
|
||||
module_name: 模块名(SHA1,用于生成 .obj 文件名)
|
||||
cc_cmd: 编译器命令(如 "llc")
|
||||
cc_flags: 编译器参数(如 "-filetype=obj -relocation-model=pic")
|
||||
|
||||
Returns:
|
||||
0 成功,非 0 失败
|
||||
"""
|
||||
if ir_path is None or cc_cmd is None or output_dir is None or module_name is None:
|
||||
return 1
|
||||
|
||||
# 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj
|
||||
obj_path: str = build_sliced_path(output_dir, module_name, "obj")
|
||||
if obj_path is None:
|
||||
return 1
|
||||
|
||||
# 构造命令: llc -filetype=obj -o {obj_path} ir_path
|
||||
cmd_len: t.CSizeT = string.strlen(cc_cmd) + string.strlen(cc_flags) + string.strlen(obj_path) + string.strlen(ir_path) + 64
|
||||
cmd: bytes = _mbuddy.alloc(cmd_len)
|
||||
if cmd is None:
|
||||
return 1
|
||||
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path)
|
||||
|
||||
# 用 stdlib.system() 直接在控制台运行,输出直接显示
|
||||
# 避免 subprocess 管道捕获丢失输出
|
||||
sys_ret: int = stdlib.system(cmd)
|
||||
if sys_ret != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd)
|
||||
VLogger.error(fb, "LLC")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def _CollectObjFilesImpl(base_dir: str, bd_len: t.CSizeT,
|
||||
out_buf: bytes, out_pos: t.CSizeT, out_size: t.CSizeT) -> t.CSizeT:
|
||||
"""递归扫描 base_dir,收集 .obj 文件路径到 out_buf,返回新的 out_pos
|
||||
|
||||
支持切片子目录(如 dir/43/{sha1}.obj)。
|
||||
"""
|
||||
find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
if find_data is None:
|
||||
return out_pos
|
||||
string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
|
||||
pattern: bytes = _mbuddy.alloc(bd_len + 8)
|
||||
if pattern is None:
|
||||
return out_pos
|
||||
viperlib.snprintf(pattern, bd_len + 8, "%s/*", base_dir)
|
||||
|
||||
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data)
|
||||
_mbuddy.free(pattern)
|
||||
if handle == w32.win32base.INVALID_HANDLE_VALUE:
|
||||
return out_pos
|
||||
|
||||
while True:
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
fname_len: t.CSizeT = string.strlen(fname)
|
||||
if fname_len > 0:
|
||||
# 跳过 . 和 ..
|
||||
is_dot: int = 0
|
||||
if fname_len == 1 and fname[0] == '.':
|
||||
is_dot = 1
|
||||
elif fname_len == 2 and fname[0] == '.' and fname[1] == '.':
|
||||
is_dot = 1
|
||||
if is_dot == 0:
|
||||
attrs: ULONG = find_data.dwFileAttributes
|
||||
is_dir: int = 0
|
||||
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
|
||||
is_dir = 1
|
||||
if is_dir != 0:
|
||||
# 递归扫描子目录
|
||||
sub_dir: bytes = _mbuddy.alloc(bd_len + fname_len + 2)
|
||||
if sub_dir is not None:
|
||||
viperlib.snprintf(sub_dir, bd_len + fname_len + 2, "%s/%s", base_dir, fname)
|
||||
sub_len: t.CSizeT = string.strlen(sub_dir)
|
||||
out_pos = _CollectObjFilesImpl(sub_dir, sub_len, out_buf, out_pos, out_size)
|
||||
_mbuddy.free(sub_dir)
|
||||
else:
|
||||
# 检查是否是 .obj 文件
|
||||
if fname_len > 4:
|
||||
if fname[fname_len - 4] == '.' and fname[fname_len - 3] == 'o' and fname[fname_len - 2] == 'b' and fname[fname_len - 1] == 'j':
|
||||
need: t.CSizeT = bd_len + 1 + fname_len + 2
|
||||
if out_pos + need < out_size:
|
||||
if out_pos > 0:
|
||||
out_buf[out_pos] = ' '
|
||||
out_pos += 1
|
||||
viperlib.snprintf(out_buf + out_pos, need, "%s/%s", base_dir, fname)
|
||||
out_pos += bd_len + 1 + fname_len
|
||||
else:
|
||||
break
|
||||
|
||||
if w32.win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
|
||||
w32.win32file.FindClose(handle)
|
||||
return out_pos
|
||||
|
||||
|
||||
def collect_obj_files(includes_binary_dir: str, out_buf: bytes, out_size: t.CSizeT) -> t.CSizeT:
|
||||
"""递归扫描 includes_binary_dir 目录,收集所有 .obj 文件路径到 out_buf
|
||||
|
||||
支持切片子目录(如 includes_binary_dir/43/{sha1}.obj)。
|
||||
|
||||
Args:
|
||||
includes_binary_dir: includes.binary 目录路径
|
||||
out_buf: 输出缓冲区(用于存放空格分隔的 .obj 文件路径)
|
||||
out_size: 输出缓冲区大小
|
||||
|
||||
Returns:
|
||||
写入的字节数(不含 null 终止符),0 表示无文件或错误
|
||||
"""
|
||||
if includes_binary_dir is None or out_buf is None or out_size == 0:
|
||||
return 0
|
||||
|
||||
out_buf[0] = '\0'
|
||||
dir_len: t.CSizeT = string.strlen(includes_binary_dir)
|
||||
out_pos: t.CSizeT = _CollectObjFilesImpl(includes_binary_dir, dir_len, out_buf, 0, out_size)
|
||||
out_buf[out_pos] = '\0'
|
||||
return out_pos
|
||||
|
||||
|
||||
def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_flags: str, linker_output: str,
|
||||
includes_binary_dir: str) -> int:
|
||||
"""调用 clang++ 链接 .obj 为 .exe
|
||||
|
||||
Args:
|
||||
output_dir: 输出目录(包含 .obj 文件)
|
||||
module_name: 模块名(SHA1)
|
||||
linker_cmd: 链接器命令(如 "clang++")
|
||||
linker_flags: 链接器参数
|
||||
linker_output: 输出文件名(如 "test.exe")
|
||||
includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj)
|
||||
|
||||
Returns:
|
||||
0 成功,非 0 失败
|
||||
"""
|
||||
if output_dir is None or linker_cmd is None or module_name is None:
|
||||
return 1
|
||||
|
||||
# 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj
|
||||
obj_path: str = build_sliced_path(output_dir, module_name, "obj")
|
||||
if obj_path is None:
|
||||
return 1
|
||||
|
||||
# 收集 includes.binary 的 .obj 文件路径
|
||||
EXTRA_BUF_SIZE: t.CSizeT = 32768
|
||||
extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE)
|
||||
if extra_objs is None:
|
||||
return 1
|
||||
extra_len: t.CSizeT = 0
|
||||
if includes_binary_dir is not None:
|
||||
extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE)
|
||||
if extra_len > 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "附加 %d 字节的 includes.binary .obj 文件", extra_len)
|
||||
VLogger.info(fb, "link")
|
||||
else:
|
||||
fb = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "includes.binary 无 .obj 文件: %s", includes_binary_dir)
|
||||
VLogger.warning(fb, "link")
|
||||
|
||||
# 构造命令: clang++ {obj_path} extra_objs -o {output_dir}/{linker_output} linker_flags
|
||||
# 注意: .obj 文件必须在 -l 库标志之前,否则链接器无法解析符号依赖
|
||||
cmd_len: t.CSizeT = string.strlen(linker_cmd) + string.strlen(obj_path) + string.strlen(linker_flags) + string.strlen(output_dir) + string.strlen(linker_output) + extra_len + 128
|
||||
cmd: bytes = _mbuddy.alloc(cmd_len)
|
||||
if cmd is None:
|
||||
return 1
|
||||
if extra_len > 0:
|
||||
viperlib.snprintf(cmd, cmd_len, "%s %s %s -o %s/%s %s",
|
||||
linker_cmd, obj_path, extra_objs,
|
||||
output_dir, linker_output, linker_flags)
|
||||
else:
|
||||
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s/%s %s",
|
||||
linker_cmd, obj_path, output_dir, linker_output,
|
||||
linker_flags)
|
||||
|
||||
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
|
||||
if result is None:
|
||||
VLogger.error("subprocess.run 返回 None", "link")
|
||||
return 1
|
||||
if result.returncode != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "链接失败,返回码: %d", result.returncode)
|
||||
VLogger.error(fb, "link")
|
||||
fb = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "命令: %s", cmd)
|
||||
VLogger.error(fb, "link")
|
||||
# 显示链接器错误输出
|
||||
# 注意: subprocess 在 Windows 下将 stderr 合并到 stdout,result.stderr 总是 None
|
||||
if result.stdout is not None:
|
||||
VLogger.error(result.stdout, "link")
|
||||
else:
|
||||
VLogger.error("无输出捕获", "link")
|
||||
if result.stderr is not None:
|
||||
VLogger.error(result.stderr, "link")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT,
|
||||
temp_dir: str, output_dir: str, module_name: str,
|
||||
cc_cmd: str, cc_flags: str) -> int:
|
||||
"""编译 IR 到 .obj(不链接)
|
||||
|
||||
Args:
|
||||
ir_buf: LLVM IR 文本缓冲区
|
||||
ir_len: IR 文本长度
|
||||
temp_dir: 临时目录
|
||||
output_dir: 输出目录
|
||||
module_name: 模块名(SHA1)
|
||||
cc_cmd: 编译器命令
|
||||
cc_flags: 编译器参数
|
||||
|
||||
Returns:
|
||||
0 成功,非 0 失败
|
||||
"""
|
||||
if ir_buf is None or temp_dir is None or output_dir is None or module_name is None:
|
||||
return 1
|
||||
|
||||
# Step 1: 写 .ll 文件
|
||||
ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name)
|
||||
if ret != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", module_name)
|
||||
VLogger.error(fb, "compile")
|
||||
return 1
|
||||
|
||||
# Step 2: 构造切片 .ll 路径并编译 → .obj
|
||||
ir_path: str = build_sliced_path(temp_dir, module_name, "ll")
|
||||
if ir_path is None:
|
||||
return 1
|
||||
|
||||
ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags)
|
||||
if ret != 0:
|
||||
fb = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "llc 编译失败: %s", module_name)
|
||||
VLogger.error(fb, "compile")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT,
|
||||
linker_cmd: str, linker_flags: str, linker_output: str,
|
||||
includes_binary_dir: str) -> int:
|
||||
"""链接多个 .obj 文件为 .exe
|
||||
|
||||
Args:
|
||||
obj_paths: 空格分隔的 .obj 文件完整路径字符串
|
||||
obj_paths_len: obj_paths 长度
|
||||
linker_cmd: 链接器命令(如 "clang++")
|
||||
linker_flags: 链接器参数
|
||||
linker_output: 输出文件完整路径
|
||||
includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj)
|
||||
|
||||
Returns:
|
||||
0 成功,非 0 失败
|
||||
"""
|
||||
if obj_paths is None or obj_paths_len == 0 or linker_cmd is None:
|
||||
return 1
|
||||
|
||||
# 收集 includes.binary 的 .obj 文件路径
|
||||
EXTRA_BUF_SIZE: t.CSizeT = 32768
|
||||
extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE)
|
||||
if extra_objs is None:
|
||||
return 1
|
||||
extra_len: t.CSizeT = 0
|
||||
if includes_binary_dir is not None:
|
||||
extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE)
|
||||
|
||||
# 构造命令: clang++ obj_paths extra_objs -o linker_output linker_flags
|
||||
cmd_len: t.CSizeT = string.strlen(linker_cmd) + obj_paths_len + string.strlen(linker_flags) + string.strlen(linker_output) + extra_len + 128
|
||||
cmd: bytes = _mbuddy.alloc(cmd_len)
|
||||
if cmd is None:
|
||||
return 1
|
||||
if extra_len > 0:
|
||||
viperlib.snprintf(cmd, cmd_len, "%s %s %s -o %s %s",
|
||||
linker_cmd, obj_paths, extra_objs,
|
||||
linker_output, linker_flags)
|
||||
else:
|
||||
viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s",
|
||||
linker_cmd, obj_paths, linker_output, linker_flags)
|
||||
|
||||
# 用 subprocess.run 捕获 clang++ 的 stdout/stderr 输出
|
||||
# 之前用 stdlib.system() 无法捕获具体错误(undefined reference 等),
|
||||
# 导致 1.txt 中只看到"链接失败,返回码: 1"而看不到未解析符号
|
||||
result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True)
|
||||
if result is None:
|
||||
VLogger.error("subprocess.run 返回 None", "link")
|
||||
return 1
|
||||
if result.returncode != 0:
|
||||
# 先用 stdio.printf 直接输出 clang++ 的完整错误输出(含 undefined reference)
|
||||
# 必须在 VLogger.error 之前输出,因为 VLogger.error 会调用 sys.exit(1) 终止进程
|
||||
if result.stdout is not None:
|
||||
stdio.printf("=== clang++ 链接错误输出 ===\n%s\n", result.stdout)
|
||||
if result.stderr is not None:
|
||||
stdio.printf("=== clang++ stderr ===\n%s\n", result.stderr)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", result.returncode, cmd)
|
||||
VLogger.error(fb, "link")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def run_pipeline(ir_buf: bytes, ir_len: t.CSizeT,
|
||||
temp_dir: str, output_dir: str, module_name: str,
|
||||
cc_cmd: str, cc_flags: str,
|
||||
linker_cmd: str, linker_flags: str, linker_output: str,
|
||||
includes_binary_dir: str) -> BuildResult | t.CPtr:
|
||||
"""执行完整编译管线
|
||||
|
||||
Args:
|
||||
ir_buf: LLVM IR 文本缓冲区
|
||||
ir_len: IR 文本长度
|
||||
temp_dir: 临时目录
|
||||
output_dir: 输出目录
|
||||
module_name: 模块名
|
||||
cc_cmd: 编译器命令
|
||||
cc_flags: 编译器参数
|
||||
linker_cmd: 链接器命令
|
||||
linker_flags: 链接器参数
|
||||
linker_output: 输出文件名
|
||||
includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj)
|
||||
|
||||
Returns:
|
||||
BuildResult 对象
|
||||
"""
|
||||
result: BuildResult | t.CPtr = BuildResult()
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# Step 0: 确保 temp/output 目录存在(自动创建,避免写文件失败)
|
||||
ensure_dir(temp_dir)
|
||||
ensure_dir(output_dir)
|
||||
|
||||
# Step 1: 写 .ll 文件
|
||||
ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name)
|
||||
if ret != 0:
|
||||
result.Success = 0
|
||||
result.ErrorMsg = "写 .ll 文件失败"
|
||||
return result
|
||||
|
||||
# Step 2: llc 编译 .ll → .obj
|
||||
# 构造切片 .ll 文件路径
|
||||
ir_path: str = build_sliced_path(temp_dir, module_name, "ll")
|
||||
if ir_path is None:
|
||||
result.Success = 0
|
||||
result.ErrorMsg = "内存分配失败"
|
||||
return result
|
||||
|
||||
ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags)
|
||||
if ret != 0:
|
||||
result.Success = 0
|
||||
result.ErrorMsg = "llc 编译失败"
|
||||
return result
|
||||
|
||||
# Step 3: clang++ 链接 .obj → .exe(附加 includes.binary 预编译 .obj)
|
||||
ret = link_obj_to_exe(output_dir, module_name, linker_cmd, linker_flags, linker_output,
|
||||
includes_binary_dir)
|
||||
if ret != 0:
|
||||
result.Success = 0
|
||||
result.ErrorMsg = "链接失败"
|
||||
return result
|
||||
|
||||
result.Success = 1
|
||||
return result
|
||||
@@ -1,504 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAnnAssign - AnnAssign 语句处理(Mixin 继承模式)
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数)
|
||||
#
|
||||
# 支持两种形式:
|
||||
# 1. Attribute(Name('t'), 'CDefine')
|
||||
# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解)
|
||||
# ============================================================
|
||||
def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检测注解是否为 t.CDefine,返回 1 表示是,0 表示否"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if is_cdefine_annotation(bop.left) != 0:
|
||||
return 1
|
||||
if is_cdefine_annotation(bop.right) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数)
|
||||
#
|
||||
# 支持的表达式形式:
|
||||
# 1. Constant(INT) — 如 0x0002, 42
|
||||
# 2. BinOp(BitOr/BitAnd) — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
# 3. Name — 引用已注册的 CDefine 常量
|
||||
# 4. Call — 如 t.CUnsignedLong(-11) → 取第一个参数
|
||||
# 5. UnaryOp(USub/UAdd/Invert) — 如 -11
|
||||
# ============================================================
|
||||
def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int:
|
||||
"""从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp)"""
|
||||
if val_node is None:
|
||||
return 0
|
||||
k: int = val_node.kind()
|
||||
|
||||
# Case 1: Constant(INT) — 如 0x0002
|
||||
if k == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node)
|
||||
if cn.const_kind != ast.CONST_INT:
|
||||
return 0
|
||||
return cn.int_val
|
||||
|
||||
# Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node)
|
||||
left_val: int = extract_cdefine_int_value(bop.left)
|
||||
right_val: int = extract_cdefine_int_value(bop.right)
|
||||
if bop.op == ast.OpKind.BitOr:
|
||||
return left_val | right_val
|
||||
if bop.op == ast.OpKind.BitAnd:
|
||||
return left_val & right_val
|
||||
if bop.op == ast.OpKind.Add:
|
||||
return left_val + right_val
|
||||
if bop.op == ast.OpKind.Sub:
|
||||
return left_val - right_val
|
||||
return 0
|
||||
|
||||
# Case 3: Name — 引用已注册的 CDefine 常量
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node)
|
||||
if nm.id is not None:
|
||||
looked_up: int = HandlesType.lookup_cdefine_constant(nm.id)
|
||||
if HandlesType.is_cdefine_found() != 0:
|
||||
return looked_up
|
||||
return 0
|
||||
|
||||
# Case 4: Call — 如 t.CUnsignedLong(-11)
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node)
|
||||
if cl.args is not None and cl.args.__len__() > 0:
|
||||
first_arg: ast.AST | t.CPtr = cl.args.get(0)
|
||||
arg_val: int = extract_cdefine_int_value(first_arg)
|
||||
return arg_val
|
||||
return 0
|
||||
|
||||
# Case 5: UnaryOp — 如 -11
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node)
|
||||
operand_val: int = extract_cdefine_int_value(uop.operand)
|
||||
if uop.op == ast.OpKind.USub:
|
||||
return -operand_val
|
||||
if uop.op == ast.OpKind.UAdd:
|
||||
return operand_val
|
||||
if uop.op == ast.OpKind.Invert:
|
||||
return ~operand_val
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _annotation_contains_name - 递归检查注解中是否包含指定名称
|
||||
#
|
||||
# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。
|
||||
# ============================================================
|
||||
def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int:
|
||||
"""递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含"""
|
||||
if annot is None or name is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot)
|
||||
if at.attr is not None and string.strcmp(at.attr, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot)
|
||||
if nm.id is not None and string.strcmp(nm.id, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BinOp:
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if _annotation_contains_name(bop.left, name) != 0:
|
||||
return 1
|
||||
if _annotation_contains_name(bop.right, name) != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _is_ptr_element_annotation - 检查注解是否为 bytes|t.CPtr 或 str|t.CPtr
|
||||
#
|
||||
# 返回 1=是(下标按 8 字节步长, i8** 语义), 0=否(下标按 1 字节步长, i8* 语义)
|
||||
#
|
||||
# 规则:
|
||||
# bytes|t.CPtr / str|t.CPtr → i8**(8 字节步长)→ 返回 1
|
||||
# t.CChar|t.CPtr / t.CInt8T|t.CPtr → i8*(1 字节步长)→ 返回 0
|
||||
# 纯 bytes / str → i8*(1 字节步长)→ 返回 0
|
||||
#
|
||||
# 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算
|
||||
# ============================================================
|
||||
def _is_ptr_element_annotation(annot: ast.AST | t.CPtr) -> int:
|
||||
"""检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式"""
|
||||
if annot is None:
|
||||
return 0
|
||||
k: int = annot.kind()
|
||||
if k != ast.ASTKind.BinOp:
|
||||
return 0
|
||||
bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot)
|
||||
if bop.op != ast.OpKind.BitOr:
|
||||
return 0
|
||||
if _annotation_contains_name(annot, "str") != 0:
|
||||
return 1
|
||||
if _annotation_contains_name(annot, "bytes") != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _init_global_array_from_list — 从列表字面量初始化全局数组
|
||||
#
|
||||
# 为每个元素生成 GEP + store 指令,将值存入全局数组的对应位置。
|
||||
# 适用于模块级 t.CArray[elem_ty, count] = [v0, v1, ...] 的初始化。
|
||||
#
|
||||
# Args:
|
||||
# builder: IRBuilder
|
||||
# pool: 编译器内存池
|
||||
# mod: LLVMModule
|
||||
# array_alloca: 全局数组变量的 Value 引用(类型为 [N x elem_ty]*)
|
||||
# list_node: ast.List 节点
|
||||
# trans: Translator 对象
|
||||
#
|
||||
# Returns:
|
||||
# 0 成功,1 失败
|
||||
# ============================================================
|
||||
def _init_global_array_from_list(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
array_alloca: llvmlite.Value | t.CPtr,
|
||||
list_node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> int:
|
||||
"""从列表字面量初始化全局数组,为每个元素生成 GEP + store"""
|
||||
if builder is None or array_alloca is None or list_node is None:
|
||||
return 1
|
||||
|
||||
# 获取数组类型(Pointee of [N x elem_ty]*)
|
||||
arr_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if array_alloca.Ty is not None:
|
||||
arr_ty = array_alloca.Ty.Pointee
|
||||
if arr_ty is None:
|
||||
return 1
|
||||
|
||||
# 匹配数组类型获取元素类型
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
match arr_ty:
|
||||
case llvmlite.LLVMType.Array(et, _):
|
||||
elem_ty = et
|
||||
if elem_ty is None:
|
||||
return 1
|
||||
|
||||
# 获取列表元素
|
||||
lst: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if lst is None or lst.elts is None:
|
||||
return 1
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = lst.elts
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 为每个元素生成 GEP + store
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
elem_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, elem_node, None, 0, trans)
|
||||
if elem_val is not None:
|
||||
idx_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, i)
|
||||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
|
||||
builder, arr_ty, elem_ty, array_alloca, idx_val)
|
||||
if elem_ptr is not None:
|
||||
# 类型转换(如 i32 → i8 截断)
|
||||
store_val: llvmlite.Value | t.CPtr = elem_val
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, elem_val, elem_ptr.Ty.Pointee)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr)
|
||||
i += 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class AnnAssignHandle(HandlesBase.Mixin):
|
||||
"""AnnAssign 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# PreScan - 预扫描 AnnAssign,为有类型注解的变量提前创建 alloca
|
||||
#
|
||||
# 返回新增的变量数
|
||||
# ============================================================
|
||||
def PreScan(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
if k != ast.ASTKind.AnnAssign:
|
||||
return 0
|
||||
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None or aa.target is None:
|
||||
return 0
|
||||
target: ast.AST | t.CPtr = aa.target
|
||||
if target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||||
if nm.id is None:
|
||||
return 0
|
||||
|
||||
# CDefine 注解: 不创建 alloca,但注册常量到全局表
|
||||
# 供后续 t.CArray[elem_ty, NAME] 编译期解析使用
|
||||
if is_cdefine_annotation(aa.annotation) != 0:
|
||||
pool_ps: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
val_ps: int = extract_cdefine_int_value(aa.value)
|
||||
HandlesType.register_cdefine_constant(pool_ps, nm.id, val_ps)
|
||||
return 0
|
||||
|
||||
# global/nonlocal 变量不需要局部 alloca
|
||||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||||
return 0
|
||||
if HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||||
return 0
|
||||
|
||||
# 模块级全局变量已由 handle_module_level_var 注册到模块作用域,
|
||||
# 不需要创建局部 alloca(否则会导致局部变量遮蔽全局变量)
|
||||
if HandlesVar.lookup_module_var(self.Trans.SymTab, nm.id) is not None:
|
||||
return 0
|
||||
|
||||
# 检查是否已存在
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if existing is not None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
|
||||
# 从 annotation 推断类型(修复:原硬编码 i32 导致 str 等类型错误)
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
annot: ast.AST | t.CPtr = aa.annotation
|
||||
if annot is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans)
|
||||
if resolved is None:
|
||||
# 尝试特化泛型类注解(如 list[str])
|
||||
# resolve_annotation_type 返回 None 可能是因为泛型类未特化
|
||||
if annot.kind() == ast.ASTKind.Subscript:
|
||||
sub_annot: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot)
|
||||
if sub_annot.value is not None and sub_annot.value.kind() == ast.ASTKind.Name:
|
||||
sub_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_annot.value)
|
||||
if sub_nm.id is not None:
|
||||
template_cd: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(sub_nm.id)
|
||||
if template_cd is not None:
|
||||
type_args_ps: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice(pool, sub_annot.slice)
|
||||
if type_args_ps is not None and type_args_ps.__len__() > 0:
|
||||
spec_name_ps: str = HandlesClassDef._specialize_generic_class(
|
||||
self.Trans, sub_nm.id, type_args_ps)
|
||||
if spec_name_ps is not None:
|
||||
resolved = HandlesType.resolve_annotation_type(
|
||||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans)
|
||||
if resolved is not None:
|
||||
var_ty = resolved
|
||||
|
||||
# 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间)
|
||||
HandlesStruct.ensure_struct_def_in_module(pool, self.Trans.Module, var_ty)
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, var_ty)
|
||||
if alloca is not None:
|
||||
if HandlesVar.define_var(
|
||||
self.Trans.SymTab, nm.id, alloca) == 0:
|
||||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||||
if annot is not None:
|
||||
cls_nm_ps: str = HandlesType.extract_class_name_from_annotation(
|
||||
annot, self.Trans._imported_modules)
|
||||
if cls_nm_ps is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
self.Trans.SymTab, nm.id, cls_nm_ps)
|
||||
# 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长)
|
||||
if _is_ptr_element_annotation(annot) != 0:
|
||||
HandlesVar.set_var_ptr_element(
|
||||
self.Trans.SymTab, nm.id)
|
||||
return 0
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# Handle - 翻译 AnnAssign 语句
|
||||
#
|
||||
# 返回新增的变量数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 AnnAssign(target=Name, annotation=..., value=expr)"""
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None:
|
||||
return 0
|
||||
|
||||
target: ast.AST | t.CPtr = aa.target
|
||||
if target is None or target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||||
if nm.id is None:
|
||||
return 0
|
||||
|
||||
# CDefine 注解: 编译期常量,不生成运行时代码
|
||||
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
|
||||
# 注: PreScan 已注册过,此处保证即使跳过 PreScan 也能正确注册
|
||||
if is_cdefine_annotation(aa.annotation) != 0:
|
||||
pool_cd: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
val_cd: int = extract_cdefine_int_value(aa.value)
|
||||
HandlesType.register_cdefine_constant(pool_cd, nm.id, val_cd)
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
|
||||
# 确定类型(从 annotation 推断)
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
annot: ast.AST | t.CPtr = aa.annotation
|
||||
if annot is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans)
|
||||
if resolved is not None:
|
||||
var_ty = resolved
|
||||
|
||||
# global 变量:写入模块作用域中的全局变量
|
||||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||||
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if mod_alloca is not None and aa.value is not None:
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, self.Trans)
|
||||
if rhs_val is not None:
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_alloca.Ty is not None:
|
||||
target_ty = mod_alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty)
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||||
return 0
|
||||
|
||||
# nonlocal 变量:通过闭包 env 写入
|
||||
if HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||||
if aa.value is not None:
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, self.Trans)
|
||||
if rhs_val is not None:
|
||||
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
|
||||
self.Trans, nm.id)
|
||||
if nl_ptr is not None:
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
rhs_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, i32_ty)
|
||||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
return 0
|
||||
|
||||
# 模块级全局变量(由 handle_module_level_var 注册到模块作用域)
|
||||
# 非函数内 global 声明,但变量已在模块作用域中(如模块级 t.CArray 初始化)
|
||||
mod_glob: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if mod_glob is not None:
|
||||
if aa.value is not None:
|
||||
# 列表字面量 → 逐元素 GEP + store 初始化数组
|
||||
if aa.value.kind() == ast.ASTKind.List:
|
||||
_init_global_array_from_list(
|
||||
builder, pool, mod, mod_glob, aa.value, self.Trans)
|
||||
else:
|
||||
rhs_val_mg: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, self.Trans)
|
||||
if rhs_val_mg is not None:
|
||||
target_ty_mg: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_glob.Ty is not None:
|
||||
target_ty_mg = mod_glob.Ty.Pointee
|
||||
if target_ty_mg is not None:
|
||||
rhs_val_mg = HandlesExpr.coerce_to_type(builder, rhs_val_mg, target_ty_mg)
|
||||
llvmlite.build_store(builder, rhs_val_mg, mod_glob)
|
||||
return 0
|
||||
|
||||
# 普通局部变量
|
||||
# 创建 alloca
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym(
|
||||
self.Trans.SymTab, pool, builder, nm.id, var_ty)
|
||||
if alloca is None:
|
||||
return 0
|
||||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||||
if annot is not None:
|
||||
cls_nm_hd: str = HandlesType.extract_class_name_from_annotation(
|
||||
annot, self.Trans._imported_modules)
|
||||
if cls_nm_hd is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
self.Trans.SymTab, nm.id, cls_nm_hd)
|
||||
# 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长)
|
||||
if _is_ptr_element_annotation(annot) != 0:
|
||||
HandlesVar.set_var_ptr_element(
|
||||
self.Trans.SymTab, nm.id)
|
||||
|
||||
new_vars: int = 0
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if existing is None:
|
||||
new_vars = 1
|
||||
|
||||
# 如果有初始值,store
|
||||
if aa.value is not None:
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aa.value,
|
||||
None, 0, self.Trans)
|
||||
if rhs_val is not None:
|
||||
# 类型转换:将 rhs_val 转换为 alloca 的 pointee 类型
|
||||
# 修复:整数字面量是 i32,但变量可能是 i8/i16/i64,需 trunc/sext
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if alloca.Ty is not None:
|
||||
target_ty = alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty)
|
||||
llvmlite.build_store(builder, rhs_val, alloca)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewAnnAssignHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewAnnAssignHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> AnnAssignHandle | t.CPtr:
|
||||
h: AnnAssignHandle | t.CPtr = pool.alloc(AnnAssignHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, AnnAssignHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,389 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
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.HandlesExpr as HandlesExpr
|
||||
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.StubMerger as StubMerger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAssign - Assign 语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 对应 TransPyC 的 class AssignHandle(BaseHandle):
|
||||
# @t.NoVTable 继承 Mixin 获得 Trans 字段(展平嵌入,无 vtable)
|
||||
# 通过 self.Trans 访问共享状态(Pool/Module/_cur_builder/SymTab/...)
|
||||
# 通过 self.Trans.ExprH / self.Trans.IfH 等访问其他 Handle
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class AssignHandle(HandlesBase.Mixin):
|
||||
"""Assign 语句处理器:继承 Mixin 获得 Trans 回指针 + 共享方法"""
|
||||
_CurrentClass: str # 模块私有状态
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
self._CurrentClass = None
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 Assign 语句,返回新增变量数(0 或 1)
|
||||
#
|
||||
# 对应 TransPyC AssignHandle._HandleAssignLlvm
|
||||
# 共享状态从 self.Trans 获取,无需 11 个参数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
|
||||
if asgn is None:
|
||||
VLogger.error("cast failed", "ASGN")
|
||||
return 0
|
||||
|
||||
targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets
|
||||
if targets is None:
|
||||
VLogger.error("targets is None", "ASGN")
|
||||
return 0
|
||||
|
||||
# 从 self.Trans 取共享状态(替代 11 个参数)
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
|
||||
# 翻译 RHS 值
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, asgn.value, None, 0, self.Trans)
|
||||
if rhs_val is None:
|
||||
# 增强错误信息:包含文件名 + lineno + AST 节点详情,便于定位
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None and asgn.value is not None:
|
||||
sha1: str = self.Trans.ModuleSha1
|
||||
val_kind: int = asgn.value.kind()
|
||||
val_line: t.CInt = asgn.value.lineno
|
||||
# 通过 sha1 查找文件名(人类可读)
|
||||
rel_path: str = None
|
||||
if sha1 is not None:
|
||||
rel_path = StubMerger.LookupSha1RelPath(sha1)
|
||||
# 根据 AST 节点类型提取详情
|
||||
if val_kind == ast.ASTKind.Attribute:
|
||||
at_nv: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(asgn.value)
|
||||
attr_nm: str = at_nv.attr
|
||||
target_nm: str = "?"
|
||||
if at_nv.value is not None:
|
||||
if at_nv.value.kind() == ast.ASTKind.Name:
|
||||
tn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_nv.value)
|
||||
target_nm = tn_nm.id
|
||||
if rel_path is not None:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: %s:%d '%s.%s' 属性访问失败",
|
||||
rel_path, val_line, target_nm, attr_nm)
|
||||
else:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: sha1=%s:%d '%s.%s' 属性访问失败",
|
||||
sha1, val_line, target_nm, attr_nm)
|
||||
elif val_kind == ast.ASTKind.Name:
|
||||
nm_nv: ast.Name | t.CPtr = (ast.Name | t.CPtr)(asgn.value)
|
||||
if rel_path is not None:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: %s:%d 变量 '%s' 未找到",
|
||||
rel_path, val_line, nm_nv.id)
|
||||
else:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: sha1=%s:%d 变量 '%s' 未找到",
|
||||
sha1, val_line, nm_nv.id)
|
||||
elif val_kind == ast.ASTKind.Call:
|
||||
cl_nv: ast.Call | t.CPtr = (ast.Call | t.CPtr)(asgn.value)
|
||||
func_nm: str = "?"
|
||||
if cl_nv.func is not None:
|
||||
if cl_nv.func.kind() == ast.ASTKind.Name:
|
||||
fn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl_nv.func)
|
||||
func_nm = fn_nm.id
|
||||
if rel_path is not None:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: %s:%d 调用 '%s(...)' 返回 None",
|
||||
rel_path, val_line, func_nm)
|
||||
else:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: sha1=%s:%d 调用 '%s(...)' 返回 None",
|
||||
sha1, val_line, func_nm)
|
||||
else:
|
||||
if rel_path is not None:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: %s:%d [kind=%d]",
|
||||
rel_path, val_line, val_kind)
|
||||
else:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"赋值右侧为 None: sha1=%s:%d [kind=%d]",
|
||||
sha1, val_line, val_kind)
|
||||
VLogger.error(fb, "ASGN")
|
||||
else:
|
||||
VLogger.error("赋值右侧为 None (asgn.value 为空)", "ASGN")
|
||||
return 0
|
||||
|
||||
new_vars: int = 0
|
||||
tn: t.CSizeT = targets.__len__()
|
||||
for ti in range(tn):
|
||||
target: ast.AST | t.CPtr = targets.get(ti)
|
||||
if target is None:
|
||||
continue
|
||||
|
||||
tk: int = target.kind()
|
||||
|
||||
# Subscript 赋值: arr[i] = val / ptr[i] = val / list[i] = val
|
||||
if tk == ast.ASTKind.Subscript:
|
||||
# 检查是否是 list[T] 类型的 Subscript(泛型类不注册 struct)
|
||||
# list 的 subscript 赋值走 __setitem__ 内联路径
|
||||
list_obj: llvmlite.Value | t.CPtr = HandlesExpr.is_list_subscript(
|
||||
target, self.Trans)
|
||||
if list_obj is not None:
|
||||
# list[T] 类型: 内联生成 __setitem__ 逻辑
|
||||
sub_node: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(target)
|
||||
if sub_node is not None and sub_node.slice is not None:
|
||||
list_idx_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, sub_node.slice, None, 0, self.Trans)
|
||||
if list_idx_val is not None:
|
||||
HandlesExpr.list_setitem_inline(
|
||||
builder, pool, list_obj, list_idx_val, rhs_val)
|
||||
continue
|
||||
# 普通 Subscript 赋值
|
||||
elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr(
|
||||
builder, pool, mod, target, self.Trans)
|
||||
if elem_ptr is not None:
|
||||
store_val: llvmlite.Value | t.CPtr = rhs_val
|
||||
if elem_ptr.Ty is not None:
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = elem_ptr.Ty.Pointee
|
||||
if elem_ty is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, elem_ty)
|
||||
llvmlite.build_store(builder, store_val, elem_ptr)
|
||||
else:
|
||||
# get_subscript_ptr 返回 None: 尝试 __setitem__ 运算符重载
|
||||
# 适用于自定义类(如 hashtable[key]=val → hashtable.__setitem__(key, val))
|
||||
sub_asgn: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(target)
|
||||
setitem_done: int = 0
|
||||
if sub_asgn is not None and sub_asgn.value is not None:
|
||||
if sub_asgn.value.kind() == ast.ASTKind.Name:
|
||||
sub_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_asgn.value)
|
||||
if sub_nm.id is not None:
|
||||
sub_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
self.Trans.SymTab, sub_nm.id)
|
||||
if sub_alloca is not None and sub_alloca.Ty is not None:
|
||||
if HandlesExpr.is_ptr_type(sub_alloca.Ty) != 0:
|
||||
sub_pointee: llvmlite.LLVMType | t.CPtr = sub_alloca.Ty.Pointee
|
||||
if sub_pointee is not None:
|
||||
cls_nm_set: str = HandlesStruct.get_class_name_by_type(pool, sub_pointee)
|
||||
obj_val_set: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, sub_pointee, sub_alloca)
|
||||
# 指针类型变量 (X|t.CPtr): sub_pointee 是 Ptr(Struct),
|
||||
# 需 load 获取 Ptr(Struct) 再检查 inner struct
|
||||
if cls_nm_set is None and obj_val_set is not None:
|
||||
if HandlesExpr.is_ptr_type(sub_pointee) != 0:
|
||||
inner_ty_set: llvmlite.LLVMType | t.CPtr = sub_pointee.Pointee
|
||||
if inner_ty_set is not None:
|
||||
cls_nm_set = HandlesStruct.get_class_name_by_type(pool, inner_ty_set)
|
||||
if cls_nm_set is not None and obj_val_set is not None:
|
||||
key_val_set: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, sub_asgn.slice, None, 0, self.Trans)
|
||||
if key_val_set is not None:
|
||||
arg_vals_set: t.CSizeT | t.CPtr = pool.alloc(16)
|
||||
if arg_vals_set is not None:
|
||||
arg_vals_set[0] = t.CSizeT(key_val_set)
|
||||
arg_vals_set[1] = t.CSizeT(rhs_val)
|
||||
HandlesExprCall._call_method_on_ptr(
|
||||
pool, builder, mod, cls_nm_set, "__setitem__",
|
||||
obj_val_set, arg_vals_set, 2, self.Trans)
|
||||
setitem_done = 1
|
||||
elif sub_asgn.value.kind() == ast.ASTKind.Attribute:
|
||||
# self._ht[key] = val → self._ht.__setitem__(key, val)
|
||||
# 通过 get_attribute_ptr 获取字段指针,再调用 __setitem__
|
||||
field_ptr_set: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
|
||||
builder, pool, mod, sub_asgn.value, self.Trans)
|
||||
if field_ptr_set is not None and field_ptr_set.Ty is not None:
|
||||
if HandlesExpr.is_ptr_type(field_ptr_set.Ty) != 0:
|
||||
field_pointee_set: llvmlite.LLVMType | t.CPtr = field_ptr_set.Ty.Pointee
|
||||
if field_pointee_set is not None:
|
||||
cls_nm_attr: str = HandlesStruct.get_class_name_by_type(pool, field_pointee_set)
|
||||
obj_val_attr: llvmlite.Value | t.CPtr = field_ptr_set
|
||||
# field_ptr 是 Ptr(Ptr(Struct)) (X|t.CPtr 字段):
|
||||
# load 解引用获取 Ptr(Struct)
|
||||
if cls_nm_attr is None and HandlesExpr.is_ptr_type(field_pointee_set) != 0:
|
||||
inner_struct_attr: llvmlite.LLVMType | t.CPtr = field_pointee_set.Pointee
|
||||
if inner_struct_attr is not None:
|
||||
cls_nm_attr = HandlesStruct.get_class_name_by_type(pool, inner_struct_attr)
|
||||
if cls_nm_attr is not None:
|
||||
obj_val_attr = llvmlite.build_load(
|
||||
builder, field_pointee_set, field_ptr_set)
|
||||
if cls_nm_attr is not None and obj_val_attr is not None:
|
||||
key_val_attr: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, sub_asgn.slice, None, 0, self.Trans)
|
||||
if key_val_attr is not None:
|
||||
arg_vals_attr: t.CSizeT | t.CPtr = pool.alloc(16)
|
||||
if arg_vals_attr is not None:
|
||||
arg_vals_attr[0] = t.CSizeT(key_val_attr)
|
||||
arg_vals_attr[1] = t.CSizeT(rhs_val)
|
||||
HandlesExprCall._call_method_on_ptr(
|
||||
pool, builder, mod, cls_nm_attr, "__setitem__",
|
||||
obj_val_attr, arg_vals_attr, 2, self.Trans)
|
||||
setitem_done = 1
|
||||
if setitem_done == 0:
|
||||
# 通用 fallback: 翻译 sub.value 并尝试 __setitem__ 或直接 GEP+store
|
||||
# 处理 Name/Attribute 之外的节点以及 SymTab 查找失败的情况
|
||||
if sub_asgn is not None and sub_asgn.value is not None:
|
||||
obj_val_gen: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, sub_asgn.value, None, 0, self.Trans)
|
||||
key_val_gen: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, sub_asgn.slice, None, 0, self.Trans)
|
||||
if obj_val_gen is not None and key_val_gen is not None \
|
||||
and obj_val_gen.Ty is not None:
|
||||
# 内联 _get_custom_struct_cls_nm 逻辑(避免依赖新函数)
|
||||
cls_nm_gen: str = HandlesStruct.get_class_name_by_type(
|
||||
pool, obj_val_gen.Ty)
|
||||
if cls_nm_gen is None and HandlesExpr.is_ptr_type(obj_val_gen.Ty) != 0:
|
||||
inner_gen: llvmlite.LLVMType | t.CPtr = obj_val_gen.Ty.Pointee
|
||||
if inner_gen is not None:
|
||||
cls_nm_gen = HandlesStruct.get_class_name_by_type(pool, inner_gen)
|
||||
if cls_nm_gen is not None:
|
||||
# 自定义结构体: 调用 __setitem__
|
||||
arg_vals_gen: t.CSizeT | t.CPtr = pool.alloc(16)
|
||||
if arg_vals_gen is not None:
|
||||
arg_vals_gen[0] = t.CSizeT(key_val_gen)
|
||||
arg_vals_gen[1] = t.CSizeT(rhs_val)
|
||||
HandlesExprCall._call_method_on_ptr(
|
||||
pool, builder, mod, cls_nm_gen, "__setitem__",
|
||||
obj_val_gen, arg_vals_gen, 2, self.Trans)
|
||||
setitem_done = 1
|
||||
else:
|
||||
# 非自定义结构体: 直接 GEP + store
|
||||
# 处理 get_subscript_ptr 因边界情况返回 None 的指针下标
|
||||
if HandlesExpr.is_ptr_type(obj_val_gen.Ty) != 0:
|
||||
elem_gen: llvmlite.LLVMType | t.CPtr = obj_val_gen.Ty.Pointee
|
||||
if elem_gen is not None:
|
||||
store_val_gen: llvmlite.Value | t.CPtr = rhs_val
|
||||
elem_ptr_gen: llvmlite.Value | t.CPtr = None
|
||||
match elem_gen:
|
||||
case llvmlite.LLVMType.Array(arr_elem_gen, _):
|
||||
elem_ptr_gen = llvmlite.build_gep_array(
|
||||
builder, elem_gen, arr_elem_gen,
|
||||
obj_val_gen, key_val_gen)
|
||||
case _:
|
||||
elem_ptr_gen = llvmlite.build_gep(
|
||||
builder, elem_gen, obj_val_gen, key_val_gen)
|
||||
if elem_ptr_gen is not None and elem_ptr_gen.Ty is not None:
|
||||
pt_gen: llvmlite.LLVMType | t.CPtr = elem_ptr_gen.Ty.Pointee
|
||||
if pt_gen is not None:
|
||||
store_val_gen = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, pt_gen)
|
||||
llvmlite.build_store(builder, store_val_gen, elem_ptr_gen)
|
||||
setitem_done = 1
|
||||
if setitem_done == 0:
|
||||
sub_vk: int = sub_asgn.value.kind()
|
||||
if setitem_done == 0:
|
||||
HandlesType.fatal_error(target, "subscript ptr is None")
|
||||
continue
|
||||
|
||||
# Attribute 赋值: obj.field = val
|
||||
if tk == ast.ASTKind.Attribute:
|
||||
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
|
||||
builder, pool, mod, target, self.Trans)
|
||||
if field_ptr is not None:
|
||||
# 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64)
|
||||
store_val: llvmlite.Value | t.CPtr = rhs_val
|
||||
if field_ptr.Ty is not None:
|
||||
field_ty: llvmlite.LLVMType | t.CPtr = field_ptr.Ty.Pointee
|
||||
if field_ty is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, field_ty)
|
||||
llvmlite.build_store(builder, store_val, field_ptr)
|
||||
else:
|
||||
# 构造详细错误信息
|
||||
attr_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(target)
|
||||
attr_name: str = "(unknown)"
|
||||
obj_name: str = "(unknown)"
|
||||
if attr_node is not None:
|
||||
attr_name = attr_node.attr
|
||||
if attr_node.value is not None and attr_node.value.kind() == ast.ASTKind.Name:
|
||||
obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(attr_node.value)
|
||||
obj_name = obj_nm.id
|
||||
err_buf: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if err_buf is not None:
|
||||
viperlib.snprintf(err_buf, 256,
|
||||
"attribute ptr is None: %s.%s",
|
||||
obj_name, attr_name)
|
||||
HandlesType.fatal_error(target, err_buf)
|
||||
else:
|
||||
HandlesType.fatal_error(target, "attribute ptr is None")
|
||||
continue
|
||||
|
||||
# Name 赋值: var = val
|
||||
if tk == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||||
if nm.id is not None:
|
||||
# global 变量:写入模块作用域中的全局变量
|
||||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||||
mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if mod_alloca is not None:
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if mod_alloca.Ty is not None:
|
||||
target_ty = mod_alloca.Ty.Pointee
|
||||
if target_ty is not None:
|
||||
rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty)
|
||||
llvmlite.build_store(builder, rhs_val, mod_alloca)
|
||||
continue
|
||||
|
||||
# nonlocal 变量:通过闭包 env 写入
|
||||
if HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||||
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
|
||||
self.Trans, nm.id)
|
||||
if nl_ptr is not None:
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
rhs_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, i32_ty)
|
||||
llvmlite.build_store(builder, rhs_coerced, nl_ptr)
|
||||
continue
|
||||
|
||||
# 普通局部变量
|
||||
alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym(
|
||||
self.Trans.SymTab, pool, builder, nm.id, rhs_val.Ty)
|
||||
if alloca is not None:
|
||||
# 按 alloca 类型对值进行转换(如 double → float)
|
||||
store_val: llvmlite.Value | t.CPtr = rhs_val
|
||||
if alloca.Ty is not None:
|
||||
alloca_ty: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee
|
||||
if alloca_ty is not None:
|
||||
store_val = HandlesExpr.coerce_to_type(
|
||||
builder, rhs_val, alloca_ty)
|
||||
llvmlite.build_store(builder, store_val, alloca)
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if existing is None:
|
||||
new_vars += 1
|
||||
else:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "alloca failed for %s", nm.id)
|
||||
VLogger.error(fb, "ASGN")
|
||||
|
||||
return new_vars
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewAssignHandle - 工厂函数:分配并初始化 AssignHandle
|
||||
# ============================================================
|
||||
def NewAssignHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> AssignHandle | t.CPtr:
|
||||
h: AssignHandle | t.CPtr = pool.alloc(AssignHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, AssignHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,315 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import stdio
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
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.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesAugAssign - 增强赋值语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 处理 += -= *= /= %= &= |= ^= <<= >>=
|
||||
# 流程: load target → apply binop → store result
|
||||
#
|
||||
# 支持 local/global/nonlocal 三种变量作用域
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class AugAssignHandle(HandlesBase.Mixin):
|
||||
"""增强赋值处理器 (+=, -=, *=, etc.):继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 AugAssign 语句,返回新增变量数(始终为 0)
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译增强赋值语句 (x += 1, y -= 2, etc.)"""
|
||||
if node is None:
|
||||
return 0
|
||||
|
||||
aug: ast.AugAssign | t.CPtr = (ast.AugAssign | t.CPtr)(node)
|
||||
if aug is None:
|
||||
return 0
|
||||
|
||||
target: ast.AST | t.CPtr = aug.target
|
||||
if target is None:
|
||||
return 0
|
||||
|
||||
tk: int = target.kind()
|
||||
|
||||
# Attribute 目标: self.field += 1
|
||||
# 流程: get_attribute_ptr → load → binop → store
|
||||
if tk == ast.ASTKind.Attribute:
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
|
||||
# 1. 获取字段指针
|
||||
field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr(
|
||||
builder, pool, mod, target, self.Trans)
|
||||
if field_ptr is None:
|
||||
VLogger.error("attribute ptr is None", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 2. 确定字段类型并加载当前值
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if field_ptr.Ty is not None:
|
||||
target_ty = field_ptr.Ty.Pointee
|
||||
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, target_ty, field_ptr)
|
||||
if cur_val is None:
|
||||
VLogger.error("cannot load attribute", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 3. 翻译 RHS 值
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||||
if rhs_val is None:
|
||||
VLogger.error("rhs is None", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 4. 应用二元运算
|
||||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||||
pool, builder, aug.op, cur_val, rhs_val)
|
||||
if result is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "binop failed for attr op=%d", aug.op)
|
||||
VLogger.error(fb, "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 5. 类型对齐并存储
|
||||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||||
if result is None:
|
||||
return 0
|
||||
llvmlite.build_store(builder, result, field_ptr)
|
||||
return 0
|
||||
|
||||
# Subscript 目标: self.state[i] += x / arr[i] += x
|
||||
# 流程: get_subscript_ptr → load → binop → store
|
||||
if tk == ast.ASTKind.Subscript:
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
|
||||
# 1. 获取元素指针
|
||||
elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr(
|
||||
builder, pool, mod, target, self.Trans)
|
||||
if elem_ptr is None:
|
||||
VLogger.error("subscript ptr is None", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 2. 确定元素类型并加载当前值
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None:
|
||||
target_ty = elem_ptr.Ty.Pointee
|
||||
cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
builder, target_ty, elem_ptr)
|
||||
if cur_val is None:
|
||||
VLogger.error("cannot load subscript element", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 3. 翻译 RHS 值
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||||
if rhs_val is None:
|
||||
VLogger.error("rhs is None", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 4. 应用二元运算
|
||||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||||
pool, builder, aug.op, cur_val, rhs_val)
|
||||
if result is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "binop failed for sub op=%d", aug.op)
|
||||
VLogger.error(fb, "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 5. 类型对齐并存储
|
||||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||||
if result is None:
|
||||
return 0
|
||||
llvmlite.build_store(builder, result, elem_ptr)
|
||||
return 0
|
||||
|
||||
if tk != ast.ASTKind.Name:
|
||||
VLogger.error("only Name/Attribute/Subscript target supported", "AUGASGN")
|
||||
return 0
|
||||
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||||
if nm is None or nm.id is None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
|
||||
# 1. 确定变量作用域类型: 0=local, 1=global, 2=nonlocal
|
||||
scope_type: int = 0
|
||||
if HT.is_global_name(self.Trans, nm.id) != 0:
|
||||
scope_type = 1
|
||||
elif HT.is_nonlocal_name(self.Trans, nm.id) != 0:
|
||||
scope_type = 2
|
||||
|
||||
# 2. 加载当前值
|
||||
cur_val: llvmlite.Value | t.CPtr = None
|
||||
target_alloca: llvmlite.Value | t.CPtr = None
|
||||
target_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
|
||||
if scope_type == 1:
|
||||
# global 变量
|
||||
target_alloca = HandlesVar.lookup_module_var(
|
||||
self.Trans.SymTab, nm.id)
|
||||
if target_alloca is not None:
|
||||
if target_alloca.Ty is not None:
|
||||
target_ty = target_alloca.Ty.Pointee
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||||
elif scope_type == 2:
|
||||
# nonlocal 变量(通过闭包 env)
|
||||
cur_val = HandlesNonlocal.load_nonlocal_var(self.Trans, nm.id)
|
||||
if cur_val is not None:
|
||||
target_ty = cur_val.Ty
|
||||
else:
|
||||
# 普通局部变量
|
||||
target_alloca = HandlesVar.lookup_var(self.Trans.SymTab, nm.id)
|
||||
if target_alloca is not None:
|
||||
if target_alloca.Ty is not None:
|
||||
target_ty = target_alloca.Ty.Pointee
|
||||
cur_val = llvmlite.build_load(builder, target_ty, target_alloca)
|
||||
|
||||
if cur_val is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "cannot load target %s", nm.id)
|
||||
VLogger.error(fb, "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 3. 翻译 RHS 值
|
||||
rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, aug.value, None, 0, self.Trans)
|
||||
if rhs_val is None:
|
||||
VLogger.error("rhs is None", "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 4. 类型对齐 + 应用二元运算
|
||||
# 注意: AugAssign 不走运算符重载(语义上需要 __iadd__ 而非 __add__)
|
||||
result: llvmlite.Value | t.CPtr = _apply_aug_op(
|
||||
pool, builder, aug.op, cur_val, rhs_val)
|
||||
if result is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "binop failed for op=%d", aug.op)
|
||||
VLogger.error(fb, "AUGASGN")
|
||||
return 0
|
||||
|
||||
# 5. 存储结果
|
||||
result = HandlesExpr.coerce_to_type(builder, result, target_ty)
|
||||
if result is None:
|
||||
return 0
|
||||
|
||||
if scope_type == 1:
|
||||
# global 变量
|
||||
if target_alloca is not None:
|
||||
llvmlite.build_store(builder, result, target_alloca)
|
||||
elif scope_type == 2:
|
||||
# nonlocal 变量
|
||||
nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr(
|
||||
self.Trans, nm.id)
|
||||
if nl_ptr is not None:
|
||||
llvmlite.build_store(builder, result, nl_ptr)
|
||||
else:
|
||||
# 普通局部变量
|
||||
if target_alloca is not None:
|
||||
llvmlite.build_store(builder, result, target_alloca)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _apply_aug_op - 应用增强赋值的二元运算
|
||||
#
|
||||
# 支持指针算术: ptr += int / ptr -= int
|
||||
# 整数运算自动类型提升
|
||||
# ============================================================
|
||||
def _apply_aug_op(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
op: int,
|
||||
lhs: llvmlite.Value | t.CPtr,
|
||||
rhs: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""应用增强赋值的二元运算(指针算术 + 整数运算)"""
|
||||
lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty)
|
||||
rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty)
|
||||
|
||||
# 指针算术: ptr += int / ptr -= int
|
||||
if lhs_bits == 0 and rhs_bits != 0:
|
||||
if op == ast.OpKind.Add or op == ast.OpKind.Sub:
|
||||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||||
ptr_as_int: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, lhs, i64_ty)
|
||||
int_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, rhs, i64_ty)
|
||||
if ptr_as_int is None or int_val is None:
|
||||
return None
|
||||
if op == ast.OpKind.Add:
|
||||
result: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, ptr_as_int, int_val)
|
||||
else:
|
||||
result = llvmlite.build_sub(builder, ptr_as_int, int_val)
|
||||
if result is None:
|
||||
return None
|
||||
return llvmlite.build_inttoptr(builder, result, lhs.Ty)
|
||||
return None
|
||||
|
||||
# 整数运算:类型提升
|
||||
if lhs_bits > rhs_bits and rhs_bits > 0:
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty)
|
||||
elif rhs_bits > lhs_bits and lhs_bits > 0:
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty)
|
||||
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_add(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Sub:
|
||||
return llvmlite.build_sub(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mult:
|
||||
return llvmlite.build_mul(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Div:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.FloorDiv:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mod:
|
||||
return llvmlite.build_srem(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitAnd:
|
||||
return llvmlite.build_and(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitOr:
|
||||
return llvmlite.build_or(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitXor:
|
||||
return llvmlite.build_xor(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.LShift:
|
||||
return llvmlite.build_shl(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.RShift:
|
||||
return llvmlite.build_ashr(builder, lhs, rhs)
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewAugAssignHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewAugAssignHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> AugAssignHandle | t.CPtr:
|
||||
h: AugAssignHandle | t.CPtr = pool.alloc(AugAssignHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, AugAssignHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,262 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import string
|
||||
import viperlib
|
||||
import memhub
|
||||
import hashtable
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeKind - 类型种类枚举
|
||||
#
|
||||
# 替代 TransPyC 中 CType.position frozenset 的元属性系统。
|
||||
# 每个 TypeInfo 通过 Kind 字段标记其种类,避免 Python ClassVar 反射。
|
||||
# ============================================================
|
||||
class TypeKind(t.CEnum):
|
||||
Basic: t.State # 基本类型(int/char/float/double/bool 等)
|
||||
Pointer: t.State # 指针(T*)— 指针层数由 TypeInfo.PtrCount 表达
|
||||
Struct: t.State # 结构体/类
|
||||
Union: t.State # 联合体
|
||||
Enum: t.State # 枚举
|
||||
Typedef: t.State # 类型别名
|
||||
Function: t.State # 函数指针
|
||||
Array: t.State # 数组 T[N]
|
||||
Void: t.State # void
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeInfo - 类型信息结构
|
||||
#
|
||||
# 设计原则(相对 TransPyC CTypeInfo 的简化):
|
||||
# - POD 数据结构,无虚函数,无 Python 元特性(ClassVar/Generic/frozenset)
|
||||
# - 通过 mbuddy 分配,调用方管理生命周期(参考 llvmlite Module 模式)
|
||||
# - 通过 Kind 枚举代替 position frozenset
|
||||
# - PtrCount 表达指针层数(0=非指针, 1=T*, 2=T**)
|
||||
# - IsSigned 三态:-1=不适用(void/float), 0=unsigned, 1=signed
|
||||
#
|
||||
# 字段布局(8 字段):
|
||||
# Kind : i32 类型种类(TypeKind 枚举值)
|
||||
# Name : i8* 类型名(如 'int', 'CInt', 'MyStruct'),可能为 None
|
||||
# Size : i32 位宽(0=void/未知;int=32, char=8, double=64, long long=64)
|
||||
# Align : i32 对齐字节数(0=默认)
|
||||
# IsSigned : i32 -1=N/A, 0=unsigned, 1=signed
|
||||
# PtrCount : i32 指针层数
|
||||
# IsConst : i32 const 限定符(0/1)
|
||||
# IsVolatile : i32 volatile 限定符(0/1)
|
||||
#
|
||||
# 注意:Size 使用位宽(bit width)而非字节数,与 LLVM IR 的 i{N} 和
|
||||
# TransPyC CType.Size 约定一致(CInt.Size=32, CChar.Size=8)。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class TypeInfo:
|
||||
Kind: int
|
||||
Name: str
|
||||
Size: int
|
||||
Align: int
|
||||
IsSigned: int
|
||||
PtrCount: int
|
||||
IsConst: int
|
||||
IsVolatile: int
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeRegistry - 类型注册表
|
||||
#
|
||||
# 维护 name(str) → TypeInfo* 映射,基于 HashTable 实现 O(1) 查找。
|
||||
# 替代 TransPyC CTypeRegistry 的 _name_to_class dict。
|
||||
# 内置基本类型(int/char/void/...)由 InitBasicTypes 注册。
|
||||
# ============================================================
|
||||
class TypeRegistry:
|
||||
_ht: hashtable.HashTable | t.CPtr
|
||||
__mbuddy__: memhub.MemBuddy | t.CPtr
|
||||
|
||||
def Register(self, ti: TypeInfo | t.CPtr) -> int:
|
||||
"""注册一个 TypeInfo。ti.Name 字段必须已设置。
|
||||
|
||||
Returns:
|
||||
1 表示成功,0 表示失败(ti 为 None 或 Name 为 None)
|
||||
"""
|
||||
if ti is None:
|
||||
return 0
|
||||
if ti.Name is None:
|
||||
return 0
|
||||
self._ht[ti.Name] = ti
|
||||
return 1
|
||||
|
||||
def Lookup(self, name: str) -> TypeInfo | t.CPtr:
|
||||
"""按名称查找 TypeInfo。
|
||||
|
||||
Returns:
|
||||
找到返回 TypeInfo*,找不到返回 None
|
||||
"""
|
||||
if name is None:
|
||||
return None
|
||||
return self._ht[name]
|
||||
|
||||
def Has(self, name: str) -> int:
|
||||
"""检查类型是否已注册。"""
|
||||
if name is None:
|
||||
return 0
|
||||
return name in self._ht
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeInfo - 工厂函数:分配并初始化一个 TypeInfo
|
||||
#
|
||||
# 默认值:Kind=Basic, IsSigned=-1, 其余=0/None
|
||||
# ============================================================
|
||||
def NewTypeInfo(pool: memhub.MemBuddy | t.CPtr) -> TypeInfo | t.CPtr:
|
||||
ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__())
|
||||
if ptr is None:
|
||||
return None
|
||||
string.memset(ptr, 0, TypeInfo.__sizeof__())
|
||||
ptr.Kind = TypeKind.Basic
|
||||
ptr.IsSigned = -1
|
||||
return ptr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewTypeRegistry - 工厂函数:创建类型注册表
|
||||
# ============================================================
|
||||
def NewTypeRegistry(pool: memhub.MemBuddy | t.CPtr) -> TypeRegistry | t.CPtr:
|
||||
ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__())
|
||||
if ptr is None:
|
||||
return None
|
||||
string.memset(ptr, 0, TypeRegistry.__sizeof__())
|
||||
ptr.__mbuddy__ = pool
|
||||
ptr._ht = hashtable.HashTable(pool)
|
||||
return ptr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TypeToLLVM - 将 TypeInfo 转换为 LLVM IR 类型字符串
|
||||
#
|
||||
# 规则:
|
||||
# - Kind == Void 或 (Size==0 且 IsSigned==-1 且 PtrCount==0) → "void"
|
||||
# - void 有 PtrCount > 0 → "i8" + PtrCount 个 "*"
|
||||
# - IsSigned == -1 且 Size > 0 → 浮点: half/float/double/fp128
|
||||
# - IsSigned != -1 且 Size > 0 → 整数: i{Size}
|
||||
# - 未知 → "i8*"
|
||||
#
|
||||
# Args:
|
||||
# buf: 输出缓冲区(i8*)
|
||||
# buf_size: 缓冲区容量
|
||||
# ti: TypeInfo 指针
|
||||
#
|
||||
# Returns:
|
||||
# 写入的字符数(不含 NUL),失败返回 -1
|
||||
# ============================================================
|
||||
def TypeToLLVM(buf: t.CChar | t.CPtr, buf_size: t.CSizeT,
|
||||
ti: TypeInfo | t.CPtr) -> int:
|
||||
if buf is None:
|
||||
return -1
|
||||
if ti is None:
|
||||
return -1
|
||||
if buf_size == 0:
|
||||
return -1
|
||||
|
||||
# 判定 void
|
||||
is_void: int = 0
|
||||
if ti.Kind == TypeKind.Void:
|
||||
is_void = 1
|
||||
elif ti.Size == 0 and ti.IsSigned == -1 and ti.PtrCount == 0:
|
||||
is_void = 1
|
||||
|
||||
# 写入 base 类型字符串到 buf
|
||||
base_len: int = 0
|
||||
if is_void == 1:
|
||||
if ti.PtrCount == 0:
|
||||
# "void"
|
||||
if buf_size < 5:
|
||||
return -1
|
||||
string.strcpy(buf, "void")
|
||||
base_len = 4
|
||||
else:
|
||||
# void* → i8*(LLVM 中 void* 表示为 i8*)
|
||||
if buf_size < 4:
|
||||
return -1
|
||||
string.strcpy(buf, "i8")
|
||||
base_len = 2
|
||||
elif ti.IsSigned == -1:
|
||||
# 浮点
|
||||
if ti.Size == 16:
|
||||
if buf_size < 5:
|
||||
return -1
|
||||
string.strcpy(buf, "half")
|
||||
base_len = 4
|
||||
elif ti.Size == 32:
|
||||
if buf_size < 6:
|
||||
return -1
|
||||
string.strcpy(buf, "float")
|
||||
base_len = 5
|
||||
elif ti.Size == 64:
|
||||
if buf_size < 7:
|
||||
return -1
|
||||
string.strcpy(buf, "double")
|
||||
base_len = 6
|
||||
elif ti.Size == 128:
|
||||
if buf_size < 6:
|
||||
return -1
|
||||
string.strcpy(buf, "fp128")
|
||||
base_len = 5
|
||||
else:
|
||||
# 未知浮点尺寸 → double 兜底
|
||||
if buf_size < 7:
|
||||
return -1
|
||||
string.strcpy(buf, "double")
|
||||
base_len = 6
|
||||
else:
|
||||
# 整数: i{Size},用 snprintf 安全写入
|
||||
if ti.Size <= 0:
|
||||
# 无效尺寸 → i8 兜底
|
||||
if buf_size < 4:
|
||||
return -1
|
||||
string.strcpy(buf, "i8")
|
||||
base_len = 2
|
||||
else:
|
||||
viperlib.snprintf(buf, buf_size, "i%d", ti.Size)
|
||||
base_len = string.strlen(buf)
|
||||
|
||||
# 追加 PtrCount 个 "*"
|
||||
if base_len + ti.PtrCount + 1 > buf_size:
|
||||
return -1
|
||||
pos: int = base_len
|
||||
for i in range(ti.PtrCount):
|
||||
buf[pos] = '*'
|
||||
pos += 1
|
||||
buf[pos] = 0
|
||||
return pos
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Mixin - 所有 Handle 的非多态基类(对应 TransPyC 的 BaseHandle)
|
||||
#
|
||||
# @t.NoVTable 继承:字段展平嵌入子类,无 vtable 开销(对应 C++ 非多态继承)。
|
||||
# 子类继承 Trans 字段 + 共享工具方法,编译器自动生成子类方法包装
|
||||
# (self bitcast 为父类指针后调用),子类可直接调用继承的方法。
|
||||
#
|
||||
# 用法:
|
||||
# @t.NoVTable
|
||||
# class AssignHandle(Mixin):
|
||||
# _CurrentClass: str
|
||||
# def __init__(self, trans):
|
||||
# self.InitMixin(trans)
|
||||
# self._CurrentClass = None
|
||||
# def Handle(self, node) -> int:
|
||||
# rhs = self.Trans.ExprH.HandleValue(node.value)
|
||||
# ...
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Mixin:
|
||||
"""所有 Handle 的非多态基类:持有 Translator 回指针 + 共享委托方法"""
|
||||
Trans: HT.Translator | t.CPtr
|
||||
|
||||
def InitMixin(self, trans: HT.Translator | t.CPtr) -> int:
|
||||
"""初始化 Mixin 字段(子类 __init__ 中调用)"""
|
||||
self.Trans = trans
|
||||
return 0
|
||||
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: t.CVoid | t.CPtr
|
||||
@@ -1,230 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesBody - 语句分派(trans 单参模式,全方法调用)
|
||||
#
|
||||
# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。
|
||||
# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 语句翻译分派
|
||||
# ============================================================
|
||||
def translate_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译单条语句,返回新增的变量数"""
|
||||
if node is None:
|
||||
return 0
|
||||
k: int = node.kind()
|
||||
|
||||
if k == ast.ASTKind.Expr:
|
||||
return translate_expr_stmt(trans, node)
|
||||
elif k == ast.ASTKind.Assign:
|
||||
return trans.AssignH.Handle(node)
|
||||
elif k == ast.ASTKind.AnnAssign:
|
||||
return trans.AnnAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.FunctionDef:
|
||||
# 嵌套函数定义:提升为顶层函数 + 创建闭包
|
||||
return HandlesFunctions.translate_nested_function_def(trans, node)
|
||||
elif k == ast.ASTKind.Return:
|
||||
return trans.ReturnH.Handle(node)
|
||||
elif k == ast.ASTKind.If:
|
||||
return trans.IfH.Handle(node)
|
||||
elif k == ast.ASTKind.While:
|
||||
return trans.WhileH.Handle(node)
|
||||
elif k == ast.ASTKind.AugAssign:
|
||||
return trans.AugAssignH.Handle(node)
|
||||
elif k == ast.ASTKind.For:
|
||||
return trans.ForH.Handle(node)
|
||||
elif k == ast.ASTKind.ClassDef:
|
||||
return HandlesClassDef.translate_class_def(trans, node)
|
||||
elif k == ast.ASTKind.Import:
|
||||
return trans.ImportsH.HandleImport(node)
|
||||
elif k == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(node)
|
||||
return trans.ImportsH.HandleImportFromNames(node)
|
||||
elif k == ast.ASTKind.Global:
|
||||
return translate_global(trans, node)
|
||||
elif k == ast.ASTKind.Nonlocal:
|
||||
return translate_nonlocal(trans, node)
|
||||
elif k == ast.ASTKind.Pass:
|
||||
return 0
|
||||
elif k == ast.ASTKind.Break:
|
||||
return translate_break(trans)
|
||||
elif k == ast.ASTKind.Continue:
|
||||
return translate_continue(trans)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 Global 语句: global x, y
|
||||
#
|
||||
# 将 names 中的变量名加入 _global_names 集合
|
||||
# ============================================================
|
||||
def translate_global(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 global 语句:记录 global 变量名"""
|
||||
gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node)
|
||||
if gn is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = gn.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
HT.add_global_name(trans, nm.id)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 Nonlocal 语句: nonlocal x, y
|
||||
#
|
||||
# 将 names 中的变量名加入 _nonlocal_names 集合
|
||||
# ============================================================
|
||||
def translate_nonlocal(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 nonlocal 语句:记录 nonlocal 变量名"""
|
||||
nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node)
|
||||
if nl is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = nl.names
|
||||
if names is None:
|
||||
return 0
|
||||
n: t.CSizeT = names.__len__()
|
||||
for i in range(n):
|
||||
nm_node: ast.AST | t.CPtr = names.get(i)
|
||||
if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
|
||||
if nm.id is not None:
|
||||
HT.add_nonlocal_name(trans, nm.id)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译表达式语句 Expr(value=Call(...))
|
||||
# ============================================================
|
||||
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译表达式语句(printf 调用等)"""
|
||||
ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
|
||||
if ex is None:
|
||||
return 0
|
||||
call_node: ast.AST | t.CPtr = ex.value
|
||||
if call_node is None:
|
||||
return 0
|
||||
ck: int = call_node.kind()
|
||||
if ck != ast.ASTKind.Call:
|
||||
return 0
|
||||
|
||||
cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node)
|
||||
func_node: ast.AST | t.CPtr = cl.func
|
||||
if func_node is None:
|
||||
return 0
|
||||
|
||||
func_name: str = HandlesExpr.get_func_name(func_node)
|
||||
if func_name is None:
|
||||
return 0
|
||||
|
||||
# printf / print 走特殊路径(print 映射到 printf)
|
||||
if string.strcmp(func_name, "printf") == 0 or string.strcmp(func_name, "print") == 0:
|
||||
trans.ExprCallH.HandlePrintfCall(cl)
|
||||
else:
|
||||
# 通用函数调用(返回值丢弃)
|
||||
trans.ExprCallH.HandleCall(call_node)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 预扫描:为局部变量提前创建 alloca
|
||||
# ============================================================
|
||||
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描语句中的 AnnAssign,提前创建 alloca
|
||||
|
||||
返回新增的变量数
|
||||
"""
|
||||
if node is None:
|
||||
return 0
|
||||
return trans.AnnAssignH.PreScan(node)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 break 语句
|
||||
# ============================================================
|
||||
def translate_break(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 break 语句:跳转到循环 end 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 break 目标
|
||||
if trans._break_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._break_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句(break 后面的代码不可达)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译 continue 语句
|
||||
# ============================================================
|
||||
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
|
||||
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
# 发射 br 到 continue 目标
|
||||
if trans._continue_bb is not None:
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, trans._continue_bb)
|
||||
|
||||
# 创建死代码 BB,用于后续语句
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
llvmlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取语句类型名(调试用)
|
||||
# ============================================================
|
||||
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
|
||||
"""获取语句类型名"""
|
||||
if node is None:
|
||||
return None
|
||||
return node.type_name()
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,238 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import llvmlite
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesEnum - 枚举类型注册和成员查找
|
||||
#
|
||||
# 管理 t.CEnum 派生类的成员信息:
|
||||
# - 枚举名 → EnumEntry(基准类型 + 成员表)
|
||||
# - 成员名 → EnumMember(值、类型)
|
||||
#
|
||||
# 使用全局数组存储,线性查找(枚举数量通常很少)
|
||||
# ============================================================
|
||||
|
||||
ENUM_MAX: t.CDefine = 64
|
||||
ENUM_MEMBER_MAX: t.CDefine = 64
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumMember - 枚举成员条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class EnumMember:
|
||||
Name: t.CChar | t.CPtr # 成员名(字符串)
|
||||
Value: t.CInt64T # 成员的整数值
|
||||
Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# EnumEntry - 枚举类型条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class EnumEntry:
|
||||
Name: t.CChar | t.CPtr # 枚举类名
|
||||
BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的)
|
||||
MemberCount: int # 成员数量
|
||||
Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局注册表(静态分配)
|
||||
# ============================================================
|
||||
_enum_table: EnumEntry | t.CPtr = None
|
||||
_enum_count: int = 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_enum_table — 初始化枚举注册表
|
||||
# ============================================================
|
||||
def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int:
|
||||
"""初始化枚举注册表,返回 1 成功"""
|
||||
global _enum_table
|
||||
global _enum_count
|
||||
|
||||
if _enum_table is not None:
|
||||
return 1
|
||||
|
||||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||||
_enum_table = pool.alloc(entry_size * ENUM_MAX)
|
||||
if _enum_table is None:
|
||||
return 0
|
||||
string.memset(_enum_table, 0, entry_size * ENUM_MAX)
|
||||
_enum_count = 0
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_entry — 获取第 i 个 EnumEntry 槽位
|
||||
# ============================================================
|
||||
def _get_enum_entry(i: int) -> EnumEntry | t.CPtr:
|
||||
"""获取第 i 个枚举条目"""
|
||||
if _enum_table is None or i < 0 or i >= ENUM_MAX:
|
||||
return None
|
||||
entry_size: t.CSizeT = EnumEntry.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(_enum_table) + i * entry_size
|
||||
return (EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _get_enum_member — 获取枚举中第 i 个 EnumMember 槽位
|
||||
# ============================================================
|
||||
def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.CPtr:
|
||||
"""获取枚举中第 i 个成员条目"""
|
||||
if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX:
|
||||
return None
|
||||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||||
addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size
|
||||
return (EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr))
|
||||
|
||||
|
||||
# ============================================================
|
||||
# register_enum — 注册枚举类型
|
||||
#
|
||||
# 返回 EnumEntry 指针,可用于添加成员
|
||||
# ============================================================
|
||||
def register_enum(pool: memhub.MemBuddy | t.CPtr,
|
||||
name: str,
|
||||
base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr:
|
||||
"""注册枚举类型,返回 EnumEntry 指针"""
|
||||
if init_enum_table(pool) == 0:
|
||||
return None
|
||||
|
||||
# 检查是否已注册
|
||||
existing: EnumEntry | t.CPtr = find_enum(name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
|
||||
if _enum_count >= ENUM_MAX:
|
||||
fb_et: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_et is not None:
|
||||
viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name)
|
||||
VLogger.error(fb_et, "ENUM")
|
||||
return None
|
||||
|
||||
entry: EnumEntry | t.CPtr = _get_enum_entry(_enum_count)
|
||||
if entry is None:
|
||||
return None
|
||||
|
||||
# 分配成员数组
|
||||
member_size: t.CSizeT = EnumMember.__sizeof__()
|
||||
entry.Members = pool.alloc(member_size * ENUM_MEMBER_MAX)
|
||||
if entry.Members is None:
|
||||
return None
|
||||
string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX)
|
||||
|
||||
# 复制类名
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, name)
|
||||
entry.Name = name_buf
|
||||
|
||||
entry.BaseTy = base_ty
|
||||
entry.MemberCount = 0
|
||||
|
||||
_enum_count += 1
|
||||
return entry
|
||||
|
||||
|
||||
# ============================================================
|
||||
# add_enum_member — 向枚举添加成员
|
||||
# ============================================================
|
||||
def add_enum_member(pool: memhub.MemBuddy | t.CPtr,
|
||||
enum_entry: EnumEntry | t.CPtr,
|
||||
member_name: str,
|
||||
member_val: t.CInt64T,
|
||||
member_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""向枚举添加成员,返回成员索引(-1 失败)"""
|
||||
if enum_entry is None or member_name is None or member_ty is None:
|
||||
return -1
|
||||
|
||||
if enum_entry.MemberCount >= ENUM_MEMBER_MAX:
|
||||
fb_em: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_em is not None:
|
||||
viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name)
|
||||
VLogger.error(fb_em, "ENUM")
|
||||
return -1
|
||||
|
||||
idx: int = enum_entry.MemberCount
|
||||
me: EnumMember | t.CPtr = _get_enum_member(enum_entry, idx)
|
||||
if me is None:
|
||||
return -1
|
||||
|
||||
# 复制成员名
|
||||
name_len: t.CSizeT = string.strlen(member_name)
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1)
|
||||
if name_buf is not None:
|
||||
string.strcpy(name_buf, member_name)
|
||||
me.Name = name_buf
|
||||
|
||||
me.Value = member_val
|
||||
me.Ty = member_ty
|
||||
|
||||
enum_entry.MemberCount = idx + 1
|
||||
return idx
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_enum — 按枚举类名查找
|
||||
# ============================================================
|
||||
def find_enum(name: str) -> EnumEntry | t.CPtr:
|
||||
"""按枚举类名查找,返回 EnumEntry 或 None"""
|
||||
if name is None or _enum_table is None:
|
||||
return None
|
||||
for i in range(_enum_count):
|
||||
entry: EnumEntry | t.CPtr = _get_enum_entry(i)
|
||||
if entry is not None and entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_enum_member — 按枚举类名和成员名查找
|
||||
# ============================================================
|
||||
def lookup_enum_member(enum_name: str,
|
||||
member_name: str) -> EnumMember | t.CPtr:
|
||||
"""按枚举类名和成员名查找,返回 EnumMember 或 None"""
|
||||
if enum_name is None or member_name is None:
|
||||
return None
|
||||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||||
if entry is None:
|
||||
return None
|
||||
for mi in range(entry.MemberCount):
|
||||
me: EnumMember | t.CPtr = _get_enum_member(entry, mi)
|
||||
if me is not None and me.Name is not None:
|
||||
if string.strcmp(me.Name, member_name) == 0:
|
||||
return me
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# is_enum_class — 检查类名是否为已注册枚举
|
||||
# ============================================================
|
||||
def is_enum_class(name: str) -> int:
|
||||
"""检查类名是否为已注册枚举,返回 1=是 / 0=否"""
|
||||
if name is None:
|
||||
return 0
|
||||
if find_enum(name) is not None:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_enum_base_type — 按枚举类名获取基准类型
|
||||
# ============================================================
|
||||
def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr:
|
||||
"""按枚举类名获取基准类型"""
|
||||
entry: EnumEntry | t.CPtr = find_enum(enum_name)
|
||||
if entry is not None:
|
||||
return entry.BaseTy
|
||||
return None
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,289 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesExprOps - 二元运算处理(模块级纯函数)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 运算符重载支持
|
||||
#
|
||||
# 当二元/比较运算的 lhs 是结构体指针时,检查该类是否定义了
|
||||
# 对应的 dunder 方法(如 __add__、__eq__),若有则生成方法调用
|
||||
# 而非原生算术/比较指令。
|
||||
# ============================================================
|
||||
|
||||
# BinOp 运算符 → dunder 方法名
|
||||
def _binop_to_dunder(op: int) -> str:
|
||||
"""将 BinOp 运算符映射到 dunder 方法名,无映射时返回 None"""
|
||||
if op == ast.OpKind.Add: return "__add__"
|
||||
if op == ast.OpKind.Sub: return "__sub__"
|
||||
if op == ast.OpKind.Mult: return "__mul__"
|
||||
if op == ast.OpKind.Div: return "__div__"
|
||||
if op == ast.OpKind.Mod: return "__mod__"
|
||||
if op == ast.OpKind.BitAnd: return "__and__"
|
||||
if op == ast.OpKind.BitOr: return "__or__"
|
||||
if op == ast.OpKind.BitXor: return "__xor__"
|
||||
if op == ast.OpKind.LShift: return "__lshift__"
|
||||
if op == ast.OpKind.RShift: return "__rshift__"
|
||||
if op == ast.OpKind.FloorDiv: return "__floordiv__"
|
||||
return None
|
||||
|
||||
# Compare 运算符 → dunder 方法名
|
||||
def _cmpop_to_dunder(op: int) -> str:
|
||||
"""将 Compare 运算符映射到 dunder 方法名,无映射时返回 None"""
|
||||
if op == ast.OpKind.Eq: return "__eq__"
|
||||
if op == ast.OpKind.Ne: return "__ne__"
|
||||
if op == ast.OpKind.Lt: return "__lt__"
|
||||
if op == ast.OpKind.Le: return "__le__"
|
||||
if op == ast.OpKind.Gt: return "__gt__"
|
||||
if op == ast.OpKind.Ge: return "__ge__"
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# try_operator_overload - 尝试运算符重载
|
||||
#
|
||||
# 检查 lhs 是否为结构体指针,并在该类(含继承链)中查找对应的
|
||||
# dunder 方法。找到则生成方法调用 lhs.__dunder__(rhs),返回
|
||||
# 调用结果;未找到返回 None,调用方回退到原生运算。
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# builder: IRBuilder
|
||||
# mod: LLVM 模块
|
||||
# lhs: 左操作数 Value(已求值)
|
||||
# rhs: 右操作数 Value(已求值)
|
||||
# op: OpKind 运算符
|
||||
# trans: Translator 对象
|
||||
# is_compare: 0=BinOp, 1=Compare(决定 dunder 映射表)
|
||||
#
|
||||
# Returns:
|
||||
# 方法调用的 Value(成功),None(未重载)
|
||||
# ============================================================
|
||||
def try_operator_overload(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
lhs: llvmlite.Value | t.CPtr,
|
||||
rhs: llvmlite.Value | t.CPtr,
|
||||
op: int,
|
||||
trans: HT.Translator | t.CPtr,
|
||||
is_compare: int) -> llvmlite.Value | t.CPtr:
|
||||
"""尝试运算符重载:lhs 是结构体指针时调用 dunder 方法,否则返回 None"""
|
||||
if lhs is None or rhs is None:
|
||||
return None
|
||||
|
||||
# 延迟导入避免循环依赖
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
|
||||
# 映射运算符到 dunder 方法名
|
||||
dunder: str = None
|
||||
if is_compare != 0:
|
||||
dunder = _cmpop_to_dunder(op)
|
||||
else:
|
||||
dunder = _binop_to_dunder(op)
|
||||
if dunder is None:
|
||||
return None
|
||||
|
||||
# 检查 lhs 是否为结构体指针
|
||||
struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type_from_value(lhs)
|
||||
if struct_ty is None:
|
||||
return None
|
||||
|
||||
# 获取类名
|
||||
class_name: str = HandlesStruct.get_class_name_by_type(pool, struct_ty)
|
||||
if class_name is None:
|
||||
return None
|
||||
|
||||
# 在继承链中查找 dunder 方法
|
||||
lookup_name: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if lookup_name is None:
|
||||
return None
|
||||
viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder)
|
||||
found_func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, lookup_name)
|
||||
|
||||
search_class: str = class_name
|
||||
if found_func is None:
|
||||
cur_parent: str = HandlesStruct.get_parent_name(class_name)
|
||||
while cur_parent is not None:
|
||||
parent_lookup: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if parent_lookup is not None:
|
||||
viperlib.snprintf(parent_lookup, 128, "%s.%s", cur_parent, dunder)
|
||||
parent_func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, parent_lookup)
|
||||
if parent_func is not None:
|
||||
found_func = parent_func
|
||||
search_class = cur_parent
|
||||
break
|
||||
cur_parent = HandlesStruct.get_parent_name(cur_parent)
|
||||
|
||||
# 方法不在当前模块中时,检查类(含父类)是否有 SHA1(stub 可能未注入)
|
||||
# 优先用类型指针定位 entry 获取 SHA1(规避跨模块同名 find_struct 找错)
|
||||
cls_sha1: str = None
|
||||
op_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty)
|
||||
if op_entry is not None:
|
||||
cls_sha1 = op_entry.ModuleSha1
|
||||
if cls_sha1 is None:
|
||||
cls_sha1 = HandlesStruct.get_struct_sha1(search_class)
|
||||
if cls_sha1 is None:
|
||||
cur_p: str = HandlesStruct.get_parent_name(search_class)
|
||||
while cur_p is not None and cls_sha1 is None:
|
||||
cls_sha1 = HandlesStruct.get_struct_sha1(cur_p)
|
||||
cur_p = HandlesStruct.get_parent_name(cur_p)
|
||||
|
||||
# 既无函数定义也无 SHA1 → 该类没有此 dunder 方法,返回 None 回退原生运算
|
||||
if found_func is None and cls_sha1 is None:
|
||||
return None
|
||||
|
||||
# 构建 extra_args 数组(仅含 rhs 一个参数)
|
||||
extra_args: t.CSizeT | t.CPtr = pool.alloc(8)
|
||||
if extra_args is None:
|
||||
return None
|
||||
extra_args[0] = t.CSizeT(rhs)
|
||||
|
||||
# 调用方法: lhs.__dunder__(rhs)
|
||||
return HandlesExprCall._call_method_on_ptr(
|
||||
pool, builder, mod, search_class, dunder,
|
||||
lhs, extra_args, 1, trans)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译二元运算(自动类型提升)
|
||||
# ============================================================
|
||||
def translate_binop(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
node: ast.AST | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr:
|
||||
"""翻译二元运算(自动类型提升)"""
|
||||
binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
|
||||
if binop is None:
|
||||
return None
|
||||
|
||||
lhs_node: ast.AST | t.CPtr = binop.left
|
||||
rhs_node: ast.AST | t.CPtr = binop.right
|
||||
op: int = binop.op
|
||||
|
||||
# 先翻译 rhs(只翻译一次,避免副作用重复)
|
||||
rhs: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, rhs_node, None, 0, trans)
|
||||
if rhs is None:
|
||||
return None
|
||||
|
||||
# === 运算符重载路径 1: lhs 是 Name 且对应结构体变量 ===
|
||||
# 对于值类型变量(如 cnt: Counter),translate_value 会 load 返回 Struct 值,
|
||||
# 但 dunder 方法需要 Ptr(Struct) 作为 self。直接用 alloca 指针尝试重载。
|
||||
if lhs_node is not None and lhs_node.kind() == ast.ASTKind.Name and trans is not None:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(lhs_node)
|
||||
if nm is not None and nm.id is not None:
|
||||
lhs_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, nm.id)
|
||||
if lhs_alloca is not None:
|
||||
ovl_result: llvmlite.Value | t.CPtr = try_operator_overload(
|
||||
pool, builder, mod, lhs_alloca, rhs, op, trans, 0)
|
||||
if ovl_result is not None:
|
||||
return ovl_result
|
||||
|
||||
# 正常翻译 lhs
|
||||
lhs: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, mod, lhs_node, None, 0, trans)
|
||||
if lhs is None:
|
||||
return None
|
||||
|
||||
# === 运算符重载路径 2: lhs 是 Ptr(Struct)(如 Counter|t.CPtr 变量 load 后)===
|
||||
ovl_result2: llvmlite.Value | t.CPtr = try_operator_overload(
|
||||
pool, builder, mod, lhs, rhs, op, trans, 0)
|
||||
if ovl_result2 is not None:
|
||||
return ovl_result2
|
||||
|
||||
# 获取操作数类型信息
|
||||
lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty)
|
||||
rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty)
|
||||
lhs_fbits: int = HandlesExpr.get_llvm_float_bits(lhs.Ty)
|
||||
rhs_fbits: int = HandlesExpr.get_llvm_float_bits(rhs.Ty)
|
||||
|
||||
# 浮点运算: 任一操作数为浮点时,使用浮点指令(必须在指针算术之前检查,
|
||||
# 因为 float 的 int bits 为 0,会被误认为指针)
|
||||
if lhs_fbits != 0 or rhs_fbits != 0:
|
||||
# 确定目标浮点类型(使用较大的位宽)
|
||||
target_fbits: int = lhs_fbits
|
||||
if rhs_fbits > target_fbits:
|
||||
target_fbits = rhs_fbits
|
||||
target_float_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool)
|
||||
if target_fbits == 32:
|
||||
target_float_ty = llvmlite.Float(pool)
|
||||
# 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc)
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, target_float_ty)
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, target_float_ty)
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_fadd(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Sub:
|
||||
return llvmlite.build_fsub(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mult:
|
||||
return llvmlite.build_fmul(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Div:
|
||||
return llvmlite.build_fdiv(builder, lhs, rhs)
|
||||
if op == ast.OpKind.Mod:
|
||||
return llvmlite.build_frem(builder, lhs, rhs)
|
||||
return None
|
||||
|
||||
# 指针算术: ptr + int 或 ptr - int → ptrtoint + add/sub + inttoptr
|
||||
if (lhs_bits == 0 and rhs_bits != 0) or (lhs_bits != 0 and rhs_bits == 0):
|
||||
if op == ast.OpKind.Add or op == ast.OpKind.Sub:
|
||||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||||
if lhs_bits == 0:
|
||||
# lhs 是指针,rhs 是整数
|
||||
ptr_as_int: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, lhs, i64_ty)
|
||||
int_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, rhs, i64_ty)
|
||||
if op == ast.OpKind.Add:
|
||||
result: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, ptr_as_int, int_val)
|
||||
else:
|
||||
result = llvmlite.build_sub(builder, ptr_as_int, int_val)
|
||||
return llvmlite.build_inttoptr(builder, result, lhs.Ty)
|
||||
else:
|
||||
# rhs 是指针,lhs 是整数(仅 Add 支持交换)
|
||||
ptr_as_int = llvmlite.build_ptrtoint(builder, rhs, i64_ty)
|
||||
int_val = HandlesExpr.coerce_to_type(builder, lhs, i64_ty)
|
||||
if op == ast.OpKind.Add:
|
||||
result = llvmlite.build_add(builder, int_val, ptr_as_int)
|
||||
else:
|
||||
result = llvmlite.build_sub(builder, int_val, ptr_as_int)
|
||||
return llvmlite.build_inttoptr(builder, result, rhs.Ty)
|
||||
|
||||
if lhs_bits > rhs_bits:
|
||||
rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty)
|
||||
elif rhs_bits > lhs_bits:
|
||||
lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty)
|
||||
|
||||
if op == ast.OpKind.Add:
|
||||
return llvmlite.build_add(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Sub:
|
||||
return llvmlite.build_sub(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mult:
|
||||
return llvmlite.build_mul(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Div:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.FloorDiv:
|
||||
return llvmlite.build_sdiv(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.Mod:
|
||||
return llvmlite.build_srem(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitAnd:
|
||||
return llvmlite.build_and(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitOr:
|
||||
return llvmlite.build_or(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.BitXor:
|
||||
return llvmlite.build_xor(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.LShift:
|
||||
return llvmlite.build_shl(builder, lhs, rhs)
|
||||
elif op == ast.OpKind.RShift:
|
||||
return llvmlite.build_ashr(builder, lhs, rhs)
|
||||
return None
|
||||
@@ -1,398 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
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.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesFor - for 循环语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 支持 for i in range(start, stop, step) 模式:
|
||||
# %i = alloca i32
|
||||
# store i32 start, i32* %i
|
||||
# br label %cond
|
||||
# cond:
|
||||
# %cur = load i32, i32* %i
|
||||
# %cmp = icmp slt i32 %cur, stop
|
||||
# br i1 %cmp, label %body, label %end
|
||||
# body:
|
||||
# ... body ...
|
||||
# br label %incr
|
||||
# incr:
|
||||
# %cur2 = load i32, i32* %i
|
||||
# %next = add i32 %cur2, step
|
||||
# store i32 %next, i32* %i
|
||||
# br label %cond
|
||||
# end:
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class ForHandle(HandlesBase.Mixin):
|
||||
"""for 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 for 语句,返回新增变量数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 for i in range(...) 循环语句"""
|
||||
if node is None:
|
||||
return 0
|
||||
|
||||
trans: HT.Translator | t.CPtr = self.Trans
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
for_node: ast.For | t.CPtr = (ast.For | t.CPtr)(node)
|
||||
|
||||
# 1. 获取循环变量名(仅支持 for i in range(...))
|
||||
target: ast.AST | t.CPtr = for_node.target
|
||||
if target is None:
|
||||
return 0
|
||||
if target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
target_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target)
|
||||
var_name: str = target_nm.id
|
||||
if var_name is None:
|
||||
return 0
|
||||
|
||||
# 2. 解析迭代器:支持 range() 和指针迭代
|
||||
iter_node: ast.AST | t.CPtr = for_node.iter
|
||||
if iter_node is None:
|
||||
return 0
|
||||
|
||||
# 检查是否是 range() 调用
|
||||
is_range_iter: int = 0
|
||||
if iter_node.kind() == ast.ASTKind.Call:
|
||||
call_pre: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node)
|
||||
fn_pre: str = HandlesExpr.get_func_name(call_pre.func)
|
||||
if fn_pre is not None:
|
||||
if string.strcmp(fn_pre, "range") == 0:
|
||||
is_range_iter = 1
|
||||
else:
|
||||
err_msg: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if err_msg is not None:
|
||||
viperlib.snprintf(err_msg, 256, "仅支持 range() 或指针迭代,got call '%s'", fn_pre)
|
||||
HandlesType.fatal_error(iter_node, err_msg)
|
||||
HandlesType.fatal_error(iter_node, "仅支持 range() 或指针迭代")
|
||||
|
||||
# 非范围迭代:走指针迭代路径
|
||||
if is_range_iter == 0:
|
||||
return self._handle_ptr_iter(for_node, var_name)
|
||||
|
||||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node)
|
||||
|
||||
# 3. 解析 range 参数: range(stop) / range(start, stop) / range(start, stop, step)
|
||||
args: list[ast.AST | t.CPtr] | t.CPtr = call.args
|
||||
if args is None:
|
||||
return 0
|
||||
arg_count: t.CSizeT = args.__len__()
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
start_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
stop_val: llvmlite.Value | t.CPtr = None
|
||||
step_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 1)
|
||||
|
||||
if arg_count == 1:
|
||||
stop_val = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, args.get(0),
|
||||
trans._funcs, trans._func_count, trans)
|
||||
elif arg_count >= 2:
|
||||
start_val = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, args.get(0),
|
||||
trans._funcs, trans._func_count, trans)
|
||||
stop_val = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, args.get(1),
|
||||
trans._funcs, trans._func_count, trans)
|
||||
if arg_count >= 3:
|
||||
step_val = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, args.get(2),
|
||||
trans._funcs, trans._func_count, trans)
|
||||
|
||||
if stop_val is None:
|
||||
stop_val = llvmlite.const_int32(pool, 0)
|
||||
if start_val is None:
|
||||
start_val = llvmlite.const_int32(pool, 0)
|
||||
if step_val is None:
|
||||
step_val = llvmlite.const_int32(pool, 1)
|
||||
|
||||
# 4. 创建/查找循环变量 alloca
|
||||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, var_name)
|
||||
new_vars: int = 0
|
||||
if var_alloca is None:
|
||||
var_alloca = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||||
if HandlesVar.define_var(
|
||||
trans.SymTab, var_name, var_alloca) == 0:
|
||||
new_vars = 1
|
||||
|
||||
# 获取循环变量的实际元素类型(alloca 是指针类型,需解引用 Pointee)
|
||||
# 当循环变量已声明为 i64(如 t.CSizeT),使用 i64 而非硬编码 i32
|
||||
# 避免 load i32, i64* / store i32, i64* 类型不匹配
|
||||
loop_var_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if var_alloca is not None and var_alloca.Ty is not None:
|
||||
match var_alloca.Ty:
|
||||
case llvmlite.LLVMType.Ptr(pointee_ty):
|
||||
if pointee_ty is not None:
|
||||
loop_var_ty = pointee_ty
|
||||
loop_var_bits: int = HandlesExpr.get_llvm_type_bits(loop_var_ty)
|
||||
|
||||
# 5. 存储初始值 (类型对齐: start_val 可能是 i32/i64,需对齐到 loop_var_ty)
|
||||
init_val: llvmlite.Value | t.CPtr = start_val
|
||||
if start_val is not None and start_val.Ty is not None:
|
||||
start_bits: int = HandlesExpr.get_llvm_type_bits(start_val.Ty)
|
||||
if start_bits != 0 and start_bits != loop_var_bits:
|
||||
if start_bits < loop_var_bits:
|
||||
init_val = llvmlite.build_sext(builder, start_val, loop_var_ty)
|
||||
else:
|
||||
init_val = llvmlite.build_trunc(builder, start_val, loop_var_ty)
|
||||
llvmlite.build_store(builder, init_val, var_alloca)
|
||||
|
||||
# 6. 创建基本块: cond / body / incr / end(使用 trans._label_counter,不与 SSA 名共享)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "for.cond.%d", cnt)
|
||||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.body.%d", cnt)
|
||||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.incr.%d", cnt)
|
||||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.end.%d", cnt)
|
||||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 7. 跳转到 cond 块
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# 8. cond 块: load i, icmp slt i, stop, cond_br body/end
|
||||
llvmlite.position_at_end(builder, cond_bb)
|
||||
cur_i: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca)
|
||||
# 类型对齐: stop_val 可能是 i64 (如 range(strlen(s))),需将 cur_i 提升到 stop_val 类型
|
||||
cmp_lhs: llvmlite.Value | t.CPtr = cur_i
|
||||
cmp_rhs: llvmlite.Value | t.CPtr = stop_val
|
||||
if stop_val is not None and stop_val.Ty is not None:
|
||||
stop_bits: int = HandlesExpr.get_llvm_type_bits(stop_val.Ty)
|
||||
cur_bits: int = HandlesExpr.get_llvm_type_bits(cur_i.Ty)
|
||||
if stop_bits != 0 and cur_bits != 0 and stop_bits != cur_bits:
|
||||
if cur_bits < stop_bits:
|
||||
cmp_lhs = llvmlite.build_sext(builder, cur_i, stop_val.Ty)
|
||||
else:
|
||||
cmp_rhs = llvmlite.build_trunc(builder, stop_val, loop_var_ty)
|
||||
cond_i1: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_SLT, cmp_lhs, cmp_rhs)
|
||||
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
|
||||
|
||||
# 9. body 块: 翻译循环体,跳到 incr
|
||||
llvmlite.position_at_end(builder, body_bb)
|
||||
|
||||
# 保存旧循环上下文,设置 break/continue 目标
|
||||
old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb
|
||||
old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = for_node.children
|
||||
if body is not None:
|
||||
body_count: t.CSizeT = body.__len__()
|
||||
for bi in range(body_count):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
|
||||
# 恢复旧循环上下文
|
||||
trans._break_bb = old_break
|
||||
trans._continue_bb = old_continue
|
||||
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, incr_bb)
|
||||
|
||||
# 10. incr 块: i = i + step, 跳回 cond
|
||||
llvmlite.position_at_end(builder, incr_bb)
|
||||
cur_i2: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca)
|
||||
# 类型对齐: step_val 可能是 i32/i64,需对齐到 loop_var_ty 与 cur_i2 类型一致
|
||||
incr_step: llvmlite.Value | t.CPtr = step_val
|
||||
if step_val is not None and step_val.Ty is not None:
|
||||
step_bits: int = HandlesExpr.get_llvm_type_bits(step_val.Ty)
|
||||
cur2_bits: int = HandlesExpr.get_llvm_type_bits(cur_i2.Ty)
|
||||
if step_bits != 0 and cur2_bits != 0 and step_bits != cur2_bits:
|
||||
if step_bits > cur2_bits:
|
||||
incr_step = llvmlite.build_trunc(builder, step_val, loop_var_ty)
|
||||
else:
|
||||
incr_step = llvmlite.build_sext(builder, step_val, loop_var_ty)
|
||||
next_i: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_i2, incr_step)
|
||||
llvmlite.build_store(builder, next_i, var_alloca)
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# 11. 定位到 end 块
|
||||
llvmlite.position_at_end(builder, end_bb)
|
||||
return new_vars
|
||||
|
||||
# ============================================================
|
||||
# _handle_ptr_iter - 指针迭代: for x in ptr:
|
||||
# 遍历指针,依赖隐式 index,直到解引用为空(null 终止符)
|
||||
#
|
||||
# 生成 IR 结构:
|
||||
# %idx = alloca i32
|
||||
# store i32 0, i32* %idx
|
||||
# br label %cond
|
||||
# cond:
|
||||
# %i = load i32, i32* %idx
|
||||
# %ep = getelementptr elem_ty, ptr_ty %ptr, i32 %i
|
||||
# %ev = load elem_ty, elem_ty* %ep
|
||||
# %null = icmp eq elem_ty %ev, 0
|
||||
# br i1 %null, label %end, label %body
|
||||
# body:
|
||||
# store elem_ty %ev, elem_ty* %var
|
||||
# ... 循环体 ...
|
||||
# br label %incr
|
||||
# incr:
|
||||
# %next = add i32 %i, 1
|
||||
# store i32 %next, i32* %idx
|
||||
# br label %cond
|
||||
# end:
|
||||
# ============================================================
|
||||
def _handle_ptr_iter(self, for_node: ast.For | t.CPtr,
|
||||
var_name: str) -> int:
|
||||
"""指针迭代: for x in ptr: 直到解引用为空"""
|
||||
trans: HT.Translator | t.CPtr = self.Trans
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
|
||||
# 翻译迭代器表达式,获取指针值
|
||||
ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, for_node.iter,
|
||||
trans._funcs, trans._func_count, trans)
|
||||
if ptr_val is None:
|
||||
HandlesType.fatal_error(for_node, "指针迭代: 无法翻译迭代器表达式")
|
||||
|
||||
# 检查是否是指针类型
|
||||
if HandlesExpr.is_ptr_type(ptr_val.Ty) == 0:
|
||||
HandlesType.fatal_error(for_node, "指针迭代: 迭代器不是指针类型")
|
||||
|
||||
# 获取元素类型
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee
|
||||
if elem_ty is None:
|
||||
HandlesType.fatal_error(for_node, "指针迭代: 无法获取元素类型")
|
||||
|
||||
# 元素类型必须是整数(用于 icmp eq 0 检查 null 终止符)
|
||||
elem_bits: int = HandlesExpr.get_llvm_type_bits(elem_ty)
|
||||
if elem_bits == 0:
|
||||
HandlesType.fatal_error(for_node, "指针迭代: 元素类型不是整数,无法检查 null 终止符")
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
|
||||
# 创建循环变量 alloca(存储元素值)
|
||||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, var_name)
|
||||
new_vars: int = 0
|
||||
if var_alloca is None:
|
||||
var_alloca = HandlesVar._alloca_at_entry(builder, elem_ty)
|
||||
if HandlesVar.define_var(
|
||||
trans.SymTab, var_name, var_alloca) == 0:
|
||||
new_vars = 1
|
||||
|
||||
# 创建隐式 index 变量,初始为 0
|
||||
idx_alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, i32_ty)
|
||||
llvmlite.build_store(builder, llvmlite.const_int32(pool, 0), idx_alloca)
|
||||
|
||||
# 创建基本块: cond / body / incr / end
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "ptr.cond.%d", cnt)
|
||||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.body.%d", cnt)
|
||||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.incr.%d", cnt)
|
||||
incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.end.%d", cnt)
|
||||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 跳转到 cond
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# cond 块: load index, GEP, load elem, icmp eq 0
|
||||
llvmlite.position_at_end(builder, cond_bb)
|
||||
cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i32_ty, idx_alloca)
|
||||
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||||
builder, elem_ty, ptr_val, cur_idx)
|
||||
cur_elem: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, elem_ty, elem_ptr)
|
||||
null_val: llvmlite.Value | t.CPtr = llvmlite.const_int(pool, elem_bits, 0)
|
||||
is_null: llvmlite.Value | t.CPtr = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_EQ, cur_elem, null_val)
|
||||
llvmlite.build_cond_br(builder, is_null, end_bb, body_bb)
|
||||
|
||||
# body 块: store elem to var, 翻译循环体
|
||||
llvmlite.position_at_end(builder, body_bb)
|
||||
llvmlite.build_store(builder, cur_elem, var_alloca)
|
||||
|
||||
# 保存旧循环上下文,设置 break/continue 目标
|
||||
old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb
|
||||
old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = for_node.children
|
||||
if body is not None:
|
||||
body_count: t.CSizeT = body.__len__()
|
||||
for bi in range(body_count):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
|
||||
# 恢复旧循环上下文
|
||||
trans._break_bb = old_break
|
||||
trans._continue_bb = old_continue
|
||||
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, incr_bb)
|
||||
|
||||
# incr 块: index++, br cond
|
||||
llvmlite.position_at_end(builder, incr_bb)
|
||||
one_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 1)
|
||||
next_idx: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_idx, one_val)
|
||||
llvmlite.build_store(builder, next_idx, idx_alloca)
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# 定位到 end 块
|
||||
llvmlite.position_at_end(builder, end_bb)
|
||||
return new_vars
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewForHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewForHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ForHandle | t.CPtr:
|
||||
h: ForHandle | t.CPtr = pool.alloc(ForHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ForHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,995 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import viperlib
|
||||
import stdio
|
||||
import stdlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesNonlocal as HandlesNonlocal
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
|
||||
|
||||
# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug)
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性
|
||||
#
|
||||
# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式
|
||||
# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式
|
||||
#
|
||||
# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None
|
||||
# ============================================================
|
||||
def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr,
|
||||
decorator_list: list[ast.AST | t.CPtr] | t.CPtr,
|
||||
imported_modules: str) -> t.CChar | t.CPtr:
|
||||
"""从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串"""
|
||||
if decorator_list is None:
|
||||
return None
|
||||
dn: t.CSizeT = decorator_list.__len__()
|
||||
if dn == 0:
|
||||
return None
|
||||
|
||||
attrs_buf: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if attrs_buf is None:
|
||||
return None
|
||||
attrs_buf[0] = '\0'
|
||||
found_any: int = 0
|
||||
|
||||
for di in range(dn):
|
||||
deco: ast.AST | t.CPtr = decorator_list.get(di)
|
||||
if deco is None or deco.kind() != ast.ASTKind.Call:
|
||||
continue
|
||||
call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco)
|
||||
if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute:
|
||||
continue
|
||||
|
||||
# 检测 c.Attribute
|
||||
func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func)
|
||||
if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0:
|
||||
continue
|
||||
if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name:
|
||||
continue
|
||||
c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value)
|
||||
if c_name.id is None or string.strcmp(c_name.id, "c") != 0:
|
||||
continue
|
||||
if HandlesImports.is_module_imported(imported_modules, "c") == 0:
|
||||
continue
|
||||
|
||||
# 遍历参数提取属性
|
||||
if call_node.args is None:
|
||||
continue
|
||||
args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args
|
||||
an: t.CSizeT = args_list.__len__()
|
||||
for ai in range(an):
|
||||
arg_node: ast.AST | t.CPtr = args_list.get(ai)
|
||||
if arg_node is None:
|
||||
continue
|
||||
|
||||
# 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx)
|
||||
attr_name: str = _get_attr_name_from_node(arg_node)
|
||||
if attr_name is None:
|
||||
continue
|
||||
|
||||
# 映射到 LLVM 属性名并追加
|
||||
if _append_llvm_attr(attrs_buf, attr_name) != 0:
|
||||
found_any = 1
|
||||
# 追加成功后,如果不是最后一个属性,添加空格分隔
|
||||
# 在下一次追加前由 _append_str 处理
|
||||
|
||||
if found_any == 0:
|
||||
return None
|
||||
return attrs_buf
|
||||
|
||||
|
||||
def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str:
|
||||
"""从 AST 节点提取属性名
|
||||
|
||||
支持:
|
||||
- Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline"
|
||||
- Attribute: t.attr.packed -> "packed"
|
||||
- Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind"
|
||||
"""
|
||||
if node is None:
|
||||
return None
|
||||
k: int = node.kind()
|
||||
|
||||
# Call 节点: t.attr.always_inline()
|
||||
if k == ast.ASTKind.Call:
|
||||
call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
|
||||
if call.func is None or call.func.kind() != ast.ASTKind.Attribute:
|
||||
return None
|
||||
at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func)
|
||||
return at.attr
|
||||
|
||||
# Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind
|
||||
if k == ast.ASTKind.Attribute:
|
||||
at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node)
|
||||
return at2.attr
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _append_llvm_attr(attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int:
|
||||
"""将属性名映射到 LLVM 属性名并追加到缓冲区
|
||||
|
||||
返回 1 表示已追加,0 表示不支持该属性
|
||||
"""
|
||||
if attrs_buf is None or attr_name is None:
|
||||
return 0
|
||||
|
||||
# 先确定映射的 LLVM 属性名
|
||||
llvm_name: str = None
|
||||
if string.strcmp(attr_name, "always_inline") == 0:
|
||||
llvm_name = "alwaysinline"
|
||||
elif string.strcmp(attr_name, "noinline") == 0:
|
||||
llvm_name = "noinline"
|
||||
elif string.strcmp(attr_name, "noreturn") == 0:
|
||||
llvm_name = "noreturn"
|
||||
elif string.strcmp(attr_name, "pure") == 0:
|
||||
llvm_name = "readonly"
|
||||
elif string.strcmp(attr_name, "const") == 0:
|
||||
llvm_name = "readnone"
|
||||
elif string.strcmp(attr_name, "nounwind") == 0:
|
||||
llvm_name = "nounwind"
|
||||
elif string.strcmp(attr_name, "noredzone") == 0:
|
||||
llvm_name = "noredzone"
|
||||
elif string.strcmp(attr_name, "willreturn") == 0:
|
||||
llvm_name = "willreturn"
|
||||
elif string.strcmp(attr_name, "mustprogress") == 0:
|
||||
llvm_name = "mustprogress"
|
||||
else:
|
||||
# packed/aligned/section/visibility/weak 等不支持作为函数内联属性
|
||||
return 0
|
||||
|
||||
# 支持的属性:如果缓冲区非空,先追加空格分隔
|
||||
if attrs_buf[0] != '\0':
|
||||
_append_str(attrs_buf, " ")
|
||||
_append_str(attrs_buf, llvm_name)
|
||||
return 1
|
||||
|
||||
|
||||
def _append_str(buf: t.CChar | t.CPtr, s: str) -> None:
|
||||
"""将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)"""
|
||||
if buf is None or s is None:
|
||||
return
|
||||
cur_len: t.CSizeT = string.strlen(buf)
|
||||
string.strcpy(buf + cur_len, s)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesFunctions - 函数定义处理(trans 单参模式)
|
||||
#
|
||||
# 参考 Python 版 TransPyC FunctionHandle
|
||||
#
|
||||
# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope
|
||||
# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _mangle_name - 为名称添加 SHA1 前缀
|
||||
#
|
||||
# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带
|
||||
# SHA1 前缀(16 hex + '.'),则原样返回。
|
||||
# ============================================================
|
||||
def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str:
|
||||
"""为任意名称添加 SHA1 前缀(不做 main/export 检查)"""
|
||||
if trans is None or name is None:
|
||||
return name
|
||||
if trans.ModuleSha1 is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c: t.CChar = name[i]
|
||||
if not (('0' <= c <= '9') or ('a' <= c <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1: str = trans.ModuleSha1
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀
|
||||
#
|
||||
# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling,
|
||||
# 而非当前模块的 SHA1。
|
||||
# ============================================================
|
||||
def _mangle_name_with_sha1(sha1: str, name: str) -> str:
|
||||
"""用指定 SHA1 为名称添加前缀(不做 main/export 检查)"""
|
||||
if sha1 is None or name is None:
|
||||
return name
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
# 已带 SHA1 前缀(16 hex + '.')则跳过
|
||||
if name_len > 17:
|
||||
is_sha1: int = 1
|
||||
for i in range(16):
|
||||
c2: t.CChar = name[i]
|
||||
if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')):
|
||||
is_sha1 = 0
|
||||
break
|
||||
if is_sha1 != 0 and name[16] == '.':
|
||||
return name
|
||||
sha1_len: t.CSizeT = string.strlen(sha1)
|
||||
mangled: str = stdlib.malloc(sha1_len + name_len + 2)
|
||||
if mangled is None:
|
||||
return name
|
||||
string.strcpy(mangled, sha1)
|
||||
mangled[sha1_len] = '.'
|
||||
string.strcpy(mangled + sha1_len + 1, name)
|
||||
return mangled
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查)
|
||||
#
|
||||
# 规则:
|
||||
# - main 函数不加前缀(程序入口点)
|
||||
# - has_export 非 0 时不加前缀(t.CExport 导出函数)
|
||||
# - 已带 SHA1 前缀的不再加
|
||||
# - ModuleSha1 为 None 时不加前缀
|
||||
# ============================================================
|
||||
def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str,
|
||||
has_export: int) -> str:
|
||||
"""为函数名添加 SHA1 前缀(检查 main/export)"""
|
||||
if trans is None or name is None:
|
||||
return name
|
||||
if has_export != 0:
|
||||
return name
|
||||
if string.strcmp(name, "main") == 0:
|
||||
return name
|
||||
return _mangle_name(trans, name)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明
|
||||
#
|
||||
# 解决同模块内前向引用问题:如 viperlib.py 中 sprintf(行15) 调用
|
||||
# vsnprintf(行41),但 vsnprintf 定义在后面。
|
||||
#
|
||||
# 对每个顶层 FunctionDef:
|
||||
# 1. 推断返回类型和参数类型
|
||||
# 2. 计算 mangled name(含 SHA1 前缀)
|
||||
# 3. 创建 declare(IsDeclared=1)
|
||||
# 4. 添加参数
|
||||
# 5. 注册到函数表
|
||||
#
|
||||
# 后续 translate_function_def 会通过 find_func_in_module 找到已有的 declare,
|
||||
# 复用之(清除 IsDeclared,跳过参数创建,直接添加函数体)。
|
||||
# ============================================================
|
||||
def forward_declare_functions(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""预扫描所有顶层 FunctionDef,创建前向声明"""
|
||||
if trans is None or tree is None:
|
||||
return 0
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
if pool is None or mod is None:
|
||||
return 0
|
||||
|
||||
imported_modules: str = trans._imported_modules
|
||||
from_imports: str = trans._from_imports
|
||||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
if child.kind() != ast.ASTKind.FunctionDef:
|
||||
continue
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||||
if fd is None or fd.name is None:
|
||||
continue
|
||||
|
||||
# 推断返回类型
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if fd.returns is not None:
|
||||
ret_ty = HandlesType.resolve_annotation_type(
|
||||
pool, fd.returns, imported_modules, from_imports, trans)
|
||||
if ret_ty is None and fd.returns is not None:
|
||||
if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
|
||||
ret_ty = llvmlite.Void(pool)
|
||||
if ret_ty is None:
|
||||
ret_ty = i32_ty
|
||||
|
||||
# 检测 CExtern/State/CExport
|
||||
has_extern: int = 0
|
||||
has_state: int = 0
|
||||
has_export: int = 0
|
||||
if fd.returns is not None:
|
||||
has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern")
|
||||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||||
is_extern_decl: int = 0
|
||||
if has_extern != 0 or has_state != 0:
|
||||
is_extern_decl = 1
|
||||
|
||||
# 计算 mangled name
|
||||
if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main":
|
||||
mangled_name: str = fd.name
|
||||
else:
|
||||
mangled_name = _mangle_func_name(trans, fd.name, 0)
|
||||
|
||||
# 如果函数已存在(如重复定义),跳过
|
||||
existing: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name)
|
||||
if existing is not None:
|
||||
continue
|
||||
|
||||
# 创建 declare
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
if func is None:
|
||||
continue
|
||||
|
||||
# 提取默认参数信息
|
||||
# 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(),
|
||||
# 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错
|
||||
fd_args_node: ast.Arguments | t.CPtr = fd.args
|
||||
fd_defaults: t.CVoid | t.CPtr = None
|
||||
fd_default_count: int = 0
|
||||
fd_param_count: int = 0
|
||||
if fd_args_node is not None:
|
||||
fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node)
|
||||
if fd_ags.args is not None:
|
||||
fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args
|
||||
fd_param_count = fd_alist.__len__()
|
||||
if fd_ags.defaults is not None:
|
||||
fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults
|
||||
fd_defaults = fd_dlist
|
||||
fd_default_count = fd_dlist.__len__()
|
||||
|
||||
# 注册到函数表(用裸名 fd.name,不是 mangled_name)
|
||||
max_funcs: int = 256
|
||||
cur_count: int = trans._func_count
|
||||
if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs,
|
||||
fd_defaults, fd_default_count, fd_param_count) == 0:
|
||||
trans._func_count = cur_count + 1
|
||||
|
||||
# 注册 CExport 函数到全局表
|
||||
if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None:
|
||||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||||
|
||||
# 添加参数
|
||||
args_node: ast.Arguments | t.CPtr = fd.args
|
||||
if args_node is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = alist.__len__()
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is None or arg.arg is None:
|
||||
continue
|
||||
# t.CVoid 表示空参:跳过
|
||||
if arg.annotation is not None:
|
||||
if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
|
||||
continue
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg.annotation, imported_modules, from_imports, trans)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 翻译函数定义 FunctionDef(name, args, body, ...)
|
||||
#
|
||||
# trans 单参模式:所有共享状态从 trans 获取
|
||||
# 函数局部作用域通过 enter_scope/exit_scope 管理
|
||||
# ============================================================
|
||||
def translate_function_def(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)"""
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
imported_modules: str = trans._imported_modules
|
||||
from_imports: str = trans._from_imports
|
||||
funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs
|
||||
func_count: int = trans._func_count
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
|
||||
# 推断返回类型:优先使用返回类型注解
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if fd.returns is not None:
|
||||
ret_ty = HandlesType.resolve_annotation_type(
|
||||
pool, fd.returns, imported_modules, from_imports, trans)
|
||||
|
||||
# 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void
|
||||
# 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32
|
||||
if ret_ty is None and fd.returns is not None:
|
||||
if HandlesType.has_decorator_marker(fd.returns, "State") != 0:
|
||||
ret_ty = llvmlite.Void(pool)
|
||||
|
||||
# 如果仍然为 None,扫描 return 语句推断(至少返回 i32)
|
||||
if ret_ty is None:
|
||||
param_types_str: str = HandlesType.build_param_types_str(pool, fd.args)
|
||||
ret_ty = HandlesType.infer_return_type(
|
||||
pool, fd.children, param_types_str)
|
||||
# 检测是否为外部声明函数(t.CExtern 或 t.State)
|
||||
# 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号)
|
||||
# t.State = t.CExtern + t.CExport(既是声明又是导出)
|
||||
# t.CExport 导出函数不加 SHA1 前缀
|
||||
# t.CExtern/t.State/t.CExport 都不加 SHA1 前缀,直接映射到 C 标准库函数名
|
||||
is_extern_decl: int = 0
|
||||
has_export: int = 0
|
||||
has_extern: int = 0
|
||||
has_state: int = 0
|
||||
if fd.returns is not None:
|
||||
has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern")
|
||||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||||
# t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass)
|
||||
if has_extern != 0 or has_state != 0:
|
||||
is_extern_decl = 1
|
||||
|
||||
# SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名
|
||||
# (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference)
|
||||
# main 函数也不加前缀(程序入口点)
|
||||
if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main":
|
||||
mangled_name: str = fd.name
|
||||
else:
|
||||
mangled_name: str = _mangle_func_name(trans, fd.name, 0)
|
||||
|
||||
# 注册 CExport 函数到全局表(供跨模块调用查表)
|
||||
# t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func
|
||||
if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None:
|
||||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||||
|
||||
if is_extern_decl != 0:
|
||||
# 外部声明函数:生成 declare(仅声明,不定义)
|
||||
# 先检查是否已由 forward_declare_functions 创建,避免重复 declare
|
||||
existing_extern: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name)
|
||||
if existing_extern is not None:
|
||||
# 已存在前向声明,复用之,不再重复创建
|
||||
return 0
|
||||
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, mangled_name, ret_ty)
|
||||
if func is None:
|
||||
return 0
|
||||
|
||||
# 注册到函数表
|
||||
max_funcs_extern: int = 256
|
||||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern) == 0:
|
||||
trans._func_count = func_count + 1
|
||||
|
||||
# 添加参数(支持类型注解)
|
||||
args_node_extern: ast.Arguments | t.CPtr = fd.args
|
||||
if args_node_extern is not None:
|
||||
ags_e: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node_extern)
|
||||
if ags_e.args is not None:
|
||||
alist_e: list[ast.AST | t.CPtr] | t.CPtr = ags_e.args
|
||||
an_e: t.CSizeT = alist_e.__len__()
|
||||
for ai_e in range(an_e):
|
||||
arg_e: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist_e.get(ai_e))
|
||||
if arg_e is not None and arg_e.arg is not None:
|
||||
# t.CVoid 表示空参:跳过,不添加到函数签名
|
||||
if arg_e.annotation is not None:
|
||||
if HandlesType._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0:
|
||||
continue
|
||||
param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg_e.annotation is not None:
|
||||
resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg_e.annotation, imported_modules, from_imports, trans)
|
||||
if resolved_e is not None:
|
||||
param_ty_e = resolved_e
|
||||
pname_e: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if pname_e is not None:
|
||||
viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg)
|
||||
llvmlite.add_param(pool, func, param_ty_e, pname_e)
|
||||
|
||||
# 提取 @c.Attribute 装饰器属性并设置到函数
|
||||
func_attrs_e: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||||
if func_attrs_e is not None:
|
||||
llvmlite.function_set_attrs(func, func_attrs_e)
|
||||
|
||||
return 0
|
||||
|
||||
# args_node 用于后续 alloca 创建,提前赋值
|
||||
args_node: ast.Arguments | t.CPtr = fd.args
|
||||
|
||||
# 检查是否已有前向声明(由 forward_declare_functions 创建)
|
||||
func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name)
|
||||
if func is not None and llvmlite.function_is_declared(func) != 0:
|
||||
# 复用前向声明:清除 IsDeclared 标记,转为 define
|
||||
func.IsDeclared = 0
|
||||
# 装饰器属性设置(前向声明时未设置)
|
||||
func_attrs_reuse: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||||
if func_attrs_reuse is not None:
|
||||
llvmlite.function_set_attrs(func, func_attrs_reuse)
|
||||
else:
|
||||
# 创建新的 LLVM 函数(使用 SHA1 混淆名)
|
||||
func = llvmlite.create_function(pool, mod, mangled_name, ret_ty)
|
||||
if func is None:
|
||||
fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_cf is not None:
|
||||
viperlib.snprintf(fb_cf, 1024, "create_function %s failed", fd.name)
|
||||
VLogger.error(fb_cf, "FUNC")
|
||||
return 0
|
||||
|
||||
# 提取 @c.Attribute 装饰器属性并设置到函数
|
||||
func_attrs: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules)
|
||||
if func_attrs is not None:
|
||||
llvmlite.function_set_attrs(func, func_attrs)
|
||||
|
||||
# 提取默认参数信息
|
||||
tfd_defaults: t.CVoid | t.CPtr = None
|
||||
tfd_default_count: int = 0
|
||||
tfd_param_count: int = 0
|
||||
if args_node is not None:
|
||||
tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if tfd_ags.args is not None:
|
||||
tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args
|
||||
tfd_param_count = tfd_alist.__len__()
|
||||
if tfd_ags.defaults is not None:
|
||||
tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults
|
||||
tfd_defaults = tfd_dlist
|
||||
tfd_default_count = tfd_dlist.__len__()
|
||||
|
||||
# 注册到函数表
|
||||
max_funcs: int = 256
|
||||
if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs,
|
||||
tfd_defaults, tfd_default_count, tfd_param_count) == 0:
|
||||
trans._func_count = func_count + 1
|
||||
|
||||
# 添加参数(支持类型注解)
|
||||
if args_node is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = alist.__len__()
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is not None and arg.arg is not None:
|
||||
# t.CVoid 表示空参:跳过,不添加到函数签名
|
||||
if arg.annotation is not None:
|
||||
if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0:
|
||||
continue
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg.annotation, imported_modules, from_imports, trans)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
# 创建 entry 块
|
||||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None:
|
||||
return 0
|
||||
|
||||
# 创建函数专属 builder
|
||||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||||
if func_builder is None:
|
||||
return 0
|
||||
llvmlite.position_at_end(func_builder, entry_blk)
|
||||
|
||||
# 进入函数作用域(嵌套符号表)
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
|
||||
|
||||
# 为参数创建 alloca
|
||||
if args_node is not None:
|
||||
ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags2.args is not None:
|
||||
alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args
|
||||
an2: t.CSizeT = alist2.__len__()
|
||||
for ai2 in range(an2):
|
||||
arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2))
|
||||
if arg2 is not None and arg2.arg is not None:
|
||||
# t.CVoid 表示空参:跳过,不创建 alloca
|
||||
if arg2.annotation is not None:
|
||||
if HandlesType._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0:
|
||||
continue
|
||||
param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg2.annotation is not None:
|
||||
resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg2.annotation, imported_modules, from_imports, trans)
|
||||
if resolved2 is not None:
|
||||
param_ty2 = resolved2
|
||||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2)
|
||||
if alloca is not None:
|
||||
HandlesVar.define_var(trans.SymTab, arg2.arg, alloca)
|
||||
# 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体)
|
||||
if arg2.annotation is not None:
|
||||
cls_nm: str = HandlesType.extract_class_name_from_annotation(
|
||||
arg2.annotation, imported_modules)
|
||||
if cls_nm is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
trans.SymTab, arg2.arg, cls_nm)
|
||||
pname2: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if pname2 is not None:
|
||||
viperlib.snprintf(pname2, 32, "%%%s", arg2.arg)
|
||||
param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(
|
||||
pool, param_ty2, pname2)
|
||||
llvmlite.build_store(func_builder, param_val, alloca)
|
||||
# 保存模块级作用域状态(仅非变量表相关)
|
||||
old_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
old_global_count: int = trans._global_name_count
|
||||
old_nonlocal_count: int = trans._nonlocal_name_count
|
||||
old_env_count: int = trans._closure_env_count
|
||||
|
||||
trans._cur_func = func
|
||||
trans._cur_builder = func_builder
|
||||
# 清空 global/nonlocal 名称集合(新函数作用域)
|
||||
HT.clear_scope_names(trans)
|
||||
|
||||
# 预扫描函数体:为局部变量提前创建 alloca
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
if body is not None:
|
||||
bn: t.CSizeT = body.__len__()
|
||||
for bi in range(bn):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.pre_scan_allocas(trans, stmt)
|
||||
|
||||
# 翻译函数体
|
||||
if body is not None:
|
||||
bn2: t.CSizeT = body.__len__()
|
||||
for bi2 in range(bn2):
|
||||
stmt2: ast.AST | t.CPtr = body.get(bi2)
|
||||
if stmt2 is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt2)
|
||||
|
||||
# 如果函数体最后一条语句不是 Return,添加隐式 ret
|
||||
last_is_return: int = 0
|
||||
if body is not None:
|
||||
bn3: t.CSizeT = body.__len__()
|
||||
if bn3 > 0:
|
||||
last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||||
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
|
||||
last_is_return = 1
|
||||
if last_is_return == 0:
|
||||
if llvmlite.builder_cur_block_is_terminated(func_builder) == 0:
|
||||
# 根据返回类型生成正确的零值返回
|
||||
_is_void: int = 0
|
||||
_is_ptr: int = 0
|
||||
if ret_ty is not None:
|
||||
match ret_ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
_is_void = 1
|
||||
case llvmlite.LLVMType.Ptr(_pe):
|
||||
_is_ptr = 1
|
||||
if _is_void != 0:
|
||||
llvmlite.build_ret_void(func_builder)
|
||||
elif _is_ptr != 0:
|
||||
_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
|
||||
llvmlite.build_ret(func_builder, _null_val)
|
||||
else:
|
||||
_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
llvmlite.build_ret(func_builder, _zero_val)
|
||||
|
||||
# 恢复模块级作用域(退出函数作用域)
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
trans._cur_func = old_func
|
||||
trans._cur_builder = old_builder
|
||||
trans._global_name_count = old_global_count
|
||||
trans._nonlocal_name_count = old_nonlocal_count
|
||||
trans._closure_env_count = old_env_count
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_nested_function_def - 嵌套函数提升 + 闭包创建
|
||||
#
|
||||
# 将嵌套函数提升为顶层函数 @__closure_{name}(i8* %env) -> i32,
|
||||
# 在父函数中创建闭包对象 {i8* fn_ptr, i8* env_ptr} 并存储到
|
||||
# 以函数名命名的局部变量中。
|
||||
#
|
||||
# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配)
|
||||
# Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节)
|
||||
# ============================================================
|
||||
def translate_nested_function_def(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译嵌套函数定义:提升为顶层函数 + 创建闭包"""
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
func_name: str = fd.name
|
||||
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
# 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突)
|
||||
promoted_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if promoted_name is not None:
|
||||
viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name)
|
||||
mangled_promoted: str = _mangle_name(trans, promoted_name)
|
||||
|
||||
# 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env)
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||||
pool, mod, mangled_promoted, i32_ty)
|
||||
if func is None:
|
||||
return 0
|
||||
llvmlite.add_param(pool, func, i8_ptr_ty, "%env")
|
||||
|
||||
# 3. 创建 entry 块 + builder
|
||||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None:
|
||||
return 0
|
||||
func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func)
|
||||
if func_builder is None:
|
||||
return 0
|
||||
llvmlite.position_at_end(func_builder, entry_blk)
|
||||
|
||||
# 4. 进入嵌套函数作用域(嵌套符号表)
|
||||
HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION)
|
||||
|
||||
# 5. 创建 _env_ptr alloca 并存储 %env 参数
|
||||
env_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, i8_ptr_ty)
|
||||
if env_alloca is not None:
|
||||
HandlesVar.define_var(trans.SymTab, "_env_ptr", env_alloca)
|
||||
env_param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "%env")
|
||||
llvmlite.build_store(func_builder, env_param_val, env_alloca)
|
||||
|
||||
# 6. 保存父函数作用域状态(仅非变量表相关)
|
||||
old_func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
old_func_name: str = trans._cur_func_name
|
||||
old_global_count: int = trans._global_name_count
|
||||
old_nonlocal_count: int = trans._nonlocal_name_count
|
||||
old_env_count: int = trans._closure_env_count
|
||||
|
||||
# 7. 切换到嵌套函数作用域 + 清空 scope names
|
||||
trans._cur_func = func
|
||||
trans._cur_builder = func_builder
|
||||
trans._cur_func_name = func_name
|
||||
HT.clear_scope_names(trans)
|
||||
|
||||
# 8. 预扫描函数体:为局部变量提前创建 alloca
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = fd.children
|
||||
if body is not None:
|
||||
bn: t.CSizeT = body.__len__()
|
||||
for bi in range(bn):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.pre_scan_allocas(trans, stmt)
|
||||
|
||||
# 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names)
|
||||
if body is not None:
|
||||
bn2: t.CSizeT = body.__len__()
|
||||
for bi2 in range(bn2):
|
||||
stmt2: ast.AST | t.CPtr = body.get(bi2)
|
||||
if stmt2 is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt2)
|
||||
|
||||
# 10. 隐式 ret
|
||||
last_is_return: int = 0
|
||||
if body is not None:
|
||||
bn3: t.CSizeT = body.__len__()
|
||||
if bn3 > 0:
|
||||
last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1)
|
||||
if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return:
|
||||
last_is_return = 1
|
||||
if last_is_return == 0:
|
||||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
llvmlite.build_ret(func_builder, zero_val)
|
||||
|
||||
# 11. 保存嵌套函数的 nonlocal 信息
|
||||
nested_nonlocal_count: int = trans._nonlocal_name_count
|
||||
|
||||
# 12. 退出嵌套函数作用域,回到父函数作用域(保留 _nonlocal_names 用于 env 创建)
|
||||
HandlesVar.exit_scope(trans.SymTab)
|
||||
trans._cur_func = old_func
|
||||
trans._cur_builder = old_builder
|
||||
# NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值
|
||||
|
||||
# 13. 在父函数中创建闭包对象
|
||||
parent_builder: llvmlite.IRBuilder | t.CPtr = old_builder
|
||||
if parent_builder is None:
|
||||
# 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态
|
||||
trans._cur_func_name = old_func_name
|
||||
trans._global_name_count = old_global_count
|
||||
trans._nonlocal_name_count = old_nonlocal_count
|
||||
trans._closure_env_count = old_env_count
|
||||
return 0
|
||||
|
||||
# 13a. 创建 env: malloc(4 * nested_nonlocal_count) — env 直接存储 i32 值
|
||||
env_ptr: llvmlite.Value | t.CPtr = None
|
||||
if nested_nonlocal_count > 0:
|
||||
env_size: t.CInt64T = nested_nonlocal_count * 4
|
||||
env_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, env_size)
|
||||
if env_size_val is not None:
|
||||
env_size_val.Next = None
|
||||
env_ptr = llvmlite.build_call(
|
||||
parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0)
|
||||
|
||||
# 为每个 nonlocal 变量存储值到 env
|
||||
if env_ptr is not None:
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty)
|
||||
for ni in range(nested_nonlocal_count):
|
||||
# 从 _nonlocal_names 缓冲区读取名称
|
||||
name_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + ni * 8
|
||||
nl_slot: str | t.CPtr = (t.CVoid | t.CPtr)(name_addr)
|
||||
nl_name: str = nl_slot[0]
|
||||
if nl_name is not None:
|
||||
# 在父函数作用域中查找(Current 已回到父作用域)
|
||||
var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, nl_name)
|
||||
if var_alloca is not None:
|
||||
# 加载变量值
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if var_alloca.Ty is not None:
|
||||
var_ty = var_alloca.Ty.Pointee
|
||||
if var_ty is None:
|
||||
var_ty = i32_ty
|
||||
var_val: llvmlite.Value | t.CPtr = llvmlite.build_load(
|
||||
parent_builder, var_ty, var_alloca)
|
||||
if var_val is not None:
|
||||
# GEP to env[ni*4]
|
||||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, ni * 4)
|
||||
slot: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||||
parent_builder, i8_ty, env_ptr, offset_val)
|
||||
if slot is not None:
|
||||
# bitcast to i32* and store value
|
||||
slot_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
parent_builder, slot, i32_ptr_ty)
|
||||
if slot_typed is not None:
|
||||
# 类型转换(确保 var_val 是 i32)
|
||||
coerced_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(
|
||||
parent_builder, var_val, i32_ty)
|
||||
if coerced_val is not None:
|
||||
llvmlite.build_store(parent_builder, coerced_val, slot_typed)
|
||||
|
||||
# 13b. 创建闭包结构: malloc(16)
|
||||
closure_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 16)
|
||||
if closure_size_val is not None:
|
||||
closure_size_val.Next = None
|
||||
closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call(
|
||||
parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0)
|
||||
if closure_ptr is None:
|
||||
# malloc 失败,恢复状态
|
||||
trans._cur_func_name = old_func_name
|
||||
trans._global_name_count = old_global_count
|
||||
trans._nonlocal_name_count = old_nonlocal_count
|
||||
trans._closure_env_count = old_env_count
|
||||
return 0
|
||||
|
||||
# 13c. 存储 fn_ptr 到 offset 0
|
||||
# 创建函数指针类型 i32(i8*)*
|
||||
fn_param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty)
|
||||
fn_func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, fn_param_node, 1)
|
||||
fn_func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, fn_func_ty)
|
||||
|
||||
# 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名)
|
||||
fn_ptr_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if fn_ptr_name is not None:
|
||||
# SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func")
|
||||
if string.strchr(mangled_promoted, '.') is not None:
|
||||
viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted)
|
||||
else:
|
||||
viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted)
|
||||
fn_ptr_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name)
|
||||
|
||||
# bitcast 函数指针到 i8*(闭包存储 i8* 类型)
|
||||
fn_as_i8ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
parent_builder, fn_ptr_val, i8_ptr_ty)
|
||||
fn_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty))
|
||||
if fn_slot is not None and fn_as_i8ptr is not None:
|
||||
llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot)
|
||||
|
||||
# 13d. 存储 env_ptr 到 offset 8
|
||||
eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8)
|
||||
env_slot_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(
|
||||
parent_builder, i8_ty, closure_ptr, eight_val)
|
||||
if env_slot_addr is not None:
|
||||
env_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(
|
||||
parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty))
|
||||
if env_slot is not None:
|
||||
if env_ptr is not None:
|
||||
llvmlite.build_store(parent_builder, env_ptr, env_slot)
|
||||
else:
|
||||
# 无 nonlocal 变量,存储 null
|
||||
null_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "null")
|
||||
llvmlite.build_store(parent_builder, null_val, env_slot)
|
||||
|
||||
# 13e. 将闭包指针存储到父函数的局部变量 {func_name}
|
||||
closure_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(parent_builder, i8_ptr_ty)
|
||||
if closure_alloca is not None:
|
||||
llvmlite.build_store(parent_builder, closure_ptr, closure_alloca)
|
||||
HandlesVar.define_var(trans.SymTab, func_name, closure_alloca)
|
||||
|
||||
# 14. 恢复 scope names
|
||||
trans._cur_func_name = old_func_name
|
||||
trans._global_name_count = old_global_count
|
||||
trans._nonlocal_name_count = old_nonlocal_count
|
||||
trans._closure_env_count = old_env_count
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 创建 LLVM 函数(简单版本,仅声明)
|
||||
# ============================================================
|
||||
def create_function(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
name: str,
|
||||
args_node: ast.AST | t.CPtr,
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr:
|
||||
"""创建 LLVM 函数并添加参数"""
|
||||
if name is None or mod is None:
|
||||
return None
|
||||
|
||||
func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty)
|
||||
if func is None:
|
||||
return None
|
||||
|
||||
if args_node is not None:
|
||||
ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node)
|
||||
if ags.args is not None:
|
||||
alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args
|
||||
an: t.CSizeT = alist.__len__()
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
for ai in range(an):
|
||||
arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai))
|
||||
if arg is not None and arg.arg is not None:
|
||||
# t.CVoid 表示空参:跳过
|
||||
if arg.annotation is not None:
|
||||
if arg.annotation.kind() == ast.ASTKind.Attribute:
|
||||
at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation)
|
||||
if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0:
|
||||
continue
|
||||
param_ty: llvmlite.LLVMType | t.CPtr = i32_ty
|
||||
if arg.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, arg.annotation, None, None, None)
|
||||
if resolved is not None:
|
||||
param_ty = resolved
|
||||
pname: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if pname is not None:
|
||||
viperlib.snprintf(pname, 32, "%%%s", arg.arg)
|
||||
llvmlite.add_param(pool, func, param_ty, pname)
|
||||
|
||||
return func
|
||||
@@ -1,141 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
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.HandlesBody as HandlesBody
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesIf - if/elif/else 语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 翻译 if 语句为 LLVM IR 控制流:
|
||||
# br i1 %cond, label %then, label %else
|
||||
# then:
|
||||
# ... body ...
|
||||
# br label %end
|
||||
# else:
|
||||
# ... orelse ...
|
||||
# br label %end
|
||||
# end:
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class IfHandle(HandlesBase.Mixin):
|
||||
"""if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 if 语句,返回新增变量数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 if/elif/else 语句"""
|
||||
if node is None:
|
||||
return 0
|
||||
|
||||
trans: HT.Translator | t.CPtr = self.Trans
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(node)
|
||||
|
||||
# 1. 求值条件表达式
|
||||
cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, if_node.test,
|
||||
trans._funcs, trans._func_count, trans)
|
||||
|
||||
# 2. 转换为 i1 条件
|
||||
# Compare/Not 表达式已返回 i1,直接使用;其他类型与 0 比较
|
||||
if cond_val is None:
|
||||
cond_val = llvmlite.const_int32(pool, 0)
|
||||
cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty)
|
||||
if cond_bits == 1:
|
||||
cond_i1: llvmlite.Value | t.CPtr = cond_val
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
cond_i1 = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_NE, cond_val, zero)
|
||||
|
||||
# 3. 创建基本块(使用 trans._label_counter 生成唯一标签名,不与 SSA 名共享)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "if.then.%d", cnt)
|
||||
then_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "if.end.%d", cnt)
|
||||
merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 检查是否有 else 分支
|
||||
has_else: int = 0
|
||||
orelse_list: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse
|
||||
if orelse_list is not None:
|
||||
if orelse_list.__len__() > 0:
|
||||
has_else = 1
|
||||
|
||||
else_bb: llvmlite.BasicBlock | t.CPtr = None
|
||||
if has_else == 1:
|
||||
viperlib.snprintf(name_buf, 32, "if.else.%d", cnt)
|
||||
else_bb = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 4. 发射条件分支
|
||||
if has_else == 1:
|
||||
llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb)
|
||||
else:
|
||||
llvmlite.build_cond_br(builder, cond_i1, then_bb, merge_bb)
|
||||
|
||||
# 5. 翻译 then body
|
||||
llvmlite.position_at_end(builder, then_bb)
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = if_node.children
|
||||
if body is not None:
|
||||
body_count: t.CSizeT = body.__len__()
|
||||
for bi in range(body_count):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
|
||||
# then 块未终止则跳到 merge
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, merge_bb)
|
||||
|
||||
# 6. 翻译 else body(若有)
|
||||
if has_else == 1:
|
||||
llvmlite.position_at_end(builder, else_bb)
|
||||
else_count: t.CSizeT = orelse_list.__len__()
|
||||
for ei in range(else_count):
|
||||
stmt: ast.AST | t.CPtr = orelse_list.get(ei)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, merge_bb)
|
||||
|
||||
# 7. 定位到 merge 块继续后续代码
|
||||
llvmlite.position_at_end(builder, merge_bb)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewIfHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewIfHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr:
|
||||
h: IfHandle | t.CPtr = pool.alloc(IfHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, IfHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,596 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import memhub
|
||||
import string
|
||||
import stdlib
|
||||
import viperlib
|
||||
import stdio
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesImports - 导入语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 管理 _imported_modules 和 _from_imports 字符串
|
||||
# 注意:str = bytes = t.CChar | t.CPtr = i8*
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模块级工具函数(保留供外部调用)
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 添加已导入模块名
|
||||
# ============================================================
|
||||
def add_imported_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
imported_modules: str,
|
||||
name: str) -> str:
|
||||
"""记录已导入的模块名,返回新的 imported_modules 字符串指针"""
|
||||
if name is None:
|
||||
return imported_modules
|
||||
if imported_modules is None:
|
||||
nlen: t.CSizeT = string.strlen(name)
|
||||
buf: t.CChar | t.CPtr = pool.alloc(nlen + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, name)
|
||||
return buf
|
||||
return None
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(imported_modules)
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
new_len: t.CSizeT = old_len + 1 + name_len
|
||||
buf2: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf2 is not None:
|
||||
string.strcpy(buf2, imported_modules)
|
||||
buf2[old_len] = ' '
|
||||
string.strcpy(buf2 + old_len + 1, name)
|
||||
return buf2
|
||||
return imported_modules
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 检查模块是否已导入
|
||||
# ============================================================
|
||||
def is_module_imported(imported_modules: str, name: str) -> int:
|
||||
"""检查模块是否已导入(词边界精确匹配,避免子串误匹配)"""
|
||||
if name is None or imported_modules is None:
|
||||
return 0
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = imported_modules
|
||||
total_len: t.CSizeT = string.strlen(imported_modules)
|
||||
ci: t.CSizeT = 0
|
||||
while ci < total_len:
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
word_start: t.CSizeT = ci
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
word_len: t.CSizeT = ci - word_start
|
||||
if word_len == name_len:
|
||||
match: int = 1
|
||||
for ei in range(name_len):
|
||||
if cur[word_start + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
if match == 1:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 添加 from-import 名称映射
|
||||
# ============================================================
|
||||
def add_from_import(pool: memhub.MemBuddy | t.CPtr,
|
||||
from_imports: str,
|
||||
local_name: str,
|
||||
module_name: str,
|
||||
original_name: str = None) -> str:
|
||||
"""添加 from-import 映射,返回新的 from_imports 字符串
|
||||
|
||||
格式:
|
||||
无别名: "local_name:module_name"
|
||||
有别名: "local_name:module_name:original_name"
|
||||
(original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰)
|
||||
"""
|
||||
if local_name is None or module_name is None:
|
||||
return from_imports
|
||||
entry: t.CChar | t.CPtr = pool.alloc(256)
|
||||
if entry is None:
|
||||
return from_imports
|
||||
if original_name is not None and original_name != local_name:
|
||||
viperlib.snprintf(entry, 256, "%s:%s:%s", local_name, module_name, original_name)
|
||||
else:
|
||||
viperlib.snprintf(entry, 256, "%s:%s", local_name, module_name)
|
||||
if from_imports is None:
|
||||
return entry
|
||||
else:
|
||||
old_len: t.CSizeT = string.strlen(from_imports)
|
||||
entry_len: t.CSizeT = string.strlen(entry)
|
||||
new_len: t.CSizeT = old_len + 1 + entry_len
|
||||
buf: t.CChar | t.CPtr = pool.alloc(new_len + 1)
|
||||
if buf is not None:
|
||||
string.strcpy(buf, from_imports)
|
||||
buf[old_len] = ' '
|
||||
string.strcpy(buf + old_len + 1, entry)
|
||||
return buf
|
||||
return from_imports
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回原始函数名(别名场景)
|
||||
#
|
||||
# 对于 from X import Y as Z,返回 Y(源模块中的真实函数名)。
|
||||
# 无别名时返回 None(local_name 即为原始名)。
|
||||
# ============================================================
|
||||
def lookup_from_import_original(from_imports: str,
|
||||
local_name: str) -> str:
|
||||
"""查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到"""
|
||||
if local_name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(local_name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到第一个 ':' 的位置
|
||||
colon1: t.CSizeT = ci
|
||||
while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ':
|
||||
colon1 += 1
|
||||
if colon1 >= total_len or cur[colon1] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon1 - ci
|
||||
# 跳过 star import
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
continue
|
||||
# 比较名称
|
||||
if entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != local_name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
# 找到匹配,检查是否有第三个字段(原始名)
|
||||
pos: t.CSizeT = colon1 + 1
|
||||
# 跳过模块名
|
||||
while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0':
|
||||
pos += 1
|
||||
if pos < total_len and cur[pos] == ':':
|
||||
# 有第三个字段: original_name
|
||||
orig_start: t.CSizeT = pos + 1
|
||||
orig_end: t.CSizeT = orig_start
|
||||
while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0':
|
||||
orig_end += 1
|
||||
orig_len: t.CSizeT = orig_end - orig_start
|
||||
if orig_len > 0:
|
||||
orig_buf: str = cur + orig_start
|
||||
# 返回指向内部的指针(调用方需在使用期内保持 from_imports 有效)
|
||||
return orig_buf
|
||||
return None
|
||||
return None
|
||||
# 跳到下一个条目
|
||||
ci = colon1
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 查找 from-import 名称 → 返回模块名或 None
|
||||
#
|
||||
# allow_star_fallback: 是否允许 star import 回退(默认 1=允许)。
|
||||
# 当查询明确模块名(如 "BuildPipeline")时,应传 0 禁用回退,
|
||||
# 避免被 star import 模块名误导(如 from stdint import * 后
|
||||
# 查询 "BuildPipeline" 错误回退到 "stdint")。
|
||||
# ============================================================
|
||||
def lookup_from_import(from_imports: str, name: str,
|
||||
allow_star_fallback: int = 1) -> str:
|
||||
"""查找 from-import 名称,返回模块名或 None
|
||||
|
||||
支持 star import: 如果 from_imports 中有 "*:module" 条目,
|
||||
且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。
|
||||
"""
|
||||
if name is None or from_imports is None:
|
||||
return None
|
||||
name_len: t.CSizeT = string.strlen(name)
|
||||
cur: t.CChar | t.CPtr = from_imports
|
||||
ci: t.CSizeT = 0
|
||||
total_len: t.CSizeT = string.strlen(from_imports)
|
||||
star_mod: str = None
|
||||
while ci < total_len:
|
||||
# 跳过前导空格
|
||||
while ci < total_len and cur[ci] == ' ':
|
||||
ci += 1
|
||||
if ci >= total_len:
|
||||
break
|
||||
# 找到 ':' 的位置
|
||||
colon_pos: t.CSizeT = ci
|
||||
while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ':
|
||||
colon_pos += 1
|
||||
if colon_pos >= total_len or cur[colon_pos] != ':':
|
||||
break
|
||||
entry_name_len: t.CSizeT = colon_pos - ci
|
||||
# 检测 star import ("*:module")
|
||||
if entry_name_len == 1 and cur[ci] == '*':
|
||||
mod_start: t.CSizeT = colon_pos + 1
|
||||
mod_end: t.CSizeT = mod_start
|
||||
while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':':
|
||||
mod_end += 1
|
||||
star_mod = cur + mod_start
|
||||
# 比较名称
|
||||
elif entry_name_len == name_len:
|
||||
match: int = 1
|
||||
ei: t.CSizeT = 0
|
||||
while ei < name_len:
|
||||
if cur[ci + ei] != name[ei]:
|
||||
match = 0
|
||||
break
|
||||
ei += 1
|
||||
if match == 1:
|
||||
mod_start2: t.CSizeT = colon_pos + 1
|
||||
mod_end2: t.CSizeT = mod_start2
|
||||
# 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符)
|
||||
while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':':
|
||||
mod_end2 += 1
|
||||
return cur + mod_start2
|
||||
# 跳到下一个条目
|
||||
ci = colon_pos
|
||||
while ci < total_len and cur[ci] != ' ':
|
||||
ci += 1
|
||||
# 未找到精确匹配,仅在允许时回退到 star import
|
||||
if allow_star_fallback == 0:
|
||||
return None
|
||||
return star_mod
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 全局 re-export 映射表(module_sha1 + func_name → source_module)
|
||||
#
|
||||
# 当 ast/__init__.py 中有 from .lexer import _lexer_init 时,
|
||||
# _lexer_init 被 re-export 为 ast._lexer_init。
|
||||
# 跨模块调用 ast._lexer_init(...) 需使用 ast.lexer 的 SHA1 混淆,
|
||||
# 而非 ast 的 SHA1。
|
||||
#
|
||||
# 数据布局:
|
||||
# _g_reexport_sha1s: 每条 17 字节(SHA1 16字符 + null)
|
||||
# _g_reexport_funcs: 每条 64 字节(函数名 + null)
|
||||
# _g_reexport_srcs: 每条 64 字节(源模块名 + null)
|
||||
# ============================================================
|
||||
MAX_REEXPORT: t.CDefine = 512
|
||||
|
||||
_g_reexport_sha1s: bytes = None
|
||||
_g_reexport_funcs: bytes = None
|
||||
_g_reexport_srcs: bytes = None
|
||||
_g_reexport_count: int = 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# register_reexport - 注册 re-export 映射
|
||||
#
|
||||
# 在 HandleImportFromNames 中调用:当处理 from .X import Y 时,
|
||||
# 记录当前模块(通过 ModuleSha1)re-export 了函数 Y,源模块为 X。
|
||||
#
|
||||
# 幂等:重复注册相同映射不会增加条目。
|
||||
# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。
|
||||
# ============================================================
|
||||
def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int:
|
||||
"""注册 re-export 映射(幂等),返回 0 成功,-1 失败"""
|
||||
global _g_reexport_sha1s, _g_reexport_funcs, _g_reexport_srcs, _g_reexport_count
|
||||
if mod_sha1 is None or func_name is None or source_module is None:
|
||||
return -1
|
||||
# 懒初始化
|
||||
if _g_reexport_sha1s is None:
|
||||
_g_reexport_sha1s = stdlib.malloc(MAX_REEXPORT * 17)
|
||||
_g_reexport_funcs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
_g_reexport_srcs = stdlib.malloc(MAX_REEXPORT * 64)
|
||||
if _g_reexport_sha1s is None or _g_reexport_funcs is None or _g_reexport_srcs is None:
|
||||
return -1
|
||||
string.memset(_g_reexport_sha1s, 0, MAX_REEXPORT * 17)
|
||||
string.memset(_g_reexport_funcs, 0, MAX_REEXPORT * 64)
|
||||
string.memset(_g_reexport_srcs, 0, MAX_REEXPORT * 64)
|
||||
if _g_reexport_count >= MAX_REEXPORT:
|
||||
return -1
|
||||
# 幂等检查:查找是否已存在相同映射
|
||||
for i in range(_g_reexport_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0:
|
||||
# 已存在,更新 source_module(以防变化)
|
||||
string.strcpy(_g_reexport_srcs + fidx, source_module)
|
||||
return 0
|
||||
# 添加新条目
|
||||
idx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 17
|
||||
fidx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 64
|
||||
string.strcpy(_g_reexport_sha1s + idx2, mod_sha1)
|
||||
string.strcpy(_g_reexport_funcs + fidx2, func_name)
|
||||
string.strcpy(_g_reexport_srcs + fidx2, source_module)
|
||||
_g_reexport_count += 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_reexport - 查找 re-export 映射
|
||||
#
|
||||
# 给定模块 SHA1 和函数名,返回源模块名(如 "ast.lexer")或 None。
|
||||
# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。
|
||||
# ============================================================
|
||||
def lookup_reexport(mod_sha1: str, func_name: str) -> str:
|
||||
"""查找 re-export 映射,返回源模块名或 None"""
|
||||
if mod_sha1 is None or func_name is None:
|
||||
return None
|
||||
if _g_reexport_sha1s is None or _g_reexport_count <= 0:
|
||||
return None
|
||||
for i in range(_g_reexport_count):
|
||||
sidx: t.CSizeT = t.CSizeT(i) * 17
|
||||
fidx: t.CSizeT = t.CSizeT(i) * 64
|
||||
if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0:
|
||||
if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0:
|
||||
return _g_reexport_srcs + fidx
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _resolve_relative_module - 解析相对导入为完整模块名
|
||||
#
|
||||
# 对于 from .X import Y(level=1, module="X")在包 pkg 中:
|
||||
# 解析为 "pkg.X"
|
||||
# 对于 from . import Y(level=1, module=None)在包 pkg 中:
|
||||
# 解析为 "pkg"
|
||||
# 对于 from ..X import Y(level=2, module="X")在包 pkg.sub 中:
|
||||
# 解析为 "pkg.X"(先从 pkg.sub 上溯一级到 pkg,再追加 .X)
|
||||
#
|
||||
# Args:
|
||||
# pool: 内存池
|
||||
# current_package: 当前文件所属包名(如 "llvmlite"),None 表示无包
|
||||
# level: 相对导入级别(0=绝对,1=., 2=..)
|
||||
# module: ImportFrom 的 module 字段(可能为 None)
|
||||
#
|
||||
# Returns:
|
||||
# 解析后的完整模块名;绝对导入(level<=0)直接返回 module;
|
||||
# 无法解析时返回 module(回退到原始值)
|
||||
# ============================================================
|
||||
def _resolve_relative_module(pool: memhub.MemBuddy | t.CPtr,
|
||||
current_package: str,
|
||||
level: t.CInt,
|
||||
module: str) -> str:
|
||||
"""解析相对导入为完整模块名"""
|
||||
if level <= 0:
|
||||
return module
|
||||
if current_package is None:
|
||||
return module
|
||||
|
||||
# 从 current_package 开始,上溯 (level-1) 级
|
||||
pkg: str = current_package
|
||||
up: t.CInt = level - 1
|
||||
while up > 0:
|
||||
pkg_len: t.CSizeT = string.strlen(pkg)
|
||||
last_dot: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < pkg_len:
|
||||
if pkg[i] == '.':
|
||||
last_dot = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无更多父级,包变为空
|
||||
pkg = None
|
||||
break
|
||||
# 截断到最后一个 '.' 处
|
||||
new_pkg: str = pool.alloc(last_dot + 1)
|
||||
if new_pkg is None:
|
||||
return module
|
||||
string.strncpy(new_pkg, pkg, last_dot)
|
||||
new_pkg[last_dot] = '\0'
|
||||
pkg = new_pkg
|
||||
up -= 1
|
||||
|
||||
if module is None:
|
||||
# from . import Y → 模块就是包本身
|
||||
return pkg
|
||||
if pkg is None:
|
||||
# 包已上溯到空,直接用 module
|
||||
return module
|
||||
# 拼接 pkg + "." + module
|
||||
pkg_len2: t.CSizeT = string.strlen(pkg)
|
||||
mod_len: t.CSizeT = string.strlen(module)
|
||||
buf: str = pool.alloc(pkg_len2 + 1 + mod_len + 1)
|
||||
if buf is None:
|
||||
return module
|
||||
string.strcpy(buf, pkg)
|
||||
buf[pkg_len2] = '.'
|
||||
string.strcpy(buf + pkg_len2 + 1, module)
|
||||
return buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# compute_package_from_relpath - 从相对路径计算包名
|
||||
#
|
||||
# 包名 = 文件所在目录路径,将 / 和 \ 替换为 .
|
||||
# 对于顶级文件(无目录分隔符),返回 None
|
||||
#
|
||||
# 示例:
|
||||
# "llvmlite/__init__.py" → "llvmlite"
|
||||
# "llvmlite/__types.py" → "llvmlite"
|
||||
# "ast/parser.py" → "ast"
|
||||
# "ast.py" → None(顶级文件)
|
||||
# ============================================================
|
||||
def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr,
|
||||
rel_path: str) -> str:
|
||||
"""从相对路径计算包名(目录部分,分隔符替换为 .)"""
|
||||
if rel_path is None:
|
||||
return None
|
||||
rlen: t.CSizeT = string.strlen(rel_path)
|
||||
# 找最后一个 / 或 \
|
||||
last_sep: t.CSizeT = 0
|
||||
found: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i < rlen:
|
||||
ch: t.CChar = rel_path[i]
|
||||
if ch == '/' or ch == '\\':
|
||||
last_sep = i
|
||||
found = 1
|
||||
i += 1
|
||||
if found == 0:
|
||||
# 无目录分隔符 → 顶级文件,无包
|
||||
return None
|
||||
# 复制目录部分,将 / 和 \ 替换为 .
|
||||
dir_len: t.CSizeT = last_sep
|
||||
buf: str = pool.alloc(dir_len + 1)
|
||||
if buf is None:
|
||||
return None
|
||||
j: t.CSizeT = 0
|
||||
while j < dir_len:
|
||||
ch2: t.CChar = rel_path[j]
|
||||
if ch2 == '/' or ch2 == '\\':
|
||||
buf[j] = '.'
|
||||
else:
|
||||
buf[j] = ch2
|
||||
j += 1
|
||||
buf[dir_len] = '\0'
|
||||
return buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ImportsHandle - 导入语句处理器(Mixin 继承模式)
|
||||
#
|
||||
# 方法版本:直接更新 trans._imported_modules / trans._from_imports
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ImportsHandle(HandlesBase.Mixin):
|
||||
"""导入语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# HandleImport - 处理 import 语句,更新 trans._imported_modules
|
||||
# ============================================================
|
||||
def HandleImport(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 import 语句,返回 0"""
|
||||
imp: ast.Import | t.CPtr = (ast.Import | t.CPtr)(node)
|
||||
if imp is None:
|
||||
return 0
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = imp.names
|
||||
if names is None:
|
||||
return 0
|
||||
nn: t.CSizeT = names.__len__()
|
||||
for ni in range(nn):
|
||||
alias: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(names.get(ni))
|
||||
if alias is not None and alias.name is not None:
|
||||
pool_val: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
im_val: str = self.Trans._imported_modules
|
||||
self.Trans._imported_modules = add_imported_module(
|
||||
pool_val, im_val, alias.name)
|
||||
# 别名也加入导入模块列表(用于模块限定构造器检查 Module.Class())
|
||||
if alias.asname is not None:
|
||||
self.Trans._imported_modules = add_imported_module(
|
||||
pool_val, self.Trans._imported_modules, alias.asname)
|
||||
# 别名也加入 from_imports(asname:fullname),
|
||||
# 使 HT.func() 跨模块调用能通过 from_imports 查找别名→完整模块名→SHA1
|
||||
# 否则 _lookup_module_sha1("HT") 找不到(mod_arr 只存文件名 HandlesTranslator)
|
||||
self.Trans._from_imports = add_from_import(
|
||||
pool_val, self.Trans._from_imports, alias.asname, alias.name)
|
||||
else:
|
||||
# 无别名时(import a.b.c),将顶层包名 "a" 也加入 _imported_modules,
|
||||
# 使 a.b.c 作为属性访问的 base 被翻译时能通过 is_module_imported("a") 检查
|
||||
dot_ptr: str = string.strstr(alias.name, '.')
|
||||
if dot_ptr is not None:
|
||||
pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_ptr) - t.CUInt64T(alias.name))
|
||||
if pkg_len > 0 and pkg_len < 256:
|
||||
pkg_buf: bytes = pool_val.alloc(pkg_len + 1)
|
||||
if pkg_buf is not None:
|
||||
string.strncpy(pkg_buf, alias.name, pkg_len)
|
||||
pkg_buf[pkg_len] = '\0'
|
||||
self.Trans._imported_modules = add_imported_module(
|
||||
pool_val, self.Trans._imported_modules, pkg_buf)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# HandleImportFromModule - 处理 from X import Y 的模块部分
|
||||
#
|
||||
# 对相对导入(level > 0),使用 trans.CurrentPackage 解析为
|
||||
# 完整模块名(如 __types → llvmlite.__types),确保 .deps.txt
|
||||
# 记录的模块名与 SHA1 映射表一致。
|
||||
# ============================================================
|
||||
def HandleImportFromModule(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 from X import Y 的模块部分,更新 trans._imported_modules"""
|
||||
impf: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(node)
|
||||
if impf is None:
|
||||
return 0
|
||||
# 解析模块名:相对导入需补充包前缀
|
||||
resolved: str = _resolve_relative_module(
|
||||
self.Trans.Pool, self.Trans.CurrentPackage,
|
||||
impf.level, impf.module)
|
||||
if resolved is not None:
|
||||
self.Trans._imported_modules = add_imported_module(
|
||||
self.Trans.Pool, self.Trans._imported_modules, resolved)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# HandleImportFromNames - 处理 from X import Y 的名称部分
|
||||
#
|
||||
# 同样使用解析后的完整模块名,确保 from-import 映射
|
||||
# (如 LLVMType:llvmlite.__types)能正确查到 SHA1。
|
||||
# ============================================================
|
||||
def HandleImportFromNames(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""处理 from X import Y 的名称部分,更新 trans._from_imports"""
|
||||
impf: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(node)
|
||||
if impf is None:
|
||||
return 0
|
||||
# 解析模块名:相对导入需补充包前缀
|
||||
resolved: str = _resolve_relative_module(
|
||||
self.Trans.Pool, self.Trans.CurrentPackage,
|
||||
impf.level, impf.module)
|
||||
if resolved is not None:
|
||||
names: list[ast.AST | t.CPtr] | t.CPtr = impf.names
|
||||
if names is not None:
|
||||
nn: t.CSizeT = names.__len__()
|
||||
for ni in range(nn):
|
||||
alias: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(names.get(ni))
|
||||
if alias is not None and alias.name is not None:
|
||||
local_name: str = alias.name
|
||||
orig_name: str = None
|
||||
if alias.asname is not None:
|
||||
local_name = alias.asname
|
||||
orig_name = alias.name
|
||||
self.Trans._from_imports = add_from_import(
|
||||
self.Trans.Pool, self.Trans._from_imports,
|
||||
local_name, resolved, orig_name)
|
||||
# 命名空间隔离:from-import 的名称标记为可见结构体
|
||||
HandlesStruct.add_visible_struct(self.Trans.Pool, local_name)
|
||||
# 注册 re-export 映射:当前模块 re-export 了 local_name,源模块为 resolved
|
||||
# 使跨模块调用 module.func() 能解析到正确的源模块 SHA1
|
||||
if self.Trans.ModuleSha1 is not None:
|
||||
register_reexport(self.Trans.ModuleSha1, local_name, resolved)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewImportsHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewImportsHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ImportsHandle | t.CPtr:
|
||||
h: ImportsHandle | t.CPtr = pool.alloc(ImportsHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ImportsHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,492 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesMain - 模块级翻译入口 + wrapper main 创建
|
||||
#
|
||||
# 从 translator.py 拆分出来,负责:
|
||||
# 1. create_wrapper_main() - 无用户 main 时创建包装 main
|
||||
# 2. translate_children() - 遍历 AST 子节点并分派翻译
|
||||
#
|
||||
# trans 单参模式:所有共享状态从 trans 获取,无需 11 个参数
|
||||
# 注意: str = bytes = t.CChar | t.CPtr = i8*
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数
|
||||
#
|
||||
# 解决翻译顺序依赖问题:Phase 1b 按字母序翻译,后翻译的模块的
|
||||
# CExport 函数无法被先翻译的模块正确识别为裸名调用。
|
||||
# Phase 1a 预注册所有 CExport/State 函数名到全局表。
|
||||
# ============================================================
|
||||
def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""预注册 CExport/State 函数到全局表(仅注册,不生成 IR)"""
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node)
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
if trans is None or trans.ModuleSha1 is None:
|
||||
return 0
|
||||
|
||||
# 检查返回类型是否有 CExport 或 State 标记
|
||||
has_export: int = 0
|
||||
has_state: int = 0
|
||||
if fd.returns is not None:
|
||||
has_export = HandlesType.has_decorator_marker(fd.returns, "CExport")
|
||||
has_state = HandlesType.has_decorator_marker(fd.returns, "State")
|
||||
|
||||
if has_export != 0 or has_state != 0:
|
||||
HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# translate_children - 遍历 AST 子节点并分派翻译
|
||||
#
|
||||
# 对应 TransPyC translator._translate_children()
|
||||
# 共享状态从 trans 获取,imported_modules/from_imports 更新到 trans
|
||||
# ============================================================
|
||||
def translate_children(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr) -> int:
|
||||
"""遍历 tree.children 并翻译每个子节点
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is None:
|
||||
return 0
|
||||
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
added_total: int = 0
|
||||
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None: continue
|
||||
kd: int = child.kind()
|
||||
|
||||
# _declare_only == 0 时,_translate_module_level 已预处理导入语句,
|
||||
# 此处跳过避免重复处理(from_imports 条目重复)
|
||||
if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom):
|
||||
continue
|
||||
if kd == ast.ASTKind.Import:
|
||||
trans.ImportsH.HandleImport(child)
|
||||
elif kd == ast.ASTKind.ImportFrom:
|
||||
trans.ImportsH.HandleImportFromModule(child)
|
||||
trans.ImportsH.HandleImportFromNames(child)
|
||||
elif kd == ast.ASTKind.FunctionDef:
|
||||
# Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖)
|
||||
# Phase 1b 全量翻译:正常翻译函数体
|
||||
if trans._declare_only == 0:
|
||||
added: int = HandlesFunctions.translate_function_def(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 1:
|
||||
_register_cexport_from_funcdef(trans, child)
|
||||
elif kd == ast.ASTKind.ClassDef:
|
||||
# ClassDef 在模块级直接处理(不需要 builder)
|
||||
# _declare_only=2(import扫描模式)时跳过,只处理 import 依赖
|
||||
if trans._declare_only != 2:
|
||||
HandlesClassDef.translate_class_def(trans, child)
|
||||
elif trans._declare_only == 0 and trans._cur_builder is not None:
|
||||
# 有 builder → 委托 HandlesBody 分派
|
||||
added = HandlesBody.translate_stmt(trans, child)
|
||||
added_total += added
|
||||
elif kd == ast.ASTKind.AnnAssign and trans._declare_only != 2:
|
||||
# 模块级 AnnAssign
|
||||
# _declare_only=2(import扫描模式)时跳过
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine(在 handle_module_level_var 内部判断)
|
||||
# _declare_only=0(全量翻译)时处理所有模块级 AnnAssign
|
||||
added = handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
elif trans._declare_only == 0 and kd == ast.ASTKind.Assign:
|
||||
# 无 builder 的模块级 Assign → 创建全局变量(仅全量翻译模式)
|
||||
added = handle_module_level_var(trans, child)
|
||||
added_total += added
|
||||
|
||||
return added_total
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器
|
||||
#
|
||||
# 生成格式: [N x elem_ty] [elem_ty val0, elem_ty val1, ...]
|
||||
# 用于模块级 t.CArray 列表字面量初始化(不依赖 builder,直接生成常量初始化器)
|
||||
# ============================================================
|
||||
def _build_array_initializer_text(pool: memhub.MemBuddy | t.CPtr,
|
||||
var_ty: llvmlite.LLVMType | t.CPtr,
|
||||
list_node: ast.List | t.CPtr) -> str:
|
||||
"""从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败"""
|
||||
if var_ty is None or list_node is None:
|
||||
return None
|
||||
|
||||
# 重新进行类型转换,确保 TPV 编译器正确识别 ast.List 类型
|
||||
# (避免 init_list_node 初始值为 None 时类型推断退化为 t.CPtr)
|
||||
ln: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node)
|
||||
if ln is None:
|
||||
return None
|
||||
|
||||
# 从 var_ty 提取数组元素类型和数量
|
||||
elem_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
arr_count: t.CInt = 0
|
||||
match var_ty:
|
||||
case llvmlite.LLVMType.Array(et, cnt):
|
||||
elem_ty = et
|
||||
arr_count = cnt
|
||||
|
||||
if elem_ty is None or arr_count <= 0:
|
||||
return None
|
||||
|
||||
# 确定元素类型的 IR 表示
|
||||
elem_ir_ty: str = "i8"
|
||||
match elem_ty:
|
||||
case llvmlite.LLVMType.Int(bits):
|
||||
if bits == 8:
|
||||
elem_ir_ty = "i8"
|
||||
elif bits == 16:
|
||||
elem_ir_ty = "i16"
|
||||
elif bits == 32:
|
||||
elem_ir_ty = "i32"
|
||||
elif bits == 64:
|
||||
elem_ir_ty = "i64"
|
||||
|
||||
# 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别)
|
||||
elts: list[ast.AST | t.CPtr] | t.CPtr = ln.elts
|
||||
if elts is None:
|
||||
return None
|
||||
elts_count: t.CSizeT = elts.__len__()
|
||||
|
||||
# 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符
|
||||
buf_size: t.CSizeT = 64 + elts_count * 32
|
||||
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
|
||||
if buf is None:
|
||||
return None
|
||||
|
||||
# 写入前缀: "["(类型前缀由 _print_global 输出,初始化器只需元素列表)
|
||||
written: t.CInt = viperlib.snprintf(buf, buf_size, "[")
|
||||
pos: t.CSizeT = t.CSizeT(written)
|
||||
|
||||
# 逐个元素写入
|
||||
i: t.CSizeT = 0
|
||||
while i < elts_count:
|
||||
elem_node: ast.AST | t.CPtr = elts.get(i)
|
||||
# 直接从 Constant 节点提取 int_val(避免 extract_cdefine_int_value 的 t.CInt 截断)
|
||||
elem_val: t.CInt64T = 0
|
||||
if elem_node is not None:
|
||||
ek: int = elem_node.kind()
|
||||
if ek == ast.ASTKind.Constant:
|
||||
ec: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(elem_node)
|
||||
if ec is not None and ec.const_kind == ast.CONST_INT:
|
||||
elem_val = ec.int_val
|
||||
elif ek == ast.ASTKind.UnaryOp:
|
||||
# 负数: UnaryOp(USub, Constant)
|
||||
elem_val = HandlesAnnAssign.extract_cdefine_int_value(elem_node)
|
||||
if i > 0:
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, ", ")
|
||||
pos += t.CSizeT(written)
|
||||
written = viperlib.snprintf(buf + pos, buf_size - pos, "%s %lld", elem_ir_ty, elem_val)
|
||||
pos += t.CSizeT(written)
|
||||
i += 1
|
||||
|
||||
# 写入后缀 "]"
|
||||
viperlib.snprintf(buf + pos, buf_size - pos, "]")
|
||||
return buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _build_string_ptr_initializer - 为字符串字面量初始化指针类型全局变量
|
||||
#
|
||||
# 创建内部字符串常量全局 @.str.{var_name} = private constant [len+1 x i8] c"...\00"
|
||||
# 返回 GEP 初始化器文本: getelementptr inbounds ([len+1 x i8], [len+1 x i8]* @.str.{var_name}, i32 0, i32 0)
|
||||
# 用于 b64_tab: t.CArray[t.CChar, None] = "ABC..." 等字符串初始化指针类型
|
||||
# ============================================================
|
||||
def _build_string_ptr_initializer(pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
var_name: str,
|
||||
str_val: str) -> str:
|
||||
"""为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败"""
|
||||
if str_val is None or var_name is None:
|
||||
return None
|
||||
|
||||
# 构造内部字符串常量名称: .str.{var_name}
|
||||
str_name_buf: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if str_name_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name)
|
||||
|
||||
# 调用 llvmlite.create_global_string 创建字符串常量全局
|
||||
str_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_string(
|
||||
pool, mod, str_name_buf, str_val)
|
||||
if str_gv is None:
|
||||
return None
|
||||
|
||||
# 生成 GEP 初始化器文本
|
||||
str_len: t.CSizeT = string.strlen(str_val)
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(128)
|
||||
if init_buf is None:
|
||||
return None
|
||||
viperlib.snprintf(init_buf, 128,
|
||||
"getelementptr inbounds ([%d x i8], [%d x i8]* @%s, i32 0, i32 0)",
|
||||
str_len + 1, str_len + 1, str_name_buf)
|
||||
return init_buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量
|
||||
#
|
||||
# 当用户已定义 main(无 wrapper main builder)时,模块级
|
||||
# AnnAssign/Assign 创建全局变量 @var_name 并注册到 SymTab 模块作用域
|
||||
# 支持整数、列表字面量、字符串字面量初始值
|
||||
# ============================================================
|
||||
def handle_module_level_var(trans: HT.Translator | t.CPtr,
|
||||
node: ast.AST | t.CPtr) -> int:
|
||||
"""处理模块级变量声明,创建全局变量"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
# CDefine 注解: 编译期常量,不创建全局变量
|
||||
# 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_cd: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_cd is not None and aa_cd.target is not None:
|
||||
if aa_cd.target.kind() == ast.ASTKind.Name:
|
||||
nm_cd: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa_cd.target)
|
||||
if nm_cd.id is not None:
|
||||
if HandlesAnnAssign.is_cdefine_annotation(aa_cd.annotation) != 0:
|
||||
val_cd: int = HandlesAnnAssign.extract_cdefine_int_value(aa_cd.value)
|
||||
HandlesType.register_cdefine_constant(pool, nm_cd.id, val_cd)
|
||||
return 0
|
||||
|
||||
# _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量
|
||||
# CDefine 已在上面处理并返回,到这里说明不是 CDefine,直接跳过
|
||||
if trans._declare_only == 1:
|
||||
return 0
|
||||
|
||||
var_name: str = None
|
||||
var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
init_val: t.CInt64T = 0
|
||||
init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str
|
||||
init_str_val: str = None
|
||||
init_list_node: ast.List | t.CPtr = None
|
||||
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa is None or aa.target is None:
|
||||
return 0
|
||||
if aa.target.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target)
|
||||
var_name = nm.id
|
||||
# 解析类型
|
||||
if aa.annotation is not None:
|
||||
resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type(
|
||||
pool, aa.annotation, trans._imported_modules, trans._from_imports, trans)
|
||||
if resolved is not None:
|
||||
var_ty = resolved
|
||||
# 解析初始值(支持整数、列表字面量、字符串字面量)
|
||||
if aa.value is not None:
|
||||
val_kind: int = aa.value.kind()
|
||||
if val_kind == ast.ASTKind.Constant:
|
||||
cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(aa.value)
|
||||
if cn.const_kind == ast.CONST_INT:
|
||||
init_val = cn.int_val
|
||||
init_kind = 1
|
||||
elif cn.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn.str_val
|
||||
init_kind = 3
|
||||
elif val_kind == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(aa.value)
|
||||
init_kind = 2
|
||||
elif k == ast.ASTKind.Assign:
|
||||
asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
|
||||
if asgn is None or asgn.targets is None:
|
||||
return 0
|
||||
targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets
|
||||
if targets.__len__() < 1:
|
||||
return 0
|
||||
t0: ast.AST | t.CPtr = targets.get(0)
|
||||
if t0 is None or t0.kind() != ast.ASTKind.Name:
|
||||
return 0
|
||||
nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0)
|
||||
var_name = nm2.id
|
||||
if asgn.value is not None:
|
||||
val_kind2: int = asgn.value.kind()
|
||||
if val_kind2 == ast.ASTKind.Constant:
|
||||
cn2: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(asgn.value)
|
||||
if cn2.const_kind == ast.CONST_INT:
|
||||
init_val = cn2.int_val
|
||||
init_kind = 1
|
||||
elif cn2.const_kind == ast.CONST_STR:
|
||||
init_str_val = cn2.str_val
|
||||
init_kind = 3
|
||||
elif val_kind2 == ast.ASTKind.List:
|
||||
init_list_node = (ast.List | t.CPtr)(asgn.value)
|
||||
init_kind = 2
|
||||
|
||||
if var_name is None:
|
||||
return 0
|
||||
|
||||
# 检查是否已注册
|
||||
existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(
|
||||
trans.SymTab, var_name)
|
||||
if existing is not None:
|
||||
return 0
|
||||
|
||||
# 创建全局变量 @var_name
|
||||
# 先确保 var_ty 中的跨模块结构体类型在模块中有 opaque 声明
|
||||
# 否则 @var_name = global %"sha1.ClassName"* zeroinitializer 会报
|
||||
# "use of undefined type named 'sha1.ClassName'" 错误
|
||||
# (如 _mbuddy: memhub.MemManager | t.CPtr → Ptr(Struct("aeb3...MemManager")))
|
||||
llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty)
|
||||
gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, var_name, var_ty)
|
||||
if gv is None:
|
||||
return 0
|
||||
llvmlite.module_add_global(mod, gv)
|
||||
|
||||
# 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值)
|
||||
gv.Linkage = None
|
||||
if init_kind == 1:
|
||||
# 整数初始值
|
||||
init_buf: t.CChar | t.CPtr = pool.alloc(48)
|
||||
if init_buf is not None:
|
||||
viperlib.snprintf(init_buf, 48, "%lld", init_val)
|
||||
gv.Initializer = init_buf
|
||||
elif init_kind == 2:
|
||||
# 列表字面量 → 数组初始化器 [N x elem_ty] [elem_ty val0, ...]
|
||||
arr_init: str = _build_array_initializer_text(pool, var_ty, init_list_node)
|
||||
if arr_init is not None:
|
||||
gv.Initializer = arr_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
elif init_kind == 3:
|
||||
# 字符串字面量 → 创建字符串常量全局 + GEP 引用
|
||||
str_init: str = _build_string_ptr_initializer(pool, mod, var_name, init_str_val)
|
||||
if str_init is not None:
|
||||
gv.Initializer = str_init
|
||||
else:
|
||||
gv.Initializer = "zeroinitializer"
|
||||
else:
|
||||
# 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer,
|
||||
# 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type"
|
||||
gv.Initializer = "zeroinitializer"
|
||||
|
||||
# 创建 Value 引用(@var_name, 类型为 var_ty*)
|
||||
var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty)
|
||||
ref_name: t.CChar | t.CPtr = pool.alloc(64)
|
||||
if ref_name is not None:
|
||||
viperlib.snprintf(ref_name, 64, "@%s", var_name)
|
||||
gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, var_ptr_ty, ref_name)
|
||||
|
||||
# 注册到模块作用域
|
||||
if HandlesVar.define_module_var(trans.SymTab, var_name, gv_ref) == 0:
|
||||
# 设置 AnnotClassName(联合类型如 Logger|t.CPtr 简化为 Ptr(i8) 时,
|
||||
# 属性访问需要通过 AnnotClassName 回退到类名查找结构体)
|
||||
if k == ast.ASTKind.AnnAssign:
|
||||
aa_ml: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node)
|
||||
if aa_ml is not None and aa_ml.annotation is not None:
|
||||
cls_nm_ml: str = HandlesType.extract_class_name_from_annotation(
|
||||
aa_ml.annotation, trans._imported_modules)
|
||||
if cls_nm_ml is not None:
|
||||
HandlesVar.set_var_annot_class_name(
|
||||
trans.SymTab, var_name, cls_nm_ml)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# create_wrapper_main - 创建包装 main 函数
|
||||
#
|
||||
# 当用户未定义 main 函数时调用。
|
||||
# 创建 main() -> i32 函数 → 设置 trans._cur_func/_cur_builder →
|
||||
# 预扫描 alloca → 翻译子节点 → ret 0
|
||||
# ============================================================
|
||||
def create_wrapper_main(trans: HT.Translator | t.CPtr,
|
||||
tree: ast.AST | t.CPtr,
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr) -> int:
|
||||
"""创建包装 main 函数并翻译所有顶层语句
|
||||
|
||||
Args:
|
||||
trans: 翻译器(含所有共享状态)
|
||||
tree: AST 模块节点
|
||||
i32_ty: i32 LLVMType
|
||||
|
||||
Returns:
|
||||
t.CInt: 新增的变量数
|
||||
"""
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
|
||||
main_func: llvmlite.Function | t.CPtr = llvmlite.create_function(
|
||||
pool, mod, "main", i32_ty)
|
||||
if main_func is None:
|
||||
VLogger.error("CreateFunction main returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(
|
||||
pool, main_func, "entry")
|
||||
if entry_blk is None:
|
||||
VLogger.error("CreateBlock returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, main_func)
|
||||
if builder is None:
|
||||
VLogger.error("NewBuilder returned NULL", "TR")
|
||||
return 0
|
||||
llvmlite.position_at_end(builder, entry_blk)
|
||||
|
||||
# 设置当前翻译上下文(供 Handle 通过 self.Trans._cur_builder 访问)
|
||||
trans._cur_func = main_func
|
||||
trans._cur_builder = builder
|
||||
|
||||
# 预处理模块级变量:为 AnnAssign/Assign 创建 LLVM 全局变量
|
||||
# 必须在 pre_scan_allocas 之前执行,否则 PreScan 会创建局部 alloca,
|
||||
# 导致其他函数通过 SSA 编号引用 wrapper main 的局部变量(无效 IR)
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is not None:
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign:
|
||||
handle_module_level_var(trans, child)
|
||||
|
||||
# 预扫描顶层语句:为函数内 AnnAssign 提前创建 alloca
|
||||
# (模块级变量已在上面注册到模块作用域,PreScan 的 lookup_current 会跳过它们)
|
||||
if ch is not None:
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None:
|
||||
HandlesBody.pre_scan_allocas(trans, child)
|
||||
|
||||
# 翻译子节点
|
||||
added_total: int = translate_children(trans, tree)
|
||||
|
||||
# 返回 0
|
||||
zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
llvmlite.build_ret(builder, zero_val)
|
||||
|
||||
return added_total
|
||||
@@ -1,127 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesNonlocal - nonlocal 变量访问(通过闭包 env)
|
||||
#
|
||||
# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针)
|
||||
# 指针指向原始变量(可能是 alloca 或全局变量)
|
||||
#
|
||||
# 在提升的嵌套函数中:
|
||||
# 1. 函数签名: define i32 @__closure_{name}(i8* %env)
|
||||
# 2. 入口处: %env_alloca = alloca i8*; store i8* %env, i8** %env_alloca
|
||||
# 3. 访问 nonlocal var:
|
||||
# a. %env_ptr = load i8*, i8** %env_alloca
|
||||
# b. %addr = gep i8, i8* %env_ptr, i32 (index * 8)
|
||||
# c. %ptr_addr = bitcast i8* %addr to i8**
|
||||
# d. %var_ptr_raw = load i8*, i8** %ptr_addr
|
||||
# e. %var_ptr = bitcast i8* %var_ptr_raw to i32*
|
||||
# f. read: %val = load i32, i32* %var_ptr
|
||||
# write: store i32 %new, i32* %var_ptr
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取或创建 _env_ptr 变量(存储 env 参数的 alloca)
|
||||
# ============================================================
|
||||
def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""获取或创建 _env_ptr 变量(存储闭包 env 指针)"""
|
||||
env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
trans.SymTab, "_env_ptr")
|
||||
if env_var is not None:
|
||||
return env_var
|
||||
# 创建 alloca 存储 env
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca)
|
||||
return alloca
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 加载 nonlocal 变量值 → 返回 i32 Value
|
||||
#
|
||||
# env 直接存储 i32 值(不是指针),每个 nonlocal 变量占 4 字节
|
||||
# ============================================================
|
||||
def load_nonlocal_var(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从闭包 env 加载 nonlocal 变量值(env 直接存储 i32 值)"""
|
||||
idx: int = HT.get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty)
|
||||
|
||||
# 1. 加载 env_ptr
|
||||
env_alloca: llvmlite.Value | t.CPtr = get_env_ptr_var(trans)
|
||||
if env_alloca is None:
|
||||
return None
|
||||
env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca)
|
||||
if env_ptr is None:
|
||||
return None
|
||||
|
||||
# 2. GEP to offset (idx * 4) — env 直接存储 i32 值
|
||||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 4)
|
||||
addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
# 3. Bitcast to i32* and load
|
||||
var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i32_ptr_ty)
|
||||
if var_ptr is None:
|
||||
return None
|
||||
return llvmlite.build_load(builder, i32_ty, var_ptr)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 获取 nonlocal 变量指针(用于 store)
|
||||
#
|
||||
# 返回 env 中 i32 槽位的地址(i32*),用于直接 store
|
||||
# ============================================================
|
||||
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""获取 nonlocal 变量在 env 中的地址(i32*),用于 store 操作"""
|
||||
idx: int = HT.get_nonlocal_index(trans, name)
|
||||
if idx < 0:
|
||||
return None
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty)
|
||||
|
||||
# 1. 加载 env_ptr
|
||||
env_alloca: llvmlite.Value | t.CPtr = get_env_ptr_var(trans)
|
||||
if env_alloca is None:
|
||||
return None
|
||||
env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca)
|
||||
if env_ptr is None:
|
||||
return None
|
||||
|
||||
# 2. GEP to offset (idx * 4) — env 直接存储 i32 值
|
||||
offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 4)
|
||||
addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val)
|
||||
if addr is None:
|
||||
return None
|
||||
|
||||
# 3. Bitcast to i32* and return (直接指向 env 中的 i32 槽位)
|
||||
return llvmlite.build_bitcast(builder, addr, i32_ptr_ty)
|
||||
@@ -1,117 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
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
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesReturn - Return 语句处理(Mixin 继承模式)
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class ReturnHandle(HandlesBase.Mixin):
|
||||
"""Return 语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 Return 语句,返回 0
|
||||
#
|
||||
# 翻译返回值(若有)并生成 ret 指令
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 Return 语句"""
|
||||
rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(node)
|
||||
if rt is None:
|
||||
return 0
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder
|
||||
mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module
|
||||
|
||||
val: llvmlite.Value | t.CPtr = None
|
||||
if rt.value is not None:
|
||||
# return self: 直接返回指针(self 是 SSA 参数 Ptr(struct_ty))
|
||||
# translate_value 会 load 得到结构体值,但 return self 需要指针本身
|
||||
if rt.value.kind() == ast.ASTKind.Name:
|
||||
ret_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rt.value)
|
||||
if ret_nm is not None and ret_nm.id is not None:
|
||||
if string.strcmp(ret_nm.id, "self") == 0:
|
||||
self_ptr: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(
|
||||
self.Trans.SymTab, "self")
|
||||
if self_ptr is not None:
|
||||
val = self_ptr
|
||||
if val is None:
|
||||
val = HandlesExpr.translate_value(
|
||||
builder, pool, mod, rt.value,
|
||||
self.Trans._funcs, self.Trans._func_count, self.Trans)
|
||||
|
||||
# val 为 None 时(裸 return):检查当前函数返回类型
|
||||
# void 函数(如 __init__/__before_init__)生成 ret void,
|
||||
# ptr 函数生成 ret ptr null,否则 ret i32 0
|
||||
if val is None:
|
||||
cur_func: llvmlite.Function | t.CPtr = self.Trans._cur_func
|
||||
is_void_ret: int = 0
|
||||
is_ptr_ret: int = 0
|
||||
ret_ty: llvmlite.LLVMType | t.CPtr = None
|
||||
if cur_func is not None:
|
||||
ret_ty = llvmlite.function_get_ret_ty(cur_func)
|
||||
if ret_ty is not None:
|
||||
match ret_ty:
|
||||
case llvmlite.LLVMType.Void():
|
||||
is_void_ret = 1
|
||||
case llvmlite.LLVMType.Ptr(_pe):
|
||||
is_ptr_ret = 1
|
||||
if is_void_ret != 0:
|
||||
llvmlite.build_ret_void(builder)
|
||||
return 0
|
||||
if is_ptr_ret != 0:
|
||||
null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null")
|
||||
llvmlite.build_ret(builder, null_val)
|
||||
return 0
|
||||
val = llvmlite.const_int32(pool, 0)
|
||||
|
||||
# 类型转换:确保 val 类型与函数返回类型匹配
|
||||
# 处理 i1(bool 比较结果)→ i8(t.CBool)等情况
|
||||
# i1 → 更宽整数用 zext(bool 语义:1 保持 1,而非 sext 的 0xFF)
|
||||
# 注意:当 val 是整数而 ret_ty 是 ptr 时(即使 bits 相同,如 i64 vs ptr),
|
||||
# 也必须 inttoptr 转换,否则 llc 报 "value doesn't match function result type"
|
||||
cur_func_rt: llvmlite.Function | t.CPtr = self.Trans._cur_func
|
||||
if cur_func_rt is not None and val is not None and val.Ty is not None:
|
||||
ret_ty_rt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(cur_func_rt)
|
||||
if ret_ty_rt is not None:
|
||||
val_bits: int = HandlesExpr.get_llvm_type_bits(val.Ty)
|
||||
ret_bits: int = HandlesExpr.get_llvm_type_bits(ret_ty_rt)
|
||||
val_is_ptr: int = HandlesExpr.is_ptr_type(val.Ty)
|
||||
ret_is_ptr: int = HandlesExpr.is_ptr_type(ret_ty_rt)
|
||||
# ptr 类型不一致性:val 是整数但 ret 是 ptr(或反之),必须转换
|
||||
if val_is_ptr != ret_is_ptr:
|
||||
val = HandlesExpr.coerce_to_type(builder, val, ret_ty_rt)
|
||||
elif val_bits != 0 and ret_bits != 0 and val_bits != ret_bits:
|
||||
if val_bits == 1 and val_bits < ret_bits:
|
||||
val = llvmlite.build_zext(builder, val, ret_ty_rt)
|
||||
else:
|
||||
val = HandlesExpr.coerce_to_type(builder, val, ret_ty_rt)
|
||||
llvmlite.build_ret(builder, val)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewReturnHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewReturnHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> ReturnHandle | t.CPtr:
|
||||
h: ReturnHandle | t.CPtr = pool.alloc(ReturnHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, ReturnHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,434 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesMain as HandlesMain
|
||||
import lib.core.Handles.HandlesAssign as HandlesAssign
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
# ============================================================
|
||||
# HandlesTranslator - 翻译器状态管理 + 主入口
|
||||
#
|
||||
# 从 translator.py 拆分出来,负责:
|
||||
# 1. Translator 类 - 状态管理(Module, 变量表, 函数表, 导入)
|
||||
# 2. translate() - 主翻译入口
|
||||
# 3. dump_ir() - IR 输出
|
||||
#
|
||||
# 语句/表达式翻译全部委托给 Handles 模块:
|
||||
# HandlesMain - wrapper main 创建 + children 遍历
|
||||
# HandlesBody - 语句分派
|
||||
# HandlesExpr - 表达式翻译
|
||||
# HandlesFunctions - 函数定义处理
|
||||
# 注意:str = bytes = t.CChar | t.CPtr = i8*
|
||||
# ============================================================
|
||||
|
||||
# 常量
|
||||
MAX_VARS: t.CDefine = 256
|
||||
MAX_FUNCS: t.CDefine = 256
|
||||
MAX_GLOBAL_NAMES: t.CDefine = 32
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class Translator:
|
||||
"""翻译器:管理编译状态,委托 Handles 模块执行翻译"""
|
||||
|
||||
# LLVM 上下文(共享状态)
|
||||
Module: llvmlite.LLVMModule | t.CPtr
|
||||
Pool: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 函数表
|
||||
_funcs: HandlesExprCall.FuncEntry | t.CPtr
|
||||
_func_count: t.CInt
|
||||
|
||||
# 导入模块跟踪
|
||||
_imported_modules: str
|
||||
_from_imports: str
|
||||
|
||||
# 当前翻译上下文
|
||||
_cur_func: llvmlite.Function | t.CPtr
|
||||
_cur_builder: llvmlite.IRBuilder | t.CPtr
|
||||
|
||||
# 循环控制流目标(break/continue)
|
||||
_break_bb: llvmlite.BasicBlock | t.CPtr
|
||||
_continue_bb: llvmlite.BasicBlock | t.CPtr
|
||||
|
||||
# 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调)
|
||||
_label_counter: t.CInt
|
||||
|
||||
# global 声明的变量名集合(当前函数内)
|
||||
_global_names: str
|
||||
_global_name_count: t.CInt
|
||||
|
||||
# nonlocal 声明的变量名集合(当前函数内)
|
||||
_nonlocal_names: str
|
||||
_nonlocal_name_count: t.CInt
|
||||
|
||||
# 闭包相关:当前函数名(用于嵌套函数提升命名)
|
||||
_cur_func_name: str
|
||||
|
||||
# 模块 SHA1 前缀(16 字符),用于函数名混淆(SHA1 命名空间)
|
||||
ModuleSha1: str
|
||||
# 当前文件所属包名(如 "llvmlite"),用于解析相对导入(from . import ...)
|
||||
# None 表示当前文件是顶级模块(无包),相对导入无法解析
|
||||
CurrentPackage: str
|
||||
# 闭包 env 中的 nonlocal 变量偏移映射(每个 nonlocal 变量在 env 中的字节偏移)
|
||||
_closure_env_offsets: t.CInt
|
||||
_closure_env_count: t.CInt
|
||||
|
||||
# 泛型特化上下文:当前正在特化的类型参数名/实参名列表
|
||||
# 由 _specialize_generic_class 设置,方法体翻译时用于将 T 替换为具体类型
|
||||
# None 表示不在泛型特化上下文中
|
||||
GenericTypeParamNames: list[str] | t.CPtr
|
||||
GenericTypeArgs: list[str] | t.CPtr
|
||||
|
||||
# Phase 1a 声明模式标志:1=只注册 struct/enum/union 不翻译代码体,0=全量翻译
|
||||
_declare_only: t.CInt
|
||||
|
||||
# 子 Handle 指针(每个 Handle 一个槽,通过 Mixin 回指针访问本结构体)
|
||||
AssignH: HandlesAssign.AssignHandle | t.CPtr
|
||||
ReturnH: HandlesReturn.ReturnHandle | t.CPtr
|
||||
ImportsH: HandlesImports.ImportsHandle | t.CPtr
|
||||
AnnAssignH: HandlesAnnAssign.AnnAssignHandle | t.CPtr
|
||||
AugAssignH: HandlesAugAssign.AugAssignHandle | t.CPtr
|
||||
IfH: HandlesIf.IfHandle | t.CPtr
|
||||
WhileH: HandlesWhile.WhileHandle | t.CPtr
|
||||
ForH: HandlesFor.ForHandle | t.CPtr
|
||||
ExprH: HandlesExpr.ExprHandle | t.CPtr
|
||||
ExprCallH: HandlesExprCall.ExprCallHandle | t.CPtr
|
||||
|
||||
# 嵌套作用域符号表
|
||||
SymTab: HandlesVar.SymbolTable | t.CPtr
|
||||
|
||||
def __init__(self):
|
||||
self.Module = None
|
||||
self.Pool = None
|
||||
self._funcs = None
|
||||
self._func_count = 0
|
||||
self._cur_func = None
|
||||
self._cur_builder = None
|
||||
self._break_bb = None
|
||||
self._continue_bb = None
|
||||
self._label_counter = 0
|
||||
self._imported_modules = None
|
||||
self._from_imports = None
|
||||
self._global_names = None
|
||||
self._global_name_count = 0
|
||||
self._nonlocal_names = None
|
||||
self._nonlocal_name_count = 0
|
||||
self._cur_func_name = None
|
||||
self.ModuleSha1 = None
|
||||
self.CurrentPackage = None
|
||||
self._closure_env_offsets = 0
|
||||
self._closure_env_count = 0
|
||||
self.GenericTypeParamNames = None
|
||||
self.GenericTypeArgs = None
|
||||
self._declare_only = 0
|
||||
self.AssignH = None
|
||||
self.ReturnH = None
|
||||
self.ImportsH = None
|
||||
self.AnnAssignH = None
|
||||
self.AugAssignH = None
|
||||
self.IfH = None
|
||||
self.WhileH = None
|
||||
self.ForH = None
|
||||
self.ExprH = None
|
||||
self.ExprCallH = None
|
||||
self.SymTab = None
|
||||
|
||||
# ============================================================
|
||||
# 状态初始化
|
||||
# ============================================================
|
||||
def _init_state(self, pool: memhub.MemBuddy | t.CPtr):
|
||||
"""初始化变量表、函数表和子 Handle"""
|
||||
self.Pool = pool
|
||||
if self._funcs is None:
|
||||
self._funcs = HandlesExprCall.init_func_table(pool, MAX_FUNCS)
|
||||
# 嵌套作用域符号表(新版)
|
||||
if self.SymTab is None:
|
||||
self.SymTab = HandlesVar.init_symbol_table(pool)
|
||||
# global/nonlocal 名称集合缓冲区(32 个 char* 指针 = 256 字节)
|
||||
if self._global_names is None:
|
||||
self._global_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
|
||||
if self._global_names is not None:
|
||||
string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8)
|
||||
self._global_name_count = 0
|
||||
if self._nonlocal_names is None:
|
||||
self._nonlocal_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8)
|
||||
if self._nonlocal_names is not None:
|
||||
string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8)
|
||||
self._nonlocal_name_count = 0
|
||||
# 创建子 Handle(传入 self 作为 Mixin 回指针)
|
||||
if self.AssignH is None:
|
||||
self.AssignH = HandlesAssign.NewAssignHandle(pool, self)
|
||||
if self.ReturnH is None:
|
||||
self.ReturnH = HandlesReturn.NewReturnHandle(pool, self)
|
||||
if self.ImportsH is None:
|
||||
self.ImportsH = HandlesImports.NewImportsHandle(pool, self)
|
||||
if self.AnnAssignH is None:
|
||||
self.AnnAssignH = HandlesAnnAssign.NewAnnAssignHandle(pool, self)
|
||||
if self.AugAssignH is None:
|
||||
self.AugAssignH = HandlesAugAssign.NewAugAssignHandle(pool, self)
|
||||
if self.IfH is None:
|
||||
self.IfH = HandlesIf.NewIfHandle(pool, self)
|
||||
if self.WhileH is None:
|
||||
self.WhileH = HandlesWhile.NewWhileHandle(pool, self)
|
||||
if self.ForH is None:
|
||||
self.ForH = HandlesFor.NewForHandle(pool, self)
|
||||
if self.ExprH is None:
|
||||
self.ExprH = HandlesExpr.NewExprHandle(pool, self)
|
||||
if self.ExprCallH is None:
|
||||
self.ExprCallH = HandlesExprCall.NewExprCallHandle(pool, self)
|
||||
|
||||
# ============================================================
|
||||
# 主翻译入口
|
||||
# ============================================================
|
||||
def translate(self, tree: ast.AST | t.CPtr) -> int:
|
||||
"""将 AST 翻译为 LLVM IR"""
|
||||
if tree is None:
|
||||
return 1
|
||||
if _mbuddy is None:
|
||||
return 1
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = _mbuddy
|
||||
|
||||
# 初始化状态
|
||||
self._init_state(pool)
|
||||
|
||||
# 创建 LLVM 模块
|
||||
mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main")
|
||||
if mod is None:
|
||||
VLogger.error("NewModule returned NULL", "TR")
|
||||
return 1
|
||||
self.Module = mod
|
||||
|
||||
# 设置目标(优先使用 project.vpj 中的配置)
|
||||
triple: str = Config.TargetTriple
|
||||
if triple is None:
|
||||
triple = "x86_64-pc-windows-msvc"
|
||||
llvmlite.module_set_target(mod, triple)
|
||||
|
||||
# 类型
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool)
|
||||
i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool)
|
||||
i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty)
|
||||
|
||||
# 声明 printf
|
||||
printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, "printf", i32_ty)
|
||||
if printf_func is None:
|
||||
VLogger.error("CreateDeclare printf returned NULL", "TR")
|
||||
return 1
|
||||
llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt")
|
||||
printf_func.IsVarArg = 1
|
||||
|
||||
# 声明 malloc(闭包分配用)
|
||||
malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare(
|
||||
pool, mod, "malloc", i8_ptr_ty)
|
||||
if malloc_func is not None:
|
||||
i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool)
|
||||
llvmlite.add_param(pool, malloc_func, i64_ty, "size")
|
||||
|
||||
# 检查用户是否定义了 main 函数
|
||||
has_user_main: int = 0
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is not None:
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is not None and child.kind() == ast.ASTKind.FunctionDef:
|
||||
fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child)
|
||||
if fd is not None and fd.name is not None:
|
||||
if string.strcmp(fd.name, "main") == 0:
|
||||
has_user_main = 1
|
||||
break
|
||||
|
||||
if self._declare_only != 0:
|
||||
# Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder
|
||||
self._translate_module_level(pool, mod, tree)
|
||||
elif has_user_main == 0:
|
||||
# 无用户 main → 只翻译模块级语句,不创建 wrapper main
|
||||
# 修复:避免每个文件都生成 define i32 @main() 导致链接时 main 冲突
|
||||
# 只有包含 def main() 的入口文件才会有 define i32 @main()
|
||||
self._translate_module_level(pool, mod, tree)
|
||||
else:
|
||||
# 用户已定义 main → 委托 HandlesMain 翻译模块级
|
||||
self._translate_module_level(pool, mod, tree)
|
||||
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 包装 main 函数(无用户 main 时)→ 委托 HandlesMain
|
||||
# ============================================================
|
||||
def _translate_wrapper_main(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
tree: ast.AST | t.CPtr,
|
||||
i32_ty: llvmlite.LLVMType | t.CPtr):
|
||||
"""委托 HandlesMain.create_wrapper_main() 创建包装 main(trans 单参)"""
|
||||
added: int = HandlesMain.create_wrapper_main(self, tree, i32_ty)
|
||||
|
||||
# ============================================================
|
||||
# 模块级翻译(用户已定义 main)→ 委托 HandlesMain
|
||||
# ============================================================
|
||||
def _translate_module_level(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
mod: llvmlite.LLVMModule | t.CPtr,
|
||||
tree: ast.AST | t.CPtr):
|
||||
"""委托 HandlesMain.translate_children() 翻译模块级语句(trans 单参)"""
|
||||
# 全量翻译模式下,先处理导入语句,再创建前向声明,解决前向引用问题
|
||||
if self._declare_only == 0:
|
||||
# 预处理导入语句,确保 _imported_modules 和 _from_imports 已填充
|
||||
# (前向声明需要解析类型注解,如 t.CArray[str] 依赖 t 模块已导入)
|
||||
ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children
|
||||
if ch is not None:
|
||||
cn_count: t.CSizeT = ch.__len__()
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
kd: int = child.kind()
|
||||
if kd == ast.ASTKind.Import:
|
||||
self.ImportsH.HandleImport(child)
|
||||
elif kd == ast.ASTKind.ImportFrom:
|
||||
self.ImportsH.HandleImportFromModule(child)
|
||||
self.ImportsH.HandleImportFromNames(child)
|
||||
# 预注册模块级变量(AnnAssign/Assign)到 SymTab
|
||||
# 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时,
|
||||
# _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后,
|
||||
# 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None
|
||||
# 预处理先于 translate_children 注册所有模块级变量,
|
||||
# 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var
|
||||
# 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209)
|
||||
if ch is not None:
|
||||
for ci in range(cn_count):
|
||||
child: ast.AST | t.CPtr = ch.get(ci)
|
||||
if child is None:
|
||||
continue
|
||||
kd_mv: int = child.kind()
|
||||
if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign:
|
||||
HandlesMain.handle_module_level_var(self, child)
|
||||
# 创建前向声明
|
||||
HandlesFunctions.forward_declare_functions(self, tree)
|
||||
added: int = HandlesMain.translate_children(self, tree)
|
||||
|
||||
# ============================================================
|
||||
# IR 输出
|
||||
# ============================================================
|
||||
def dump_ir(self, buf: bytes, size: t.CSizeT, mode: int):
|
||||
"""将 LLVM IR 输出到缓冲区
|
||||
|
||||
mode: 0=完整, 1=stub(仅声明), 2=text(仅代码)
|
||||
"""
|
||||
if self.Module is None or buf is None:
|
||||
return
|
||||
if _mbuddy is None:
|
||||
return
|
||||
buf[0] = '\0'
|
||||
llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# global/nonlocal 名称管理(模块级辅助函数)
|
||||
# ============================================================
|
||||
def add_global_name(trans: HT.Translator | t.CPtr, name: str):
|
||||
"""添加一个 global 变量名"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._global_name_count >= MAX_GLOBAL_NAMES:
|
||||
return
|
||||
if trans._global_names is None:
|
||||
return
|
||||
# 检查是否已存在
|
||||
if is_global_name(trans, name) != 0:
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + trans._global_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
trans._global_name_count += 1
|
||||
|
||||
|
||||
def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 global 集合中"""
|
||||
if trans is None or name is None or trans._global_names is None:
|
||||
return 0
|
||||
for i in range(trans._global_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def add_nonlocal_name(trans: HT.Translator | t.CPtr, name: str):
|
||||
"""添加一个 nonlocal 变量名"""
|
||||
if trans is None or name is None:
|
||||
return
|
||||
if trans._nonlocal_name_count >= MAX_GLOBAL_NAMES:
|
||||
return
|
||||
if trans._nonlocal_names is None:
|
||||
return
|
||||
if is_nonlocal_name(trans, name) != 0:
|
||||
return
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + trans._nonlocal_name_count * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
slot_ptr[0] = name
|
||||
trans._nonlocal_name_count += 1
|
||||
trans._closure_env_count += 1
|
||||
|
||||
|
||||
def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""检查 name 是否在当前函数的 nonlocal 集合中"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return 0
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int:
|
||||
"""获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1"""
|
||||
if trans is None or name is None or trans._nonlocal_names is None:
|
||||
return -1
|
||||
for i in range(trans._nonlocal_name_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8
|
||||
slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr)
|
||||
entry: str = slot_ptr[0]
|
||||
if entry is not None:
|
||||
if string.strcmp(entry, name) == 0:
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
def clear_scope_names(trans: HT.Translator | t.CPtr):
|
||||
"""清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)"""
|
||||
if trans is None:
|
||||
return
|
||||
trans._global_name_count = 0
|
||||
trans._nonlocal_name_count = 0
|
||||
trans._closure_env_count = 0
|
||||
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,406 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesVar - 嵌套作用域符号表 + 变量管理
|
||||
#
|
||||
# 使用 Scope 链(Parent 指针)管理嵌套作用域,
|
||||
# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。
|
||||
#
|
||||
# 作用域类型:
|
||||
# SCOPE_MODULE — 模块级(根作用域)
|
||||
# SCOPE_FUNCTION — 函数级
|
||||
# SCOPE_BLOCK — 块级(if/for/while,当前未使用块作用域)
|
||||
# ============================================================
|
||||
|
||||
# 作用域类型常量
|
||||
SCOPE_MODULE: t.CDefine = 0
|
||||
SCOPE_FUNCTION: t.CDefine = 1
|
||||
SCOPE_BLOCK: t.CDefine = 2
|
||||
|
||||
# 每个作用域最大变量数
|
||||
MAX_VARS: t.CDefine = 256
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VarEntry - 变量表条目
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class VarEntry:
|
||||
"""变量表条目"""
|
||||
Name: t.CChar | t.CPtr
|
||||
Alloca: llvmlite.Value | t.CPtr
|
||||
Used: t.CInt
|
||||
AnnotClassName: t.CChar | t.CPtr # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型)
|
||||
IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Scope - 作用域节点
|
||||
#
|
||||
# Parent 指向父作用域(None 表示根),
|
||||
# Vars 是 VarEntry 数组,VarCount 是当前变量数。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class Scope:
|
||||
"""作用域节点"""
|
||||
Parent: Scope | t.CPtr
|
||||
Vars: VarEntry | t.CPtr
|
||||
VarCount: t.CInt
|
||||
Kind: t.CInt
|
||||
|
||||
|
||||
# ============================================================
|
||||
# SymbolTable - 嵌套作用域符号表
|
||||
#
|
||||
# Root 是模块级根作用域,Current 是当前作用域。
|
||||
# enter_scope/exit_scope 管理作用域栈。
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class SymbolTable:
|
||||
"""嵌套作用域符号表"""
|
||||
Pool: memhub.MemBuddy | t.CPtr
|
||||
Root: Scope | t.CPtr
|
||||
Current: Scope | t.CPtr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_vars — 分配并清零 VarEntry 数组
|
||||
# ============================================================
|
||||
def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr:
|
||||
"""分配并清零变量表数组"""
|
||||
size: t.CSizeT = MAX_VARS * VarEntry.__sizeof__()
|
||||
vars_ptr: VarEntry | t.CPtr = pool.alloc(size)
|
||||
if vars_ptr is not None:
|
||||
string.memset(vars_ptr, 0, size)
|
||||
return vars_ptr
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_var — 在变量表中按名称查找
|
||||
# ============================================================
|
||||
def find_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在变量表中按名称查找"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry.Alloca
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy)
|
||||
# ============================================================
|
||||
def find_var_entry(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""在变量表中按名称查找,返回 VarEntry 或 None"""
|
||||
if name is None or vars_ptr is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
for i in range(var_count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry.Name is not None and entry.Used != 0:
|
||||
if string.strcmp(entry.Name, name) == 0:
|
||||
return entry
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> VarEntry | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 VarEntry 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: VarEntry | t.CPtr = find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# set_var_annot_class_name — 设置变量的原始类型注解类名
|
||||
#
|
||||
# 在函数参数定义后调用,存储原始类型注解的类名。
|
||||
# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化),
|
||||
# 通过 AnnotClassName 查找实际结构体类型。
|
||||
# ============================================================
|
||||
def set_var_annot_class_name(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
class_name: str) -> int:
|
||||
"""设置变量的原始类型注解类名,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.AnnotClassName = class_name
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型
|
||||
#
|
||||
# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*,
|
||||
# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。
|
||||
# 此标志在 HandlesAnnAssign 中根据注解形式设置。
|
||||
# ============================================================
|
||||
def set_var_ptr_element(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> int:
|
||||
"""标记变量为 ptr_element 类型,返回 0=成功 / 1=失败"""
|
||||
if symtab is None or name is None:
|
||||
return 1
|
||||
entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name)
|
||||
if entry is None:
|
||||
return 1
|
||||
entry.IsPtrElement = 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# add_var — 添加变量到变量表
|
||||
# ============================================================
|
||||
def add_var(vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""添加变量到变量表"""
|
||||
if name is None or alloca is None or vars_ptr is None:
|
||||
return 1
|
||||
if var_count >= MAX_VARS:
|
||||
return 1
|
||||
entry_size: t.CSizeT = VarEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size
|
||||
entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
entry.Name = name
|
||||
entry.Alloca = alloca
|
||||
entry.Used = 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性)
|
||||
#
|
||||
# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成,
|
||||
# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。
|
||||
# 标准做法:所有 alloca 在函数入口块生成。
|
||||
#
|
||||
# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。
|
||||
# ============================================================
|
||||
def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""在函数入口块生成 alloca,返回 alloca 值
|
||||
|
||||
使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca,
|
||||
确保所有 alloca 在入口块,避免支配性违规。
|
||||
"""
|
||||
if builder is None or ty is None:
|
||||
return None
|
||||
return llvmlite.build_alloca_at_entry(builder, ty)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_var — 查找或创建变量 alloca(旧版兼容)
|
||||
# ============================================================
|
||||
def get_or_create_var(pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
vars_ptr: VarEntry | t.CPtr,
|
||||
var_count: int,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca"""
|
||||
existing: llvmlite.Value | t.CPtr = find_var(vars_ptr, var_count, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
if add_var(vars_ptr, var_count, name, alloca) != 0:
|
||||
return None
|
||||
return alloca
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _create_scope — 创建新作用域节点(内部辅助函数)
|
||||
# ============================================================
|
||||
def _create_scope(pool: memhub.MemBuddy | t.CPtr,
|
||||
parent: Scope | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""创建并初始化作用域节点"""
|
||||
scope: Scope | t.CPtr = pool.alloc(Scope.__sizeof__())
|
||||
if scope is None:
|
||||
return None
|
||||
string.memset(scope, 0, Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
scope.Vars = init_vars(pool)
|
||||
scope.VarCount = 0
|
||||
scope.Kind = kind
|
||||
if scope.Vars is None:
|
||||
return None
|
||||
return scope
|
||||
|
||||
|
||||
# ============================================================
|
||||
# init_symbol_table — 创建符号表(含模块级根作用域)
|
||||
# ============================================================
|
||||
def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr:
|
||||
"""创建并初始化符号表,包含模块级根作用域"""
|
||||
if pool is None:
|
||||
return None
|
||||
symtab: SymbolTable | t.CPtr = pool.alloc(SymbolTable.__sizeof__())
|
||||
if symtab is None:
|
||||
return None
|
||||
string.memset(symtab, 0, SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# 创建根作用域(模块级)
|
||||
root: Scope | t.CPtr = _create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None:
|
||||
return None
|
||||
|
||||
symtab.Root = root
|
||||
symtab.Current = root
|
||||
return symtab
|
||||
|
||||
|
||||
# ============================================================
|
||||
# enter_scope — 进入新作用域
|
||||
# ============================================================
|
||||
def enter_scope(symtab: SymbolTable | t.CPtr,
|
||||
kind: int) -> Scope | t.CPtr:
|
||||
"""进入新作用域,返回新创建的作用域"""
|
||||
if symtab is None:
|
||||
return None
|
||||
pool: memhub.MemBuddy | t.CPtr = symtab.Pool
|
||||
scope: Scope | t.CPtr = _create_scope(pool, symtab.Current, kind)
|
||||
if scope is None:
|
||||
return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
|
||||
|
||||
# ============================================================
|
||||
# exit_scope — 退出当前作用域
|
||||
# ============================================================
|
||||
def exit_scope(symtab: SymbolTable | t.CPtr):
|
||||
"""退出当前作用域,恢复到父作用域"""
|
||||
if symtab is not None and symtab.Current is not None:
|
||||
symtab.Current = symtab.Current.Parent
|
||||
|
||||
|
||||
# ============================================================
|
||||
# define_var — 在当前作用域定义变量
|
||||
# ============================================================
|
||||
def define_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在当前作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
|
||||
# ============================================================
|
||||
# define_module_var — 在模块作用域定义变量
|
||||
# ============================================================
|
||||
def define_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str,
|
||||
alloca: llvmlite.Value | t.CPtr) -> int:
|
||||
"""在模块作用域定义变量,返回 0 成功"""
|
||||
if symtab is None or name is None or alloca is None:
|
||||
return 1
|
||||
scope: Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return 1
|
||||
ret: int = add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0:
|
||||
scope.VarCount = scope.VarCount + 1
|
||||
return ret
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_var — 从当前作用域逐级向上查找变量
|
||||
# ============================================================
|
||||
def lookup_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""从当前作用域逐级向上查找变量,返回 alloca 或 None"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
while scope is not None:
|
||||
result: llvmlite.Value | t.CPtr = find_var(
|
||||
scope.Vars, scope.VarCount, name)
|
||||
if result is not None:
|
||||
return result
|
||||
scope = scope.Parent
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_current — 仅在当前作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_current(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""仅在当前作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Current
|
||||
if scope is None:
|
||||
return None
|
||||
return find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# lookup_module_var — 在模块作用域查找变量
|
||||
# ============================================================
|
||||
def lookup_module_var(symtab: SymbolTable | t.CPtr,
|
||||
name: str) -> llvmlite.Value | t.CPtr:
|
||||
"""在模块作用域查找变量"""
|
||||
if symtab is None or name is None:
|
||||
return None
|
||||
scope: Scope | t.CPtr = symtab.Root
|
||||
if scope is None:
|
||||
return None
|
||||
return find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# get_or_create_sym — 查找或创建变量(在当前作用域)
|
||||
# ============================================================
|
||||
def get_or_create_sym(symtab: SymbolTable | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
builder: llvmlite.IRBuilder | t.CPtr,
|
||||
name: str,
|
||||
ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr:
|
||||
"""查找或创建变量 alloca(在当前作用域)"""
|
||||
existing: llvmlite.Value | t.CPtr = lookup_current(symtab, name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty)
|
||||
if alloca is None:
|
||||
return None
|
||||
define_var(symtab, name, alloca)
|
||||
return alloca
|
||||
@@ -1,130 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
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.HandlesBody as HandlesBody
|
||||
|
||||
|
||||
# ============================================================
|
||||
# HandlesWhile - while 循环语句处理(Mixin 继承模式)
|
||||
#
|
||||
# 翻译 while 语句为 LLVM IR 控制流:
|
||||
# br label %cond
|
||||
# cond:
|
||||
# %t = <test>
|
||||
# %c = icmp ne i32 %t, 0
|
||||
# br i1 %c, label %body, label %end
|
||||
# body:
|
||||
# ... body ...
|
||||
# br label %cond
|
||||
# end:
|
||||
# ============================================================
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class WhileHandle(HandlesBase.Mixin):
|
||||
"""while 循环语句处理器:继承 Mixin 获得 Trans 回指针"""
|
||||
|
||||
def __init__(self, trans: HT.Translator | t.CPtr):
|
||||
self.Trans = trans
|
||||
|
||||
# ============================================================
|
||||
# Handle - 处理 while 语句,返回新增变量数
|
||||
# ============================================================
|
||||
def Handle(self, node: ast.AST | t.CPtr) -> int:
|
||||
"""翻译 while 循环语句"""
|
||||
if node is None:
|
||||
return 0
|
||||
|
||||
trans: HT.Translator | t.CPtr = self.Trans
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
|
||||
func: llvmlite.Function | t.CPtr = trans._cur_func
|
||||
|
||||
if builder is None or func is None:
|
||||
return 0
|
||||
|
||||
while_node: ast.While | t.CPtr = (ast.While | t.CPtr)(node)
|
||||
|
||||
# 1. 创建基本块: cond / body / end(使用 trans._label_counter,不与 SSA 名共享)
|
||||
cnt: int = trans._label_counter
|
||||
trans._label_counter = cnt + 1
|
||||
|
||||
name_buf: t.CChar | t.CPtr = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "while.cond.%d", cnt)
|
||||
cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "while.body.%d", cnt)
|
||||
body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "while.end.%d", cnt)
|
||||
end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 2. 跳转到 cond 块
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# 3. cond 块: 求值条件,条件分支
|
||||
llvmlite.position_at_end(builder, cond_bb)
|
||||
cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value(
|
||||
builder, pool, trans.Module, while_node.test,
|
||||
trans._funcs, trans._func_count, trans)
|
||||
if cond_val is None:
|
||||
cond_val = llvmlite.const_int32(pool, 0)
|
||||
|
||||
# Compare/Not 表达式已返回 i1,直接使用;其他类型与 0 比较
|
||||
cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty)
|
||||
if cond_bits == 1:
|
||||
cond_i1: llvmlite.Value | t.CPtr = cond_val
|
||||
else:
|
||||
zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0)
|
||||
cond_i1 = llvmlite.build_icmp(
|
||||
builder, llvmlite.ICMP_NE, cond_val, zero)
|
||||
llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb)
|
||||
|
||||
# 4. body 块: 翻译循环体,跳回 cond
|
||||
llvmlite.position_at_end(builder, body_bb)
|
||||
|
||||
# 保存旧循环上下文,设置 break/continue 目标
|
||||
old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb
|
||||
old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = cond_bb
|
||||
|
||||
body: list[ast.AST | t.CPtr] | t.CPtr = while_node.children
|
||||
if body is not None:
|
||||
body_count: t.CSizeT = body.__len__()
|
||||
for bi in range(body_count):
|
||||
stmt: ast.AST | t.CPtr = body.get(bi)
|
||||
if stmt is not None:
|
||||
HandlesBody.translate_stmt(trans, stmt)
|
||||
|
||||
# 恢复旧循环上下文
|
||||
trans._break_bb = old_break
|
||||
trans._continue_bb = old_continue
|
||||
|
||||
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
|
||||
llvmlite.build_br(builder, cond_bb)
|
||||
|
||||
# 5. 定位到 end 块
|
||||
llvmlite.position_at_end(builder, end_bb)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# NewWhileHandle - 工厂函数
|
||||
# ============================================================
|
||||
def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr,
|
||||
trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr:
|
||||
h: WhileHandle | t.CPtr = pool.alloc(WhileHandle.__sizeof__())
|
||||
if h is None:
|
||||
return None
|
||||
string.memset(h, 0, WhileHandle.__sizeof__())
|
||||
h.Trans = trans
|
||||
return h
|
||||
@@ -1,23 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
# Handles 模块(绝对导入,Viper 兼容)
|
||||
# 参考 Python 版 TransPyC lib/core/Handles 的细粒度拆分
|
||||
import lib.core.Handles.HandlesBase as HandlesBase
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesExprOps as HandlesExprOps
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.Handles.HandlesAssign as HandlesAssign
|
||||
import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign
|
||||
import lib.core.Handles.HandlesReturn as HandlesReturn
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesBody as HandlesBody
|
||||
import lib.core.Handles.HandlesIf as HandlesIf
|
||||
import lib.core.Handles.HandlesWhile as HandlesWhile
|
||||
import lib.core.Handles.HandlesFor as HandlesFor
|
||||
import lib.core.Handles.HandlesAugAssign as HandlesAugAssign
|
||||
import lib.core.Handles.HandlesMain as HandlesMain
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
@@ -1,365 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import stdlib
|
||||
import w32.win32file as win32file
|
||||
import w32.win32base as win32base
|
||||
import w32.fileio as fileio
|
||||
import hashlib
|
||||
import viperlib
|
||||
import lib.core.VLogger as VLogger
|
||||
|
||||
|
||||
# ============================================================
|
||||
# IncludesScanner - includes 目录递归扫描
|
||||
#
|
||||
# 递归扫描 includes 目录,收集所有 .py 文件路径和 SHA1,
|
||||
# 为 Phase1 stub 生成和 Phase2 stub 合并提供基础数据。
|
||||
#
|
||||
# 使用 Win32 FindFirstFileA/FindNextFileA 实现目录遍历。
|
||||
# ============================================================
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 文件路径最大长度
|
||||
MAX_PATH_LEN: t.CDefine = 512
|
||||
# 单次扫描最大文件数
|
||||
MAX_FILES: t.CDefine = 256
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FileEntry - 文件条目(路径 + SHA1)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class FileEntry:
|
||||
"""扫描到的文件条目"""
|
||||
Path: str # 文件绝对路径
|
||||
Sha1: str # SHA1 前16字符(16字节+null)
|
||||
RelPath: str # 相对于 includes 根目录的路径
|
||||
ModuleName: str # 模块名(如 "ast.parser")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# ScanResult - 扫描结果
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class ScanResult:
|
||||
"""扫描结果集合"""
|
||||
Entries: FileEntry | t.CPtr # FileEntry 数组
|
||||
Count: t.CInt
|
||||
Capacity: t.CInt
|
||||
|
||||
|
||||
# ============================================================
|
||||
# create_scan_result - 创建扫描结果容器
|
||||
# ============================================================
|
||||
def create_scan_result(pool: memhub.MemBuddy | t.CPtr) -> ScanResult | t.CPtr:
|
||||
"""创建扫描结果容器,预分配 MAX_FILES 个槽位"""
|
||||
if pool is None:
|
||||
return None
|
||||
size: t.CSizeT = MAX_FILES * FileEntry.__sizeof__()
|
||||
# 使用 stdlib.malloc 避免 mbuddy 池耗尽(与 StubMerger 保持一致)
|
||||
entries: FileEntry | t.CPtr = stdlib.malloc(size)
|
||||
if entries is None:
|
||||
return None
|
||||
string.memset(entries, 0, size)
|
||||
|
||||
result: ScanResult | t.CPtr = stdlib.malloc(ScanResult.__sizeof__())
|
||||
if result is None:
|
||||
return None
|
||||
string.memset(result, 0, ScanResult.__sizeof__())
|
||||
result.Entries = entries
|
||||
result.Count = 0
|
||||
result.Capacity = MAX_FILES
|
||||
return result
|
||||
|
||||
|
||||
# ============================================================
|
||||
# add_file_entry - 向扫描结果添加文件条目
|
||||
# ============================================================
|
||||
def add_file_entry(result: ScanResult | t.CPtr,
|
||||
pool: memhub.MemBuddy | t.CPtr,
|
||||
abs_path: str, rel_path: str,
|
||||
sha1: str) -> int:
|
||||
"""添加文件条目到扫描结果,返回 0 成功"""
|
||||
if result is None or pool is None:
|
||||
return 1
|
||||
if result.Count >= result.Capacity:
|
||||
return 1
|
||||
|
||||
# 计算模块名:rel_path 中的 / 替换为 .,去掉 .py 扩展名
|
||||
rel_len: t.CSizeT = string.strlen(rel_path)
|
||||
mod_buf: str = stdlib.malloc(rel_len + 1)
|
||||
if mod_buf is None:
|
||||
return 1
|
||||
string.strcpy(mod_buf, rel_path)
|
||||
# 替换 / 为 .
|
||||
for i in range(rel_len):
|
||||
ch: t.CChar = mod_buf[i]
|
||||
if ch == '/' or ch == '\\':
|
||||
mod_buf[i] = '.'
|
||||
# 去掉 .py 扩展名
|
||||
if rel_len >= 3:
|
||||
if mod_buf[rel_len - 3] == '.' and mod_buf[rel_len - 2] == 'p' and mod_buf[rel_len - 1] == 'y':
|
||||
mod_buf[rel_len - 3] = '\0'
|
||||
|
||||
# 获取条目地址
|
||||
entry_size: t.CSizeT = FileEntry.__sizeof__()
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + result.Count * entry_size
|
||||
entry: FileEntry | t.CPtr = (FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry is None:
|
||||
return 1
|
||||
|
||||
# 复制路径字符串
|
||||
abs_len: t.CSizeT = string.strlen(abs_path)
|
||||
abs_buf: str = stdlib.malloc(abs_len + 1)
|
||||
if abs_buf is None:
|
||||
return 1
|
||||
string.strcpy(abs_buf, abs_path)
|
||||
entry.Path = abs_buf
|
||||
|
||||
# 复制 SHA1
|
||||
sha1_buf: str = stdlib.malloc(17)
|
||||
if sha1_buf is None:
|
||||
return 1
|
||||
string.strcpy(sha1_buf, sha1)
|
||||
entry.Sha1 = sha1_buf
|
||||
|
||||
# 复制相对路径
|
||||
rel_buf: str = stdlib.malloc(rel_len + 1)
|
||||
if rel_buf is None:
|
||||
return 1
|
||||
string.strcpy(rel_buf, rel_path)
|
||||
entry.RelPath = rel_buf
|
||||
|
||||
# 复制模块名
|
||||
entry.ModuleName = mod_buf
|
||||
|
||||
result.Count += 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# compute_file_sha1 - 读取文件内容并计算 SHA1
|
||||
#
|
||||
# 与 Projectrans.py 一致:CRLF → LF 转换后计算 SHA1。
|
||||
# Projectrans.py 用 Python 文本模式读取(自动 CRLF→LF),
|
||||
# IncludesScanner 用二进制模式读取,需手动去除 \r。
|
||||
# ============================================================
|
||||
def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
|
||||
file_path: str) -> str:
|
||||
"""读取文件内容并计算 SHA1 前16字符(CRLF→LF 后计算,与 Projectrans.py 一致)"""
|
||||
if pool is None or file_path is None:
|
||||
return None
|
||||
|
||||
# 打开文件
|
||||
f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
return None
|
||||
|
||||
# 分配读取缓冲区(128KB,足够大多数 .py 文件)
|
||||
# 使用 stdlib.malloc 避免 mbuddy 池耗尽(每文件 128KB,60+ 文件会耗尽 16MB 池)
|
||||
BUF_SIZE: t.CSizeT = 131072
|
||||
buf: bytes = stdlib.malloc(BUF_SIZE)
|
||||
if buf is None:
|
||||
f.close()
|
||||
return None
|
||||
|
||||
# 读取文件内容
|
||||
bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE)
|
||||
f.close()
|
||||
if bytes_read <= 0:
|
||||
return None
|
||||
|
||||
# 原地去除 \r(CRLF → LF),与 Projectrans.py 文本模式读取一致
|
||||
write_pos: t.CSizeT = 0
|
||||
read_pos: t.CSizeT = 0
|
||||
while read_pos < bytes_read:
|
||||
ch: t.CChar = buf[read_pos]
|
||||
if ch != '\r':
|
||||
buf[write_pos] = ch
|
||||
write_pos += 1
|
||||
read_pos += 1
|
||||
|
||||
# 添加 null 终止符
|
||||
buf[write_pos] = 0
|
||||
|
||||
# 计算 SHA1
|
||||
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
|
||||
if ctx is None:
|
||||
return None
|
||||
ctx.update(buf)
|
||||
|
||||
digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN)
|
||||
if digest is None:
|
||||
return None
|
||||
ctx.final(digest)
|
||||
|
||||
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
|
||||
hex_buf: str = stdlib.malloc(17)
|
||||
if hex_buf is None:
|
||||
return None
|
||||
for i in range(8):
|
||||
hi: int = (digest[i] >> 4) & 0xF
|
||||
lo: int = digest[i] & 0xF
|
||||
if hi < 10:
|
||||
hex_buf[i * 2] = '0' + hi
|
||||
else:
|
||||
hex_buf[i * 2] = 'a' + (hi - 10)
|
||||
if lo < 10:
|
||||
hex_buf[i * 2 + 1] = '0' + lo
|
||||
else:
|
||||
hex_buf[i * 2 + 1] = 'a' + (lo - 10)
|
||||
hex_buf[16] = '\0'
|
||||
return hex_buf
|
||||
|
||||
|
||||
# ============================================================
|
||||
# scan_directory_recursive - 递归扫描目录
|
||||
#
|
||||
# 使用 FindFirstFileA/FindNextFileA 遍历目录树,
|
||||
# 对每个 .py 文件计算 SHA1 并添加到结果中。
|
||||
# ============================================================
|
||||
def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
|
||||
root_dir: str,
|
||||
rel_prefix: str,
|
||||
result: ScanResult | t.CPtr) -> int:
|
||||
"""递归扫描目录,收集 .py 文件"""
|
||||
if pool is None or root_dir is None or result is None:
|
||||
return 1
|
||||
|
||||
# 构造搜索模式: root_dir/*
|
||||
root_len: t.CSizeT = string.strlen(root_dir)
|
||||
pattern: bytes = stdlib.malloc(root_len + 4)
|
||||
if pattern is None:
|
||||
return 1
|
||||
viperlib.snprintf(pattern, root_len + 4, "%s/*", root_dir)
|
||||
|
||||
# 使用 FindFirstFileA 开始搜索
|
||||
find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
if find_data is None:
|
||||
return 1
|
||||
string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
|
||||
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
|
||||
if handle == win32base.INVALID_HANDLE_VALUE:
|
||||
return 1
|
||||
|
||||
# 遍历所有文件和子目录
|
||||
while True:
|
||||
# 跳过 . 和 ..
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
fname0: t.CChar = fname[0]
|
||||
if fname0 == '.':
|
||||
fname1: t.CChar = fname[1]
|
||||
if fname1 == '\0':
|
||||
# "."
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
continue
|
||||
elif fname1 == '.':
|
||||
fname2: t.CChar = fname[2]
|
||||
if fname2 == '\0':
|
||||
# ".."
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
continue
|
||||
|
||||
# 检查是否为目录
|
||||
is_dir: int = find_data.dwFileAttributes & win32file.FILE_ATTRIBUTE_DIRECTORY
|
||||
|
||||
# 构造完整路径
|
||||
fname_len: t.CSizeT = string.strlen(fname)
|
||||
full_path: bytes = stdlib.malloc(root_len + fname_len + 2)
|
||||
if full_path is None:
|
||||
break
|
||||
viperlib.snprintf(full_path, root_len + fname_len + 2, "%s/%s", root_dir, fname)
|
||||
|
||||
# 构造相对路径
|
||||
prefix_len: t.CSizeT = 0
|
||||
if rel_prefix is not None:
|
||||
prefix_len = string.strlen(rel_prefix)
|
||||
rel_path: bytes = stdlib.malloc(prefix_len + fname_len + 2)
|
||||
if rel_path is None:
|
||||
break
|
||||
if rel_prefix is not None and prefix_len > 0:
|
||||
viperlib.snprintf(rel_path, prefix_len + fname_len + 2, "%s/%s", rel_prefix, fname)
|
||||
else:
|
||||
string.strcpy(rel_path, fname)
|
||||
|
||||
if is_dir != 0:
|
||||
# 递归扫描子目录
|
||||
scan_directory_recursive(pool, full_path, rel_path, result)
|
||||
else:
|
||||
# 检查是否为 .py 文件
|
||||
is_py: int = 0
|
||||
if fname_len >= 3:
|
||||
if fname[fname_len - 3] == '.' and fname[fname_len - 2] == 'p' and fname[fname_len - 1] == 'y':
|
||||
is_py = 1
|
||||
|
||||
if is_py != 0:
|
||||
# 跳过 __pycache__ 目录下的文件
|
||||
is_pycache: int = 0
|
||||
if rel_prefix is not None:
|
||||
if string.strcmp(rel_prefix, "__pycache__") == 0:
|
||||
is_pycache = 1
|
||||
|
||||
if is_pycache == 0:
|
||||
# 计算 SHA1
|
||||
sha1: str = compute_file_sha1(pool, full_path)
|
||||
if sha1 is not None:
|
||||
add_file_entry(result, pool, full_path, rel_path, sha1)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "扫描: %s -> %s", rel_path, sha1)
|
||||
VLogger.debug(fb, "scan")
|
||||
|
||||
# 继续搜索下一个文件
|
||||
if win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
|
||||
win32file.FindClose(handle)
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# scan_includes - 扫描 includes 目录入口
|
||||
#
|
||||
# 扫描指定的 includes 目录,返回所有 .py 文件的路径和 SHA1。
|
||||
# ============================================================
|
||||
def scan_includes(pool: memhub.MemBuddy | t.CPtr,
|
||||
includes_dir: str) -> ScanResult | t.CPtr:
|
||||
"""扫描 includes 目录,返回所有 .py 文件的扫描结果"""
|
||||
if pool is None or includes_dir is None:
|
||||
return None
|
||||
|
||||
result: ScanResult | t.CPtr = create_scan_result(pool)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
scan_directory_recursive(pool, includes_dir, None, result)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# ============================================================
|
||||
# find_entry_by_module - 按模块名查找文件条目
|
||||
# ============================================================
|
||||
def find_entry_by_module(result: ScanResult | t.CPtr,
|
||||
module_name: str) -> FileEntry | t.CPtr:
|
||||
"""按模块名查找文件条目"""
|
||||
if result is None or module_name is None:
|
||||
return None
|
||||
entry_size: t.CSizeT = FileEntry.__sizeof__()
|
||||
for i in range(result.Count):
|
||||
entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size
|
||||
entry: FileEntry | t.CPtr = (FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr))
|
||||
if entry is not None:
|
||||
if entry.ModuleName is not None:
|
||||
if entry.ModuleName == module_name:
|
||||
return entry
|
||||
return None
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,953 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import viperlib
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import sys
|
||||
import ast
|
||||
import llvmlite
|
||||
import subprocess
|
||||
import argparse
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesImports as HandlesImports
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import lib.Projectrans.Config as Config
|
||||
|
||||
# 全局 mbuddy 指针
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 源代码缓冲区大小(1MB)
|
||||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||||
|
||||
# 最大源文件数(递归扫描子目录后文件数增多,增大到 64)
|
||||
MAX_SRC_FILES: t.CDefine = 64
|
||||
|
||||
# 全局栈金丝雀(避免局部变量改变栈布局)
|
||||
_g_canary: t.CUInt32T
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class SrcFileEntry:
|
||||
"""源文件条目"""
|
||||
Path: str # 完整路径
|
||||
Sha1: str # SHA1 前16字符
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _ScanDirForPyFiles - 递归扫描目录,收集 .py 文件到 entries
|
||||
#
|
||||
# 替代旧的非递归 FindFirstFileA(dir/*.py) 扫描,支持子目录
|
||||
# (如 App/lib/core/Handles/)。遇到目录递归扫描,遇到 .py
|
||||
# 文件读取内容、计算 SHA1、加入 entries。
|
||||
#
|
||||
# Args:
|
||||
# mb: 内存池
|
||||
# dir_path: 当前扫描目录
|
||||
# entries: SrcFileEntry 数组
|
||||
# entry_size: 单个条目大小(SrcFileEntry.__sizeof__())
|
||||
# file_count: 当前已收集的文件数
|
||||
# max_files: 最大文件数
|
||||
#
|
||||
# Returns:
|
||||
# 新的 file_count
|
||||
# ============================================================
|
||||
def _ScanDirForPyFiles(mb: memhub.MemBuddy | t.CPtr,
|
||||
dir_path: str,
|
||||
entries: SrcFileEntry | t.CPtr,
|
||||
entry_size: t.CSizeT,
|
||||
file_count: int, max_files: int) -> int:
|
||||
"""递归扫描目录,收集 .py 文件到 entries,返回新的 file_count"""
|
||||
if dir_path is None or entries is None:
|
||||
return file_count
|
||||
if file_count >= max_files:
|
||||
return file_count
|
||||
|
||||
dir_len: t.CSizeT = string.strlen(dir_path)
|
||||
pattern: bytes = stdlib.malloc(dir_len + 16)
|
||||
if pattern is None:
|
||||
return file_count
|
||||
viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path)
|
||||
|
||||
find_data_size: t.CSizeT = w32.win32file.WIN32_FIND_DATAA.__sizeof__()
|
||||
find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(find_data_size + 16)
|
||||
if find_data is None:
|
||||
stdlib.free(pattern)
|
||||
return file_count
|
||||
string.memset(find_data, 0, find_data_size + 16)
|
||||
|
||||
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data)
|
||||
if handle == w32.win32base.INVALID_HANDLE_VALUE:
|
||||
stdlib.free(pattern)
|
||||
stdlib.free(find_data)
|
||||
return file_count
|
||||
|
||||
while True:
|
||||
fname: str = find_data.cFileName
|
||||
if fname is not None:
|
||||
fname_len: t.CSizeT = string.strlen(fname)
|
||||
if fname_len > 0:
|
||||
# 跳过 . 和 ..
|
||||
is_dot: int = 0
|
||||
if fname_len == 1 and fname[0] == '.':
|
||||
is_dot = 1
|
||||
elif fname_len == 2 and fname[0] == '.' and fname[1] == '.':
|
||||
is_dot = 1
|
||||
if is_dot == 0:
|
||||
# 检查是否是目录
|
||||
attrs: ULONG = find_data.dwFileAttributes
|
||||
is_dir: int = 0
|
||||
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
|
||||
is_dir = 1
|
||||
if is_dir != 0:
|
||||
# 递归扫描子目录
|
||||
sub_dir: bytes = stdlib.malloc(dir_len + fname_len + 2)
|
||||
if sub_dir is not None:
|
||||
viperlib.snprintf(sub_dir, dir_len + fname_len + 2, "%s/%s", dir_path, fname)
|
||||
file_count = _ScanDirForPyFiles(mb, sub_dir, entries, entry_size, file_count, max_files)
|
||||
stdlib.free(sub_dir)
|
||||
else:
|
||||
# 检查是否是 .py 文件
|
||||
if fname_len > 3:
|
||||
if fname[fname_len - 3] == '.' and fname[fname_len - 2] == 'p' and fname[fname_len - 1] == 'y':
|
||||
if file_count < max_files:
|
||||
full_path: bytes = stdlib.malloc(dir_len + fname_len + 2)
|
||||
if full_path is not None:
|
||||
viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", dir_path, fname)
|
||||
sf: fileio.File | t.CPtr = fileio.File(full_path, fileio.MODE.R)
|
||||
if not sf.closed:
|
||||
sbuf: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||||
if sbuf is not None:
|
||||
br: LONG = sf.read_all(sbuf, SRC_BUF_SIZE)
|
||||
sf.close()
|
||||
if br > 0:
|
||||
if br < SRC_BUF_SIZE:
|
||||
sbuf[br] = 0
|
||||
else:
|
||||
sbuf[SRC_BUF_SIZE - 1] = 0
|
||||
sha1_val: str = Utils.compute_sha1(mb, sbuf)
|
||||
if sha1_val is not None:
|
||||
ea: t.CUInt64T = t.CUInt64T(entries) + file_count * entry_size
|
||||
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
if ent is not None:
|
||||
ent.Path = full_path
|
||||
ent.Sha1 = sha1_val
|
||||
file_count += 1
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "%s (sha1=%s)", fname, sha1_val)
|
||||
VLogger.info(fb, "project")
|
||||
stdlib.free(sbuf)
|
||||
# full_path 不释放:ent.Path 引用它
|
||||
|
||||
if w32.win32file.FindNextFileA(handle, find_data) == 0:
|
||||
break
|
||||
|
||||
w32.win32file.FindClose(handle)
|
||||
stdlib.free(pattern)
|
||||
stdlib.free(find_data)
|
||||
return file_count
|
||||
|
||||
|
||||
def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr,
|
||||
source_dir: str, temp_dir: str, output_dir: str,
|
||||
cc_cmd: str, cc_flags: str,
|
||||
linker_cmd: str, linker_flags: str, linker_output: str,
|
||||
includes_binary_dir: str,
|
||||
includes_dir: str,
|
||||
do_phase1: int, do_phase2: int,
|
||||
log: VLogger.Logger | t.CPtr,
|
||||
args: argparse.ParsedArgs | t.CPtr) -> int:
|
||||
"""多文件项目编译
|
||||
|
||||
Returns: 0 成功,非 0 失败
|
||||
"""
|
||||
if source_dir is None:
|
||||
VLogger.error("source_dir 为空", "project")
|
||||
return 1
|
||||
|
||||
# === 栈金丝雀检查(全局变量,不影响栈布局)===
|
||||
_g_canary = 305419896
|
||||
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "多文件项目编译: %s", source_dir)
|
||||
VLogger.info(fb, "project")
|
||||
|
||||
# === 1. 递归扫描 source_dir 下的 .py 文件(包括子目录)===
|
||||
entry_size: t.CSizeT = SrcFileEntry.__sizeof__()
|
||||
entries: SrcFileEntry | t.CPtr = stdlib.malloc(MAX_SRC_FILES * entry_size)
|
||||
if entries is None:
|
||||
return 1
|
||||
string.memset(entries, 0, MAX_SRC_FILES * entry_size)
|
||||
|
||||
file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "共 %d 个源文件", file_count)
|
||||
VLogger.info(fb, "project")
|
||||
|
||||
if file_count == 0:
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
|
||||
# 初始化 AST 表
|
||||
ast._init_tables(mb)
|
||||
|
||||
# 确保 temp/output 目录存在
|
||||
BuildPipeline.ensure_dir(temp_dir)
|
||||
BuildPipeline.ensure_dir(output_dir)
|
||||
|
||||
# === 0.5 扫描 includes 目录填充 Sha1Store(消除 Phase1 依赖)===
|
||||
# Phase2 不依赖 Phase1 的副作用:如果 Sha1Store 为空(Phase1 未运行或提前返回),
|
||||
# 自行扫描 includes 目录并填充 Sha1Store,确保后续"编译缺失 includes"逻辑能正常工作
|
||||
if includes_dir is not None:
|
||||
if StubMerger.GetSha1StoreCount() == 0:
|
||||
inc_scan_result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir)
|
||||
if inc_scan_result is not None:
|
||||
inc_filled: int = StubMerger.PopulateSha1MapStore(inc_scan_result)
|
||||
fb_inc: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc is not None:
|
||||
viperlib.snprintf(fb_inc, 1024, "Phase2 自主填充 includes Sha1Store: %d 个", inc_filled)
|
||||
VLogger.info(fb_inc, "project")
|
||||
|
||||
# 追加 App 源文件 SHA1 到 _sha1_map.txt(人类可读输出,程序内部不读取此文件)
|
||||
# 格式: {sha1}:{rel_path}\n (保留目录结构,如 lib/core/VLogger.py)
|
||||
# 同步追加到内存存储器(AppendToSha1MapStore,供跨模块 CDefine 查找)
|
||||
td_len_am: t.CSizeT = string.strlen(temp_dir)
|
||||
src_dir_len_am: t.CSizeT = string.strlen(source_dir)
|
||||
map_path_am: bytes = stdlib.malloc(td_len_am + 32)
|
||||
if map_path_am is not None:
|
||||
viperlib.snprintf(map_path_am, td_len_am + 32, "%s/_sha1_map.txt", temp_dir)
|
||||
mf: fileio.File | t.CPtr = fileio.File(map_path_am, fileio.MODE.A)
|
||||
line_am: bytes = stdlib.malloc(512)
|
||||
# 先遍历一次填充内存存储器(不依赖文件 I/O),再写入 _sha1_map.txt
|
||||
app_filled: int = 0
|
||||
for i in range(file_count):
|
||||
ea_am: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent_am: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_am, t.CPtr))
|
||||
if ent_am is None or ent_am.Path is None or ent_am.Sha1 is None:
|
||||
continue
|
||||
# 计算相对路径(去除 source_dir 前缀,保留目录结构)
|
||||
p_str: str = ent_am.Path
|
||||
p_len: t.CSizeT = string.strlen(p_str)
|
||||
rel_path_am: str = p_str
|
||||
if p_len > src_dir_len_am + 1:
|
||||
if string.strncmp(p_str, source_dir, src_dir_len_am) == 0:
|
||||
rel_path_am = p_str + src_dir_len_am + 1
|
||||
# 同步追加到内存存储器(供跨模块 CDefine 查找)
|
||||
# rel_path_am 格式如 "lib/core/StubMerger.py",与 _sha1_map.txt 一致
|
||||
if StubMerger.AppendToSha1MapStore(ent_am.Sha1, rel_path_am) == 0:
|
||||
app_filled += 1
|
||||
# 写入 _sha1_map.txt(人类可读输出)
|
||||
if not mf.closed and line_am is not None:
|
||||
viperlib.snprintf(line_am, 512, "%s:%s\n", ent_am.Sha1, rel_path_am)
|
||||
ll_am: t.CSizeT = string.strlen(line_am)
|
||||
mf.write(line_am, ll_am)
|
||||
if line_am is not None:
|
||||
stdlib.free(line_am)
|
||||
if not mf.closed:
|
||||
mf.close()
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "已追加 %d 个 App 文件到 _sha1_map.txt 和内存存储器", app_filled)
|
||||
VLogger.info(fb, "project")
|
||||
stdlib.free(map_path_am)
|
||||
|
||||
# 构建模块 SHA1 映射(供跨模块函数调用名混淆使用)
|
||||
td_len_pb: t.CSizeT = string.strlen(temp_dir)
|
||||
pb_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
|
||||
pb_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
|
||||
pb_inc_count: int = 0
|
||||
if pb_sha1_arr is not None and pb_mod_arr is not None:
|
||||
pb_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_pb, pb_sha1_arr, pb_mod_arr)
|
||||
# 追加用户源文件的 (模块名, SHA1) 到全局映射
|
||||
# 使跨模块方法调用能通过 from_imports + _lookup_module_sha1 找到正确的 SHA1
|
||||
if pb_sha1_arr is not None and pb_mod_arr is not None:
|
||||
src_dir_len_us: t.CSizeT = string.strlen(source_dir)
|
||||
for i in range(file_count):
|
||||
ea_us: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent_us: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_us, t.CPtr))
|
||||
if ent_us is None or ent_us.Path is None or ent_us.Sha1 is None:
|
||||
continue
|
||||
if pb_inc_count >= StubMerger.MAX_INCLUDES:
|
||||
break
|
||||
# 计算相对路径并转换为点分模块名(保留完整包路径)
|
||||
path_str: str = ent_us.Path
|
||||
path_len_us: t.CSizeT = string.strlen(path_str)
|
||||
rel_path_us: str = path_str
|
||||
if path_len_us > src_dir_len_us + 1:
|
||||
if string.strncmp(path_str, source_dir, src_dir_len_us) == 0:
|
||||
rel_path_us = path_str + src_dir_len_us + 1
|
||||
# 使用 _PathToModuleName 转换为点分模块名(处理 __init__.py → 包名)
|
||||
mod_name_us: str = StubMerger._PathToModuleName(rel_path_us)
|
||||
if mod_name_us is None:
|
||||
continue
|
||||
# 写入模块名
|
||||
mod_idx: t.CSizeT = t.CSizeT(pb_inc_count) * 64
|
||||
mn_len_us: t.CSizeT = string.strlen(mod_name_us)
|
||||
if mn_len_us >= 64:
|
||||
string.strncpy(pb_mod_arr + mod_idx, mod_name_us, 63)
|
||||
pb_mod_arr[mod_idx + 63] = '\0'
|
||||
else:
|
||||
string.strcpy(pb_mod_arr + mod_idx, mod_name_us)
|
||||
stdlib.free(mod_name_us)
|
||||
# 写入 SHA1
|
||||
sha1_idx: t.CSizeT = t.CSizeT(pb_inc_count) * 17
|
||||
string.strcpy(pb_sha1_arr + sha1_idx, ent_us.Sha1)
|
||||
pb_inc_count += 1
|
||||
HandlesExprCall.set_module_sha1_map(pb_sha1_arr, pb_mod_arr, pb_inc_count)
|
||||
|
||||
|
||||
# === 2. Phase A: 为每个文件生成 stub + text ===
|
||||
# app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔)
|
||||
# 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist,实现按需编译
|
||||
# 声明在 if 块外,确保 Phase B+ 和清理代码能访问
|
||||
APP_DEPS_BUF_SIZE: t.CSizeT = 8192
|
||||
app_deps_buf: bytes = None
|
||||
app_deps_len: t.CSizeT = 0
|
||||
if do_phase1 != 0:
|
||||
if log is not None:
|
||||
log.banner("Phase A: 生成 stub + text")
|
||||
|
||||
# === Phase A-pre-inc: includes 预注册 struct + 依赖填充 ===
|
||||
# 必须在 App 源文件预注册之前执行:App 源文件(strict_mode=1)可能继承
|
||||
# 或引用 includes 中的 struct(如 ast.AST)。若 includes struct 未注册,
|
||||
# App 源文件翻译会失败 → .obj 缺失 → undefined reference。
|
||||
# 同时填充 PopulateIncludesDeps,供 Phase B+ 的 _BuildReachableSha1Set 使用。
|
||||
# 多遍扫描:解决跨文件继承问题(如 Constant(AST) 在 AST 未注册时被跳过)。
|
||||
if includes_dir is not None and includes_binary_dir is not None:
|
||||
store_count_inc_pre: int = StubMerger.GetSha1StoreCount()
|
||||
if store_count_inc_pre > 0:
|
||||
store_sha1_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_rel_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
inc_dir_len_pre: t.CSizeT = string.strlen(includes_dir)
|
||||
deps_filled_pre: int = 0
|
||||
PHASE_A_INC_MAX_PASSES: t.CInt = 3
|
||||
for pass_inc_i in range(PHASE_A_INC_MAX_PASSES):
|
||||
struct_count_before_inc: int = HandlesStruct.get_struct_count()
|
||||
for si_inc in range(store_count_inc_pre):
|
||||
inc_sha1_pre: str = store_sha1_inc_pre + t.CSizeT(si_inc) * 17
|
||||
inc_rel_pre: str = store_rel_inc_pre + t.CSizeT(si_inc) * StubMerger.MAX_REL_PATH_LEN
|
||||
if inc_rel_pre is None or inc_rel_pre[0] == '\0':
|
||||
continue
|
||||
rel_len_pre: t.CSizeT = string.strlen(inc_rel_pre)
|
||||
full_path_pre: bytes = stdlib.malloc(inc_dir_len_pre + rel_len_pre + 2)
|
||||
if full_path_pre is None:
|
||||
continue
|
||||
viperlib.snprintf(full_path_pre, inc_dir_len_pre + rel_len_pre + 2,
|
||||
"%s/%s", includes_dir, inc_rel_pre)
|
||||
pkg_inc_pre: str = HandlesImports.compute_package_from_relpath(mb, inc_rel_pre)
|
||||
tr_inc_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(
|
||||
mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1)
|
||||
stdlib.free(full_path_pre)
|
||||
if tr_inc_pre is not None:
|
||||
# 依赖填充只在第一遍执行(PopulateIncludesDeps 内部有去重)
|
||||
if pass_inc_i == 0:
|
||||
if tr_inc_pre._imported_modules is not None:
|
||||
if StubMerger.PopulateIncludesDeps(inc_sha1_pre, tr_inc_pre._imported_modules) == 0:
|
||||
deps_filled_pre = deps_filled_pre + 1
|
||||
struct_count_after_inc: int = HandlesStruct.get_struct_count()
|
||||
# 收敛检查:本遍没有新结构体注册 → 所有类已注册
|
||||
if struct_count_after_inc == struct_count_before_inc:
|
||||
break
|
||||
fb_inc_pre: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc_pre is not None:
|
||||
viperlib.snprintf(fb_inc_pre, 1024, "includes 预注册 + 依赖填充: %d/%d", deps_filled_pre, store_count_inc_pre)
|
||||
VLogger.info(fb_inc_pre, "prePhaseA")
|
||||
|
||||
# === Phase A-pre: 预注册所有源文件的 struct/enum/union ===
|
||||
# 解决循环引用问题:circ_a 翻译时需要知道 circ_b.ClassB 的 struct 定义
|
||||
# 仅注册 struct/enum/union(declare_only=1),不翻译方法体
|
||||
# 多遍扫描:解决跨文件继承的字母序问题(如 HandlesAnnAssign.py 在 HandlesBase.py 之前,
|
||||
# AnnAssignHandle 继承 Mixin 时 Mixin 未注册)。每遍注册新类后,下一遍子类可继承。
|
||||
VLogger.info("预注册 struct/enum/union...", "PhaseA")
|
||||
src_dir_len_pre: t.CSizeT = string.strlen(source_dir)
|
||||
PHASE_A_PRE_MAX_PASSES: t.CInt = 3
|
||||
for pass_i in range(PHASE_A_PRE_MAX_PASSES):
|
||||
struct_count_before: int = HandlesStruct.get_struct_count()
|
||||
for i in range(file_count):
|
||||
ea_pre: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_pre, t.CPtr))
|
||||
if ent_pre is None or ent_pre.Path is None:
|
||||
continue
|
||||
pkg_pre: str = None
|
||||
if string.strlen(ent_pre.Path) > src_dir_len_pre + 1:
|
||||
rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1
|
||||
pkg_pre = HandlesImports.compute_package_from_relpath(mb, rel_path_pre)
|
||||
tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1)
|
||||
if tr_pre is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path)
|
||||
VLogger.warning(fb, "PhaseA")
|
||||
struct_count_after: int = HandlesStruct.get_struct_count()
|
||||
# 收敛检查:本遍没有新结构体注册 → 所有类已注册
|
||||
if struct_count_after == struct_count_before:
|
||||
break
|
||||
VLogger.info("预注册完成", "PhaseA")
|
||||
|
||||
PHASE_A_IR_SIZE: t.CSizeT = 1048576
|
||||
td_len_pa: t.CSizeT = string.strlen(temp_dir)
|
||||
|
||||
# app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔)
|
||||
# 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist 使用
|
||||
# 声明已在 if 块外,此处仅赋值
|
||||
app_deps_buf = stdlib.malloc(APP_DEPS_BUF_SIZE)
|
||||
app_deps_len = 0
|
||||
if app_deps_buf is not None:
|
||||
app_deps_buf[0] = '\0'
|
||||
|
||||
for i in range(file_count):
|
||||
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
if ent is None or ent.Path is None:
|
||||
continue
|
||||
# 计算源文件的包名(相对 source_dir 的目录部分)
|
||||
src_dir_len_pa: t.CSizeT = string.strlen(source_dir)
|
||||
pkg_pa: str = None
|
||||
if string.strlen(ent.Path) > src_dir_len_pa + 1:
|
||||
rel_path_pa: str = ent.Path + src_dir_len_pa + 1
|
||||
pkg_pa = HandlesImports.compute_package_from_relpath(mb, rel_path_pa)
|
||||
tr_a: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent.Path, ent.Sha1, pkg_pa)
|
||||
if tr_a is None:
|
||||
continue
|
||||
|
||||
# dump stub IR (declarations only)
|
||||
stub_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE)
|
||||
if stub_buf_a is None:
|
||||
continue
|
||||
tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_STUB)
|
||||
stub_len_a: t.CSizeT = string.strlen(stub_buf_a)
|
||||
|
||||
# save stub.ll (切片路径: temp_dir/{sha1前缀}/{sha1}.stub.ll)
|
||||
stub_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "stub.ll")
|
||||
if stub_path_a is not None:
|
||||
sf_a: fileio.File | t.CPtr = fileio.File(stub_path_a, fileio.MODE.W)
|
||||
if not sf_a.closed:
|
||||
sf_a.write(stub_buf_a, stub_len_a)
|
||||
sf_a.close()
|
||||
stdlib.free(stub_path_a)
|
||||
stdlib.free(stub_buf_a)
|
||||
|
||||
# dump text IR (definitions only)
|
||||
text_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE)
|
||||
if text_buf_a is None:
|
||||
continue
|
||||
tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_TEXT)
|
||||
text_len_a: t.CSizeT = string.strlen(text_buf_a)
|
||||
|
||||
# save text.ll (切片路径)
|
||||
text_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "text.ll")
|
||||
if text_path_a is not None:
|
||||
tf_a: fileio.File | t.CPtr = fileio.File(text_path_a, fileio.MODE.W)
|
||||
if not tf_a.closed:
|
||||
tf_a.write(text_buf_a, text_len_a)
|
||||
tf_a.close()
|
||||
stdlib.free(text_path_a)
|
||||
stdlib.free(text_buf_a)
|
||||
|
||||
# save dependencies (_imported_modules) for Phase B (切片路径)
|
||||
deps_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "deps.txt")
|
||||
if deps_path_a is not None:
|
||||
df_a: fileio.File | t.CPtr = fileio.File(deps_path_a, fileio.MODE.W)
|
||||
if not df_a.closed:
|
||||
if tr_a._imported_modules is not None:
|
||||
dl_a: t.CSizeT = string.strlen(tr_a._imported_modules)
|
||||
df_a.write(tr_a._imported_modules, dl_a)
|
||||
df_a.close()
|
||||
stdlib.free(deps_path_a)
|
||||
|
||||
# 收集 _imported_modules 到 app_deps_buf(供 Phase B+ 按需编译)
|
||||
if tr_a._imported_modules is not None and app_deps_buf is not None:
|
||||
im_len_a: t.CSizeT = string.strlen(tr_a._imported_modules)
|
||||
if im_len_a > 0 and app_deps_len + im_len_a + 1 < APP_DEPS_BUF_SIZE:
|
||||
if app_deps_len > 0:
|
||||
app_deps_buf[app_deps_len] = ' '
|
||||
app_deps_len = app_deps_len + 1
|
||||
string.strcpy(app_deps_buf + app_deps_len, tr_a._imported_modules)
|
||||
app_deps_len = app_deps_len + im_len_a
|
||||
app_deps_buf[app_deps_len] = '\0'
|
||||
|
||||
if do_phase2 == 0:
|
||||
VLogger.info("Phase A 完成(仅 stub 生成)", "project")
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
stdlib.free(entries)
|
||||
return 0
|
||||
|
||||
# === 3. Phase B: 编译每个文件为 .obj ===
|
||||
if do_phase2 != 0:
|
||||
if log is not None:
|
||||
log.banner("Phase B: 编译 .obj")
|
||||
|
||||
# 收集 .obj 路径(增大到 64KB,避免 includes .obj 路径溢出导致链接丢失符号)
|
||||
# reachable_set/reachable_count: Phase B+ 填充,Phase C 用于按需链接
|
||||
reachable_set: bytes = None
|
||||
reachable_count: int = 0
|
||||
OBJ_PATHS_SIZE: t.CSizeT = 65536
|
||||
obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE)
|
||||
if obj_paths is None:
|
||||
return 1
|
||||
obj_paths[0] = '\0'
|
||||
obj_pos: t.CSizeT = 0
|
||||
# main_obj_path: 存放定义了用户 main 的 .obj 路径(链接时放在最前面,
|
||||
# 避免 --allow-multiple-definition 选择了其他模块的 wrapper main)
|
||||
main_obj_path: bytes = stdlib.malloc(512)
|
||||
if main_obj_path is None:
|
||||
return 1
|
||||
main_obj_path[0] = '\0'
|
||||
compiled_count: int = 0
|
||||
|
||||
# 组合 IR 缓冲区大小(4MB,足够容纳本地 stub + 所有依赖 stub + 本地 text)
|
||||
COMBINED_IR_SIZE: t.CSizeT = 4194304
|
||||
|
||||
for i in range(file_count):
|
||||
ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size
|
||||
ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr))
|
||||
if ent is None or ent.Path is None or ent.Sha1 is None:
|
||||
continue
|
||||
# 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR
|
||||
combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE)
|
||||
if combined_ir is None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path)
|
||||
VLogger.error(fb, "PhaseB")
|
||||
continue
|
||||
combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE)
|
||||
if combined_len == 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "BuildCombinedIR 失败: %s", ent.Path)
|
||||
VLogger.error(fb, "PhaseB")
|
||||
stdlib.free(combined_ir)
|
||||
continue
|
||||
|
||||
# 编译为 .obj
|
||||
cret: int = BuildPipeline.compile_module_to_obj(
|
||||
combined_ir, combined_len, temp_dir, output_dir, ent.Sha1,
|
||||
cc_cmd, cc_flags)
|
||||
stdlib.free(combined_ir)
|
||||
if cret != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", ent.Path)
|
||||
VLogger.error(fb, "PhaseB")
|
||||
sys.exit(1)
|
||||
|
||||
compiled_count += 1
|
||||
# 显示编译完成的文件
|
||||
fb_comp: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_comp is not None:
|
||||
viperlib.snprintf(fb_comp, 1024, "[%d/%d] 编译完成: %s", i + 1, file_count, ent.Path)
|
||||
VLogger.info(fb_comp, "PhaseB")
|
||||
# 构造 .obj 路径,检测是否是 main 模块(test_main.py 或 main.py)
|
||||
od_len: t.CSizeT = string.strlen(output_dir)
|
||||
is_main_mod: int = 0
|
||||
if string.strstr(ent.Path, "test_main.py") is not None:
|
||||
is_main_mod = 1
|
||||
elif string.strstr(ent.Path, "main.py") is not None:
|
||||
is_main_mod = 1
|
||||
|
||||
# 切片路径: output_dir/{sha1前缀}/{sha1}.obj
|
||||
obj_path_sliced: str = StubMerger._sliced_path(output_dir, od_len, ent.Sha1, "obj")
|
||||
if obj_path_sliced is not None:
|
||||
op_sliced_len: t.CSizeT = string.strlen(obj_path_sliced)
|
||||
if is_main_mod != 0:
|
||||
# main 模块: 复制到 main_obj_path(确保链接时 main 在最前)
|
||||
if op_sliced_len < 512:
|
||||
string.strcpy(main_obj_path, obj_path_sliced)
|
||||
else:
|
||||
VLogger.warning("main_obj_path 缓冲区不足", "PhaseB")
|
||||
else:
|
||||
# 其他模块: 追加到 obj_paths
|
||||
if obj_pos + op_sliced_len + 2 < OBJ_PATHS_SIZE:
|
||||
if obj_pos > 0:
|
||||
obj_paths[obj_pos] = ' '
|
||||
obj_pos += 1
|
||||
string.strcpy(obj_paths + obj_pos, obj_path_sliced)
|
||||
obj_pos += op_sliced_len
|
||||
obj_paths[obj_pos] = '\0'
|
||||
else:
|
||||
VLogger.warning(".obj 路径缓冲区不足", "PhaseB")
|
||||
stdlib.free(obj_path_sliced)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count)
|
||||
VLogger.success(fb, "PhaseB")
|
||||
|
||||
if compiled_count == 0:
|
||||
VLogger.error("无成功编译的文件", "PhaseB")
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
|
||||
# === 3.5 编译缺失的 includes 文件(按依赖图按需编译)===
|
||||
# 只编译被 App 源文件直接/间接引用的 includes 文件(可达集合),
|
||||
# 而非遍历整个 includes 目录。通过 _BuildReachableSha1Set 构建依赖图。
|
||||
if includes_dir is not None and includes_binary_dir is not None:
|
||||
inc_compiled: int = 0
|
||||
td_len_mi: t.CSizeT = string.strlen(temp_dir)
|
||||
|
||||
# 诊断日志:确认 Phase B+ 入口和 Sha1Store 状态
|
||||
fb_pbp_enter: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_pbp_enter is not None:
|
||||
viperlib.snprintf(fb_pbp_enter, 1024,
|
||||
"PhaseB+ 入口: store_count=%d includes_binary_dir=%s",
|
||||
StubMerger.GetSha1StoreCount(), includes_binary_dir)
|
||||
VLogger.info(fb_pbp_enter, "PhaseB+")
|
||||
|
||||
# 创建 includes_binary_dir 目录(确保 .obj 能写入和 collect_obj_files 能扫描)
|
||||
BuildPipeline.ensure_dir(includes_binary_dir)
|
||||
|
||||
# declare_only 预处理已移至 Phase A 之前(Phase A-pre-inc),
|
||||
# 确保 Phase A 翻译 App 源文件时 includes struct 已注册。
|
||||
# PopulateIncludesDeps 已在 Phase A-pre-inc 中填充。
|
||||
|
||||
# 构建可达 SHA1 集合(依赖图遍历)
|
||||
# app_deps_buf 为 None 时回退到扫描 source_dir(非递归)
|
||||
REACHABLE_SET_SIZE: t.CSizeT = t.CSizeT(StubMerger.MAX_INCLUDES_SHA1) * 17
|
||||
reachable_set: bytes = stdlib.malloc(REACHABLE_SET_SIZE)
|
||||
reachable_count: int = 0
|
||||
if reachable_set is not None:
|
||||
string.memset(reachable_set, 0, REACHABLE_SET_SIZE)
|
||||
reachable_count = StubMerger._BuildReachableSha1Set(
|
||||
mb, source_dir, temp_dir, reachable_set, app_deps_buf)
|
||||
fb_reach: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_reach is not None:
|
||||
viperlib.snprintf(fb_reach, 1024, "可达 includes SHA1: %d 个", reachable_count)
|
||||
VLogger.info(fb_reach, "PhaseB+")
|
||||
# fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止
|
||||
if reachable_count < 0:
|
||||
VLogger.error("可达集合构建失败(fast-fail),终止编译", "PhaseB+")
|
||||
return 1
|
||||
else:
|
||||
VLogger.error("reachable_set 分配失败,终止编译", "PhaseB+")
|
||||
return 1
|
||||
|
||||
# 释放 app_deps_buf(已构建完 reachable_set,不再需要)
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
app_deps_buf = None
|
||||
|
||||
# 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题)
|
||||
store_count_mi: int = StubMerger.GetSha1StoreCount()
|
||||
if store_count_mi > 0:
|
||||
store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr()
|
||||
store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr()
|
||||
store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr()
|
||||
|
||||
for si_mi in range(store_count_mi):
|
||||
# 获取当前条目的 SHA1 和 rel_path
|
||||
inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17
|
||||
inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN
|
||||
# 按需编译过滤:只处理 reachable_set 中的 includes
|
||||
# 永不回退:reachable_count > 0 时严格按可达集合过滤
|
||||
if reachable_count > 0:
|
||||
if StubMerger._is_in_sha1_set(inc_sha1_mi, reachable_set, reachable_count) == 0:
|
||||
continue
|
||||
# 检查 .obj 是否已存在于 includes.binary(切片子目录)
|
||||
ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir)
|
||||
check_pat_mi: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi, inc_sha1_mi, "obj")
|
||||
check_fd_mi: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
obj_exists_mi: int = 0
|
||||
if check_pat_mi is not None and check_fd_mi is not None:
|
||||
string.memset(check_fd_mi, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())
|
||||
check_h_mi: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(check_pat_mi, check_fd_mi)
|
||||
if check_h_mi != w32.win32base.INVALID_HANDLE_VALUE:
|
||||
w32.win32file.FindClose(check_h_mi)
|
||||
obj_exists_mi = 1
|
||||
if obj_exists_mi != 0:
|
||||
if check_pat_mi is not None:
|
||||
stdlib.free(check_pat_mi)
|
||||
stdlib.free(check_fd_mi)
|
||||
continue
|
||||
|
||||
# .obj 不存在,需要编译
|
||||
# 构造源文件路径: {includes_dir}/{rel_path}
|
||||
rel_path_len_mi: t.CSizeT = string.strlen(inc_rel_mi)
|
||||
inc_dir_len_mi: t.CSizeT = string.strlen(includes_dir)
|
||||
src_fp_mi: bytes = stdlib.malloc(inc_dir_len_mi + 1 + rel_path_len_mi + 1)
|
||||
if src_fp_mi is None:
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
continue
|
||||
viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1,
|
||||
"%s/%s", includes_dir, inc_rel_mi)
|
||||
|
||||
# 检查是否为声明文件(只有 declare 没有实质 define)
|
||||
# 判断方法: text.ll 中若有混淆函数 define(含 @")则为实现文件
|
||||
is_decl_mi: int = -1
|
||||
tpath_mi: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
|
||||
if tpath_mi is not None:
|
||||
tf_mi: fileio.File | t.CPtr = fileio.File(tpath_mi, fileio.MODE.R)
|
||||
if not tf_mi.closed:
|
||||
is_decl_mi = 1
|
||||
tbuf_mi: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
|
||||
if tbuf_mi is not None:
|
||||
tbr_mi: t.CInt64T = tf_mi.read_all(tbuf_mi, StubMerger.STUB_READ_BUF_SIZE)
|
||||
if tbr_mi > 0:
|
||||
if tbr_mi < StubMerger.STUB_READ_BUF_SIZE:
|
||||
tbuf_mi[tbr_mi] = '\0'
|
||||
else:
|
||||
tbuf_mi[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0'
|
||||
# 逐行扫描: 找 define 行中含 @" 的(混淆函数名)
|
||||
tpos_mi: t.CSizeT = 0
|
||||
while tpos_mi < tbr_mi:
|
||||
tls_mi: t.CSizeT = tpos_mi
|
||||
while tpos_mi < tbr_mi:
|
||||
if tbuf_mi[tpos_mi] == '\n':
|
||||
break
|
||||
tpos_mi += 1
|
||||
tll_mi: t.CSizeT = tpos_mi - tls_mi
|
||||
if tpos_mi < tbr_mi:
|
||||
tpos_mi += 1
|
||||
if tll_mi >= 7 and string.strncmp(tbuf_mi + tls_mi, "define ", 7) == 0:
|
||||
# 临时在行尾加 \0 供 strstr 使用
|
||||
# 仅当行尾不在缓冲区末尾时才需保存/恢复
|
||||
# (缓冲区末尾已在上方 read_all 后截断为 '\0',直接用即可)
|
||||
# 避免 tls_mi + tll_mi == tbr_mi 时越界写
|
||||
end_pos_mi: t.CSizeT = tls_mi + tll_mi
|
||||
saved_mi: t.CChar = '\0'
|
||||
need_restore_mi: int = 0
|
||||
if end_pos_mi < tbr_mi:
|
||||
saved_mi = tbuf_mi[end_pos_mi]
|
||||
tbuf_mi[end_pos_mi] = '\0'
|
||||
need_restore_mi = 1
|
||||
if string.strstr(tbuf_mi + tls_mi, "@\"") is not None:
|
||||
if need_restore_mi != 0:
|
||||
tbuf_mi[end_pos_mi] = saved_mi
|
||||
is_decl_mi = 0
|
||||
break
|
||||
if need_restore_mi != 0:
|
||||
tbuf_mi[end_pos_mi] = saved_mi
|
||||
stdlib.free(tbuf_mi)
|
||||
tf_mi.close()
|
||||
stdlib.free(tpath_mi)
|
||||
# is_decl_mi == -1: text.ll 不存在(Phase1 未翻译此文件)
|
||||
# is_decl_mi == 1: 声明文件(仅 declare 无 define)
|
||||
# is_decl_mi == 0: 实现文件(有 define)
|
||||
# 只跳过声明文件(is_decl_mi == 1);text.ll 不存在时继续,让后续翻译逻辑处理
|
||||
if is_decl_mi == 1:
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
stdlib.free(src_fp_mi)
|
||||
continue
|
||||
|
||||
# 尝试 BuildCombinedIR(stub/text 应已由 Phase1 生成)
|
||||
inc_combined_mi: bytes = stdlib.malloc(COMBINED_IR_SIZE)
|
||||
inc_combined_len_mi: t.CSizeT = 0
|
||||
if inc_combined_mi is not None:
|
||||
inc_combined_len_mi = StubMerger.BuildCombinedIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE)
|
||||
|
||||
# 如果 stub/text 不存在,翻译源文件并保存 stub + text,然后重试
|
||||
if inc_combined_len_mi == 0 and inc_combined_mi is not None:
|
||||
# 计算 includes 文件的包名(相对 includes_dir 的目录部分)
|
||||
inc_pkg_mi: str = None
|
||||
if string.strlen(src_fp_mi) > inc_dir_len_mi + 1:
|
||||
inc_rel_mi2: str = src_fp_mi + inc_dir_len_mi + 1
|
||||
inc_pkg_mi = HandlesImports.compute_package_from_relpath(mb, inc_rel_mi2)
|
||||
tr_mi: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, src_fp_mi, inc_sha1_mi, inc_pkg_mi)
|
||||
if tr_mi is not None:
|
||||
PBP_IR_SIZE: t.CSizeT = 1048576
|
||||
# 保存 stub.ll (切片路径)
|
||||
inc_stub_buf: bytes = stdlib.malloc(PBP_IR_SIZE)
|
||||
if inc_stub_buf is not None:
|
||||
tr_mi.dump_ir(inc_stub_buf, PBP_IR_SIZE, llvmlite.OUTPUT_STUB)
|
||||
inc_stub_len: t.CSizeT = string.strlen(inc_stub_buf)
|
||||
inc_stub_path: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll")
|
||||
if inc_stub_path is not None:
|
||||
isf: fileio.File | t.CPtr = fileio.File(inc_stub_path, fileio.MODE.W)
|
||||
if not isf.closed:
|
||||
isf.write(inc_stub_buf, inc_stub_len)
|
||||
isf.close()
|
||||
stdlib.free(inc_stub_path)
|
||||
stdlib.free(inc_stub_buf)
|
||||
# 保存 text.ll (切片路径)
|
||||
inc_text_buf: bytes = stdlib.malloc(PBP_IR_SIZE)
|
||||
if inc_text_buf is not None:
|
||||
tr_mi.dump_ir(inc_text_buf, PBP_IR_SIZE, llvmlite.OUTPUT_TEXT)
|
||||
inc_text_len: t.CSizeT = string.strlen(inc_text_buf)
|
||||
inc_text_path: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
|
||||
if inc_text_path is not None:
|
||||
itf: fileio.File | t.CPtr = fileio.File(inc_text_path, fileio.MODE.W)
|
||||
if not itf.closed:
|
||||
itf.write(inc_text_buf, inc_text_len)
|
||||
itf.close()
|
||||
stdlib.free(inc_text_path)
|
||||
stdlib.free(inc_text_buf)
|
||||
# 重试 BuildCombinedIR
|
||||
inc_combined_len_mi = StubMerger.BuildCombinedIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE)
|
||||
|
||||
if inc_combined_len_mi == 0:
|
||||
# 诊断:检查 stub.ll/text.ll 是否存在
|
||||
diag_stub: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll")
|
||||
diag_text: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
|
||||
diag_stub_ex: int = 0
|
||||
diag_text_ex: int = 0
|
||||
if diag_stub is not None:
|
||||
df_diag_s: fileio.File | t.CPtr = fileio.File(diag_stub, fileio.MODE.R)
|
||||
if not df_diag_s.closed:
|
||||
diag_stub_ex = 1
|
||||
df_diag_s.close()
|
||||
stdlib.free(diag_stub)
|
||||
if diag_text is not None:
|
||||
df_diag_t: fileio.File | t.CPtr = fileio.File(diag_text, fileio.MODE.R)
|
||||
if not df_diag_t.closed:
|
||||
diag_text_ex = 1
|
||||
df_diag_t.close()
|
||||
stdlib.free(diag_text)
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024,
|
||||
"BuildCombinedIR 失败: %s (stub=%d text=%d is_decl=%d)",
|
||||
src_fp_mi, diag_stub_ex, diag_text_ex, is_decl_mi)
|
||||
VLogger.error(fb, "PhaseB+")
|
||||
if inc_combined_mi is not None:
|
||||
stdlib.free(inc_combined_mi)
|
||||
stdlib.free(check_pat_mi)
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
stdlib.free(src_fp_mi)
|
||||
continue
|
||||
|
||||
# 编译为 .obj(输出到 includes_binary_dir,与存在性检查和链接收集一致)
|
||||
inc_cret_mi: int = BuildPipeline.compile_module_to_obj(
|
||||
inc_combined_mi, inc_combined_len_mi, temp_dir, includes_binary_dir, inc_sha1_mi,
|
||||
cc_cmd, cc_flags)
|
||||
stdlib.free(inc_combined_mi)
|
||||
|
||||
if inc_cret_mi != 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", src_fp_mi)
|
||||
VLogger.error(fb, "PhaseB+")
|
||||
sys.exit(1)
|
||||
|
||||
inc_compiled += 1
|
||||
# 显示编译完成的 includes 文件
|
||||
fb_inc_comp: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb_inc_comp is not None:
|
||||
viperlib.snprintf(fb_inc_comp, 1024, "[includes %d] 编译完成: %s", inc_compiled, src_fp_mi)
|
||||
VLogger.info(fb_inc_comp, "PhaseB+")
|
||||
|
||||
# 添加到 obj_paths (切片路径,从 includes_binary_dir 取)
|
||||
ibd_len_mi2: t.CSizeT = string.strlen(includes_binary_dir)
|
||||
inc_obj_sliced: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi2, inc_sha1_mi, "obj")
|
||||
|
||||
if inc_obj_sliced is not None:
|
||||
inc_obj_len: t.CSizeT = string.strlen(inc_obj_sliced)
|
||||
if obj_pos + inc_obj_len + 2 < OBJ_PATHS_SIZE:
|
||||
if obj_pos > 0:
|
||||
obj_paths[obj_pos] = ' '
|
||||
obj_pos += 1
|
||||
string.strcpy(obj_paths + obj_pos, inc_obj_sliced)
|
||||
obj_pos += inc_obj_len
|
||||
obj_paths[obj_pos] = '\0'
|
||||
stdlib.free(inc_obj_sliced)
|
||||
|
||||
# 释放本次迭代的临时内存
|
||||
if check_pat_mi is not None:
|
||||
stdlib.free(check_pat_mi)
|
||||
|
||||
if check_fd_mi is not None:
|
||||
stdlib.free(check_fd_mi)
|
||||
|
||||
stdlib.free(src_fp_mi)
|
||||
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "编译缺失 includes: %d 个", inc_compiled)
|
||||
VLogger.info(fb, "PhaseB+")
|
||||
|
||||
# 释放 app_deps_buf(Phase B+ 块未执行时此处兜底释放)
|
||||
if app_deps_buf is not None:
|
||||
stdlib.free(app_deps_buf)
|
||||
app_deps_buf = None
|
||||
|
||||
# === 4. Phase C: 链接所有 .obj → .exe ===
|
||||
if log is not None:
|
||||
log.banner("Phase C: 链接")
|
||||
|
||||
od_len2: t.CSizeT = string.strlen(output_dir)
|
||||
lo_len: t.CSizeT = string.strlen(linker_output)
|
||||
exe_path: bytes = stdlib.malloc(od_len2 + lo_len + 2)
|
||||
if exe_path is not None:
|
||||
viperlib.snprintf(exe_path, od_len2 + lo_len + 2, "%s/%s", output_dir, linker_output)
|
||||
else:
|
||||
exe_path = linker_output
|
||||
|
||||
# 构造最终 .obj 路径列表:main_obj_path 在前,其他 .obj 在后
|
||||
final_obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE + 512)
|
||||
if final_obj_paths is None:
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
final_obj_paths[0] = '\0'
|
||||
fop_pos: t.CSizeT = 0
|
||||
# main_obj_path 放在最前面(确保 --allow-multiple-definition 选择用户 main)
|
||||
if main_obj_path[0] != '\0':
|
||||
mlen: t.CSizeT = string.strlen(main_obj_path)
|
||||
string.strcpy(final_obj_paths, main_obj_path)
|
||||
fop_pos = mlen
|
||||
if obj_paths[0] != '\0':
|
||||
final_obj_paths[fop_pos] = ' '
|
||||
fop_pos += 1
|
||||
# 追加其他 .obj
|
||||
if obj_paths[0] != '\0':
|
||||
string.strcpy(final_obj_paths + fop_pos, obj_paths)
|
||||
fop_pos += string.strlen(obj_paths)
|
||||
final_obj_paths[fop_pos] = '\0'
|
||||
|
||||
obj_paths_len: t.CSizeT = fop_pos
|
||||
|
||||
# 暂时禁用按图链接:始终全量链接 includes.binary 中的 .obj
|
||||
# 按图链接在 --clean 后 deps.txt 缺失时无法正确工作(跨包传递依赖丢失)
|
||||
# 按图编译(Phase B+)仍保留:只编译 reachable_set 中的缺失 includes
|
||||
# TODO: 待 deps.txt 生成机制完善后(如 Phase A 翻译所有 includes 的 imports),重新启用按图链接
|
||||
|
||||
# 释放 reachable_set(Phase B+ 已使用完毕)
|
||||
if reachable_set is not None:
|
||||
stdlib.free(reachable_set)
|
||||
reachable_set = None
|
||||
|
||||
# 始终传 includes_binary_dir 给 link_objs_to_exe,由其全量收集 .obj
|
||||
lret: int = BuildPipeline.link_objs_to_exe(
|
||||
final_obj_paths, obj_paths_len,
|
||||
linker_cmd, linker_flags, exe_path,
|
||||
includes_binary_dir)
|
||||
|
||||
if lret == 0:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "输出: %s", exe_path)
|
||||
VLogger.success(fb, "PhaseC")
|
||||
if args.get_bool("run"):
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "执行: %s", exe_path)
|
||||
VLogger.info(fb, "run")
|
||||
rp: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False)
|
||||
if rp is not None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "退出码: %d", rp.returncode)
|
||||
VLogger.info(fb, "run")
|
||||
else:
|
||||
VLogger.error("链接失败", "PhaseC")
|
||||
stdlib.free(entries)
|
||||
return 1
|
||||
|
||||
stdlib.free(entries)
|
||||
return 0
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,291 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import stdlib
|
||||
import memhub
|
||||
import sys
|
||||
import w32.win32console as w32cmd
|
||||
import w32.win32file as w32file
|
||||
import w32.win32base as win32base
|
||||
|
||||
|
||||
# ============================================================
|
||||
# VLogger - 原生日志系统(Windows 控制台彩色输出)
|
||||
#
|
||||
# 输出格式与 TPC (lib/core/VLogger.py) 对齐:
|
||||
# ├ INFO: message
|
||||
# ├ INFO[category]: message
|
||||
# ├ WARN: message
|
||||
# ├ ERROR: message
|
||||
# ├ SUCCESS: message
|
||||
# ├ DEBUG: message
|
||||
# ╠ CRITICAL: message (红底白字,致命错误)
|
||||
# ╠ CRITICAL[category]: message
|
||||
#
|
||||
# 分段着色:前缀符号(├/╠) 用级别色,LEVEL 标签用亮色,消息用默认色
|
||||
# CRITICAL 级别使用 ╠ 前缀和红底白字标签,与 TPC critical 对齐
|
||||
# ============================================================
|
||||
|
||||
# 日志级别
|
||||
class LogLevel(t.CEnum):
|
||||
DEBUG = 0
|
||||
INFO = 1
|
||||
WARNING = 2
|
||||
ERROR = 3
|
||||
SUCCESS = 4
|
||||
CRITICAL = 5
|
||||
|
||||
|
||||
# Win32 控制台前景色属性
|
||||
FOREGROUND_BLUE: t.CDefine = 0x0001
|
||||
FOREGROUND_GREEN: t.CDefine = 0x0002
|
||||
FOREGROUND_RED: t.CDefine = 0x0004
|
||||
FOREGROUND_INTENSITY: t.CDefine = 0x0008
|
||||
FOREGROUND_WHITE: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
FOREGROUND_CYAN: t.CDefine = FOREGROUND_BLUE | FOREGROUND_GREEN
|
||||
FOREGROUND_YELLOW: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN
|
||||
FOREGROUND_MAGENTA: t.CDefine = FOREGROUND_RED | FOREGROUND_BLUE
|
||||
|
||||
# Win32 控制台背景色属性
|
||||
BACKGROUND_RED: t.CDefine = 0x0040
|
||||
BACKGROUND_GREEN: t.CDefine = 0x0020
|
||||
BACKGROUND_BLUE: t.CDefine = 0x0010
|
||||
BACKGROUND_INTENSITY: t.CDefine = 0x0080
|
||||
BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
|
||||
|
||||
|
||||
@t.NoVTable
|
||||
class Logger:
|
||||
_level: int
|
||||
_console_handle: win32base.HANDLE
|
||||
_use_color: int
|
||||
__mbuddy__: memhub.MemBuddy | t.CPtr
|
||||
|
||||
def __init__(self, level: int = 1):
|
||||
self._level = level
|
||||
self._console_handle = w32file.GetStdHandle(w32file.STD_OUTPUT_HANDLE)
|
||||
self._use_color = 1
|
||||
self.__mbuddy__ = _mbuddy
|
||||
|
||||
def _set_color(self, attr: WORD) -> int:
|
||||
uc: int = self._use_color
|
||||
if uc:
|
||||
ch: win32base.HANDLE = self._console_handle
|
||||
ret: int = w32cmd.SetConsoleTextAttribute(ch, attr)
|
||||
return ret
|
||||
return 0
|
||||
|
||||
def _reset_color(self) -> int:
|
||||
if self._use_color:
|
||||
return w32cmd.SetConsoleTextAttribute(self._console_handle, FOREGROUND_WHITE)
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# _log - 核心日志输出(分段着色)
|
||||
#
|
||||
# 格式: ├ LEVEL: msg 或 ├ LEVEL[category]: msg
|
||||
# 分三段着色:
|
||||
# 1. 前缀符号 ├ (sym_color)
|
||||
# 2. LEVEL 标签 (level_color)
|
||||
# 3. 消息内容 (默认白色)
|
||||
# ============================================================
|
||||
def _log(self, level: int, prefix_sym: str, level_str: str, msg: str,
|
||||
sym_color: WORD, level_color: WORD,
|
||||
category: str = "") -> int:
|
||||
# 前缀符号着色
|
||||
self._set_color(sym_color)
|
||||
stdio.printf("%s ", prefix_sym)
|
||||
# LEVEL 标签着色
|
||||
self._set_color(level_color)
|
||||
stdio.printf("%s", level_str)
|
||||
self._reset_color()
|
||||
# category 可选
|
||||
if category is not None and category[0] != 0:
|
||||
stdio.printf(" [%s]", category)
|
||||
stdio.printf(": %s\n", msg)
|
||||
return 0
|
||||
|
||||
def debug(self, msg: str, category: str = "") -> int:
|
||||
return self._log(LogLevel.DEBUG, "├", "DEBUG", msg,
|
||||
FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)
|
||||
|
||||
def info(self, msg: str, category: str = "") -> int:
|
||||
ret: int = self._log(LogLevel.INFO, "├", "INFO", msg,
|
||||
FOREGROUND_GREEN,
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
|
||||
return ret
|
||||
|
||||
def warning(self, msg: str, category: str = "") -> int:
|
||||
return self._log(LogLevel.WARNING, "├", "WARN", msg,
|
||||
FOREGROUND_YELLOW,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
category)
|
||||
|
||||
def error(self, msg: str, category: str = "") -> int:
|
||||
ret: int = self._log(LogLevel.ERROR, "├", "ERROR", msg,
|
||||
FOREGROUND_RED,
|
||||
FOREGROUND_RED | FOREGROUND_INTENSITY, category)
|
||||
# 错误立即终止进程(避免错误后继续执行导致连锁崩溃)
|
||||
sys.exit(1)
|
||||
return ret
|
||||
|
||||
def success(self, msg: str, category: str = "") -> int:
|
||||
return self._log(LogLevel.SUCCESS, "├", "SUCCESS", msg,
|
||||
FOREGROUND_GREEN,
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
|
||||
|
||||
def critical(self, msg: str, category: str = "") -> int:
|
||||
# CRITICAL 使用 ╠ 前缀(红底白字标签,对齐 TPC critical 风格)
|
||||
return self._log(LogLevel.CRITICAL, "╠", "CRITICAL", msg,
|
||||
FOREGROUND_RED,
|
||||
BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY,
|
||||
category)
|
||||
|
||||
def set_level(self, level: int) -> int:
|
||||
self._level = level
|
||||
return 0
|
||||
|
||||
# ============================================================
|
||||
# 高级日志方法
|
||||
# ============================================================
|
||||
|
||||
def banner(self, msg: str) -> int:
|
||||
"""输出分节标题(蓝色高亮,与 TPC banner 风格对齐)。"""
|
||||
self._set_color(FOREGROUND_BLUE | FOREGROUND_INTENSITY)
|
||||
stdio.printf("\n=== %s ===\n\n", msg)
|
||||
self._reset_color()
|
||||
return 0
|
||||
|
||||
def compile_error(self, msg: str, file: str = "", line: int = 0) -> int:
|
||||
"""格式化编译错误输出(红底白字标题 + 位置 + 错误信息)。"""
|
||||
self._set_color(BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY)
|
||||
stdio.printf(" 编译错误 ")
|
||||
self._set_color(FOREGROUND_RED | FOREGROUND_INTENSITY)
|
||||
stdio.printf("\n")
|
||||
if file is not None:
|
||||
if file[0] != 0 and line > 0:
|
||||
stdio.printf(" 位置: %s:%d\n", file, line)
|
||||
elif file[0] != 0:
|
||||
stdio.printf(" 文件: %s\n", file)
|
||||
stdio.printf(" 错误: %s\n", msg)
|
||||
self._reset_color()
|
||||
return 0
|
||||
|
||||
def compile_warning(self, msg: str, file: str = "", line: int = 0) -> int:
|
||||
"""格式化编译警告输出(黄底黑字标题 + 位置 + 警告信息)。"""
|
||||
self._set_color(BACKGROUND_RED | BACKGROUND_GREEN | FOREGROUND_INTENSITY)
|
||||
stdio.printf(" 编译警告 ")
|
||||
self._set_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY)
|
||||
stdio.printf("\n")
|
||||
if file is not None:
|
||||
if file[0] != 0 and line > 0:
|
||||
stdio.printf(" 位置: %s:%d\n", file, line)
|
||||
elif file[0] != 0:
|
||||
stdio.printf(" 文件: %s\n", file)
|
||||
stdio.printf(" 警告: %s\n", msg)
|
||||
self._reset_color()
|
||||
return 0
|
||||
|
||||
|
||||
# 全局 mbuddy 指针(由 lib.InitLib 注入)
|
||||
_mbuddy: memhub.MemBuddy | t.CPtr
|
||||
|
||||
# 全局 logger 指针
|
||||
_g_logger: Logger | t.CPtr
|
||||
|
||||
# 全局格式化缓冲区(用于带变量的日志消息,1024 字节)
|
||||
_fmt_buf: t.CChar | t.CPtr
|
||||
|
||||
|
||||
def fmt_buf() -> t.CChar | t.CPtr:
|
||||
"""获取全局格式化缓冲区(1024 字节)。
|
||||
|
||||
用法:
|
||||
buf: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if buf is not None:
|
||||
viperlib.snprintf(buf, 1024, "翻译: %s (sha1=%s)", rp, sha1)
|
||||
log.info(buf, "Phase1")
|
||||
"""
|
||||
global _fmt_buf
|
||||
if _fmt_buf is None:
|
||||
_fmt_buf = stdlib.malloc(1024)
|
||||
return _fmt_buf
|
||||
|
||||
|
||||
def get_logger() -> Logger | t.CPtr:
|
||||
"""获取全局 logger 实例。若不存在则通过 _mbuddy 分配并初始化。"""
|
||||
global _g_logger
|
||||
if _g_logger is None:
|
||||
if _mbuddy is None:
|
||||
return None
|
||||
raw: t.CVoid | t.CPtr = _mbuddy.alloc(Logger.__sizeof__())
|
||||
if raw is None:
|
||||
return None
|
||||
_g_logger = raw
|
||||
_g_logger.__before_init__()
|
||||
_g_logger.__init__(LogLevel.INFO)
|
||||
return _g_logger
|
||||
|
||||
|
||||
def set_logger(logger: Logger | t.CPtr) -> int:
|
||||
"""设置全局 logger 实例。"""
|
||||
global _g_logger
|
||||
_g_logger = logger
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 模块级便捷函数(与 TPC 的 lib.core.VLogger 对齐)
|
||||
#
|
||||
# 调用方式: VLogger.info("msg", "category")
|
||||
# 无需先 get_logger(),方便各模块直接使用
|
||||
# ============================================================
|
||||
|
||||
def info(msg: str, category: str = "") -> int:
|
||||
"""输出 INFO 级别日志。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.info(msg, category)
|
||||
return 0
|
||||
|
||||
|
||||
def warning(msg: str, category: str = "") -> int:
|
||||
"""输出 WARN 级别日志。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.warning(msg, category)
|
||||
return 0
|
||||
|
||||
|
||||
def error(msg: str, category: str = "") -> int:
|
||||
"""输出 ERROR 级别日志并立即终止进程。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.error(msg, category)
|
||||
# logger 不可用时也直接退出
|
||||
sys.exit(1)
|
||||
return 0
|
||||
|
||||
|
||||
def success(msg: str, category: str = "") -> int:
|
||||
"""输出 SUCCESS 级别日志。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.success(msg, category)
|
||||
return 0
|
||||
|
||||
|
||||
def critical(msg: str, category: str = "") -> int:
|
||||
"""输出 CRITICAL 级别日志(致命错误,红底白字)。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.critical(msg, category)
|
||||
return 0
|
||||
|
||||
|
||||
def debug(msg: str, category: str = "") -> int:
|
||||
"""输出 DEBUG 级别日志。"""
|
||||
log: Logger | t.CPtr = get_logger()
|
||||
if log is not None:
|
||||
return log.debug(msg, category)
|
||||
return 0
|
||||
@@ -1,9 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
|
||||
# ============================================================
|
||||
# core 包入口
|
||||
#
|
||||
# 子模块通过绝对导入使用(import lib.core.X as X),
|
||||
# 此 __init__.py 不做 re-export,避免引入未使用的依赖。
|
||||
# ============================================================
|
||||
@@ -1,560 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
import stdlib
|
||||
import memhub
|
||||
import argparse
|
||||
import w32.win32console as w32cmd
|
||||
import w32.fileio as fileio
|
||||
import w32.win32file
|
||||
import w32.win32base
|
||||
import sys
|
||||
import ast
|
||||
import lib
|
||||
import lib.core.VLogger as VLogger
|
||||
import lib.core.Handles.HandlesTranslator as HandlesTranslator
|
||||
import lib.core.Handles.HandlesStruct as HandlesStruct
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesType as HandlesType
|
||||
import lib.core.BuildPipeline as BuildPipeline
|
||||
import lib.core.IncludesScanner as IncludesScanner
|
||||
import lib.core.StubMerger as StubMerger
|
||||
import lib.core.Phase1 as Phase1
|
||||
import lib.core.Phase2 as Phase2
|
||||
import lib.Projectrans.Config as Config
|
||||
import lib.Projectrans.Utils as Utils
|
||||
import llvmlite
|
||||
import subprocess
|
||||
import viperlib
|
||||
import hashlib
|
||||
|
||||
|
||||
# 内存大小: fl_bytes=264 (33*8), POOL_SIZE-fl_bytes 必须是 2 的幂以避免浪费
|
||||
# 1073742088 - 264 = 1073741824 (1024MB usable = 2^30)
|
||||
# 注意: POOL_SIZE 必须是 2^30+264=1073742088,否则 _largest_pow2_le 会取 2^29=512MB
|
||||
# Phase1 翻译 87 个 includes 文件 + Phase2 翻译 30 个测试文件,512MB 不足导致 Phase2 崩溃
|
||||
POOL_SIZE: t.CDefine = 1073742088
|
||||
# 语言编码页
|
||||
CODE_PAGE: t.CDefine = 65001
|
||||
# 源代码缓冲区大小(1MB)
|
||||
SRC_BUF_SIZE: t.CDefine = 1048576
|
||||
|
||||
|
||||
# ============================================================
|
||||
# main: 命令行入口
|
||||
#
|
||||
# 解析参数 → 加载配置 → AST 解析 → LLVM IR 翻译 → 编译管线 → 可选执行
|
||||
# ============================================================
|
||||
def main() -> int:
|
||||
w32cmd.SetConsoleOutputCP(CODE_PAGE)
|
||||
w32cmd.SetConsoleCP(CODE_PAGE)
|
||||
# 初始化 mbuddy 内存池
|
||||
arena: bytes = stdlib.malloc(POOL_SIZE)
|
||||
if arena is None:
|
||||
stdio.printf("FAIL: malloc for arena failed\n")
|
||||
return 1
|
||||
mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE)
|
||||
if mb is None:
|
||||
stdio.printf("FAIL: MemBuddy init failed\n")
|
||||
return 1
|
||||
|
||||
# 设置全局 mbuddy 指针(sys 和 argparse 都需要)
|
||||
sys._mbuddy = mb
|
||||
argparse._mbuddy = mb
|
||||
ast._mbuddy = mb
|
||||
lib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
Config._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
Utils._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
HandlesTranslator._mbuddy = mb
|
||||
BuildPipeline._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
IncludesScanner._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
StubMerger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
Phase1._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
Phase2._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
subprocess._mbuddy = mb
|
||||
hashlib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
VLogger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb)
|
||||
lib.InitLib((memhub.MemBuddy | t.CPtr)(mb))
|
||||
|
||||
# 初始化 VLogger 并打印启动日志
|
||||
log: VLogger.Logger | t.CPtr = VLogger.get_logger()
|
||||
if log is not None:
|
||||
log.info("TransPyV 启动")
|
||||
|
||||
# 初始化命令行参数(Windows: GetCommandLineA, POSIX: /proc/self/cmdline)
|
||||
sys._init_argv()
|
||||
|
||||
# 创建参数解析器
|
||||
parser: argparse.ArgumentParser | t.CPtr = argparse.ArgumentParser(
|
||||
"TransPyV", "TransPyV 命令行参数解析", pool=mb)
|
||||
|
||||
# 注册参数(与 Projectrans.py main() 一致)
|
||||
parser.add_argument("--project", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "project.json 路径(默认查找当前目录)")
|
||||
parser.add_argument("--src", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "源文件目录(覆盖 project.json)")
|
||||
parser.add_argument("--temp", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "声明接口临时目录(覆盖 project.json)")
|
||||
parser.add_argument("--output", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "输出目录(覆盖 project.json)")
|
||||
parser.add_argument("--phase", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "阶段: 1=生成声明, 2=翻译+编译, all=全部")
|
||||
parser.add_argument("--cc", None, argparse.STRING, 0, None, False,
|
||||
argparse.STORE, "LLVM 编译器命令(覆盖 project.json)")
|
||||
parser.add_argument("--clean", None, argparse.BOOL, 0, None, False,
|
||||
argparse.STORE_TRUE, "清理 output 和 temp 目录")
|
||||
parser.add_argument("--run", None, argparse.BOOL, 0, None, False,
|
||||
argparse.STORE_TRUE, "编译成功后立即执行生成的可执行文件")
|
||||
parser.add_argument("--rebuild-includes", None, argparse.BOOL, 0, None, False,
|
||||
argparse.STORE_TRUE, "删除 includes.binary 预编译缓存并重新编译所有 includes")
|
||||
parser.add_argument("--clear-cache", None, argparse.BOOL, 0, None, False,
|
||||
argparse.STORE_TRUE, "清除 .transpyc_cache 全局缓存")
|
||||
|
||||
# 解析命令行参数
|
||||
args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv)
|
||||
if args is None:
|
||||
if log is not None:
|
||||
log.error("参数解析失败", "argparse")
|
||||
return 1
|
||||
|
||||
# 打印解析结果
|
||||
if log is not None:
|
||||
log.banner("TransPyV 参数解析结果")
|
||||
|
||||
# 字符串参数
|
||||
project: str = args.get_str("project")
|
||||
if project is not None:
|
||||
stdio.printf(" --project: %s\n", project)
|
||||
else:
|
||||
stdio.printf(" --project: (未指定)\n")
|
||||
|
||||
src: str = args.get_str("src")
|
||||
if src is not None:
|
||||
stdio.printf(" --src: %s\n", src)
|
||||
else:
|
||||
stdio.printf(" --src: (未指定)\n")
|
||||
|
||||
temp: str = args.get_str("temp")
|
||||
if temp is not None:
|
||||
stdio.printf(" --temp: %s\n", temp)
|
||||
else:
|
||||
stdio.printf(" --temp: (未指定)\n")
|
||||
|
||||
output: str = args.get_str("output")
|
||||
if output is not None:
|
||||
stdio.printf(" --output: %s\n", output)
|
||||
else:
|
||||
stdio.printf(" --output: (未指定)\n")
|
||||
|
||||
phase: str = args.get_str("phase")
|
||||
if phase is not None:
|
||||
stdio.printf(" --phase: %s\n", phase)
|
||||
else:
|
||||
stdio.printf(" --phase: (未指定,默认 all)\n")
|
||||
|
||||
cc: str = args.get_str("cc")
|
||||
if cc is not None:
|
||||
stdio.printf(" --cc: %s\n", cc)
|
||||
else:
|
||||
stdio.printf(" --cc: (未指定)\n")
|
||||
|
||||
# 布尔参数
|
||||
_gb_clean: INT = args.get_bool("clean")
|
||||
if _gb_clean:
|
||||
stdio.printf(" --clean: True\n")
|
||||
else:
|
||||
stdio.printf(" --clean: False\n")
|
||||
|
||||
if args.get_bool("run"):
|
||||
stdio.printf(" --run: True\n")
|
||||
else:
|
||||
stdio.printf(" --run: False\n")
|
||||
|
||||
if args.get_bool("rebuild-includes"):
|
||||
stdio.printf(" --rebuild-includes: True\n")
|
||||
else:
|
||||
stdio.printf(" --rebuild-includes: False\n")
|
||||
|
||||
if args.get_bool("clear-cache"):
|
||||
stdio.printf(" --clear-cache: True\n")
|
||||
else:
|
||||
stdio.printf(" --clear-cache: False\n")
|
||||
|
||||
stdio.printf("\n参数解析完成。\n")
|
||||
|
||||
# 加载 project.vpj 配置
|
||||
proj_loaded: int = 0
|
||||
proj_path: str = project
|
||||
if proj_path is not None:
|
||||
if log is not None:
|
||||
log.banner("工程配置")
|
||||
cfg_ret: int = Config.Load_project_config(proj_path)
|
||||
if cfg_ret == 0:
|
||||
proj_loaded = 1
|
||||
else:
|
||||
if log is not None:
|
||||
warn_buf: str = stdlib.malloc(256)
|
||||
if warn_buf is not None:
|
||||
viperlib.snprintf(warn_buf, 256, "无法加载 project.vpj: %s", proj_path)
|
||||
log.warning(warn_buf, "config")
|
||||
stdlib.free(warn_buf)
|
||||
else:
|
||||
# 尝试默认路径 project.vpj(当前目录和上级目录)
|
||||
proj_path = "project.vpj"
|
||||
if Config.Load_project_config(proj_path) == 0:
|
||||
proj_loaded = 1
|
||||
else:
|
||||
proj_path = "../project.vpj"
|
||||
if Config.Load_project_config(proj_path) == 0:
|
||||
proj_loaded = 1
|
||||
if proj_loaded == 1:
|
||||
# 提取 project.vpj 所在目录,将相对路径解析为基于该目录的路径
|
||||
proj_len: t.CSizeT = string.strlen(proj_path)
|
||||
slash_pos: t.CSizeT = proj_len
|
||||
for i in range(proj_len):
|
||||
idx: t.CSizeT = proj_len - 1 - i
|
||||
ch: t.CChar = proj_path[idx]
|
||||
if ch == '/' or ch == '\\':
|
||||
slash_pos = idx
|
||||
break
|
||||
proj_dir: str = ""
|
||||
if slash_pos > 0 and slash_pos < proj_len:
|
||||
proj_dir = stdlib.malloc(slash_pos + 1)
|
||||
if proj_dir is not None:
|
||||
string.memcpy(proj_dir, proj_path, slash_pos)
|
||||
proj_dir[slash_pos] = '\0'
|
||||
Config.resolve_paths(proj_dir)
|
||||
Config.print_config()
|
||||
|
||||
# === --clean: 清理 temp 和 output 目录 ===
|
||||
if _gb_clean:
|
||||
if log is not None:
|
||||
log.info("清理临时目录...", "clean")
|
||||
if Config.TempDir is not None:
|
||||
n: int = Utils.CleanDir(Config.TempDir)
|
||||
if log is not None:
|
||||
fb: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb is not None:
|
||||
viperlib.snprintf(fb, 1024, "%s: 删除 %d 个文件", Config.TempDir, n)
|
||||
log.info(fb, "clean")
|
||||
if Config.OutputDir is not None:
|
||||
n2: int = Utils.CleanDir(Config.OutputDir)
|
||||
if log is not None:
|
||||
fb2: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb2 is not None:
|
||||
viperlib.snprintf(fb2, 1024, "%s: 删除 %d 个文件", Config.OutputDir, n2)
|
||||
log.info(fb2, "clean")
|
||||
|
||||
# === --phase 参数控制 ===
|
||||
# phase=1: 仅 stub 分离(生成 .stub.ll/.text.ll),不编译
|
||||
# phase=2: 仅 stub 合并 + 编译(跳过 stub 分离)
|
||||
# phase=all: 两者都执行(默认)
|
||||
phase_mode: str = phase
|
||||
if phase_mode is None:
|
||||
phase_mode = "all"
|
||||
do_phase1: int = 0
|
||||
do_phase2: int = 0
|
||||
# 注意: 使用 string.strcmp 而非 ==,避免编译器 == 语义 bug
|
||||
if string.strcmp(phase_mode, "1") == 0 or string.strcmp(phase_mode, "all") == 0:
|
||||
do_phase1 = 1
|
||||
if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0:
|
||||
do_phase2 = 1
|
||||
if log is not None:
|
||||
fb3: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb3 is not None:
|
||||
viperlib.snprintf(fb3, 1024, "模式: %s (phase1=%d phase2=%d)", phase_mode, do_phase1, do_phase2)
|
||||
log.info(fb3, "phase")
|
||||
|
||||
# === Phase1: 扫描 includes(按需翻译)===
|
||||
# 对 includes 目录中每个 .py 文件,若 stub 不存在则翻译并分离 stub
|
||||
if do_phase1 != 0 and Config.IncludesDir is not None:
|
||||
ph1_temp: str = Config.TempDir
|
||||
if ph1_temp is None:
|
||||
ph1_temp = "."
|
||||
Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log)
|
||||
# 如果仅 Phase1(不执行 Phase2),直接退出
|
||||
if do_phase2 == 0:
|
||||
if log is not None:
|
||||
log.info("Phase1 完成,退出", "phase")
|
||||
return 0
|
||||
|
||||
# AST 解析:如果指定了 --src 或 --project,读取文件并解析为 AST 树
|
||||
src_path: str = args.get_str("src")
|
||||
|
||||
# === 多文件项目模式 ===
|
||||
# 当 --project 指定但 --src 未指定时,扫描 source_dir 下所有 .py 文件编译
|
||||
if src_path is None and project is not None and Config.SourceDir is not None:
|
||||
mf_temp: str = Config.TempDir if Config.TempDir is not None else "."
|
||||
mf_output: str = Config.OutputDir if Config.OutputDir is not None else "."
|
||||
mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc"
|
||||
mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic"
|
||||
mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++"
|
||||
mf_linker_flags: str = Config.LinkerFlags if Config.LinkerFlags is not None else "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition"
|
||||
mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe"
|
||||
mf_includes_bin: str = Config.get_includes_binary_dir()
|
||||
|
||||
mf_ret: int = Phase2.RunMultiFileProject(
|
||||
mb, Config.SourceDir, mf_temp, mf_output,
|
||||
mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out,
|
||||
mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args)
|
||||
argparse.release(args)
|
||||
if log is not None:
|
||||
log.success("TransPyV 完成")
|
||||
return mf_ret
|
||||
|
||||
# === 单文件模式:--src 指定时使用指定文件;--project 但无 SourceDir 时回退 ===
|
||||
if src_path is None and project is not None:
|
||||
if Config.SourceDir is not None:
|
||||
# 构造入口路径: SourceDir/main.py
|
||||
sd_len: t.CSizeT = string.strlen(Config.SourceDir)
|
||||
path_buf: bytes = stdlib.malloc(sd_len + 16)
|
||||
if path_buf is not None:
|
||||
viperlib.snprintf(path_buf, sd_len + 16, "%s/main.py", Config.SourceDir)
|
||||
src_path = path_buf
|
||||
if log is not None:
|
||||
fb4: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb4 is not None:
|
||||
viperlib.snprintf(fb4, 1024, "入口文件: %s", src_path)
|
||||
log.info(fb4, "project")
|
||||
if src_path is not None:
|
||||
if log is not None:
|
||||
log.banner("AST 解析")
|
||||
# 打开文件
|
||||
f: fileio.File | t.CPtr = fileio.File(src_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
if log is not None:
|
||||
fb5: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb5 is not None:
|
||||
viperlib.snprintf(fb5, 1024, "无法打开文件: %s", src_path)
|
||||
log.error(fb5, "fileio")
|
||||
argparse.release(args)
|
||||
return 1
|
||||
# 分配源代码缓冲区
|
||||
src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE)
|
||||
if src_buf is None:
|
||||
if log is not None:
|
||||
log.error("malloc for src_buf failed", "memhub")
|
||||
f.close()
|
||||
argparse.release(args)
|
||||
return 1
|
||||
# 读取文件内容
|
||||
bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE)
|
||||
f.close()
|
||||
if bytes_read < 0:
|
||||
if log is not None:
|
||||
fb6: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb6 is not None:
|
||||
viperlib.snprintf(fb6, 1024, "读取文件失败 (错误码: %d)", bytes_read)
|
||||
log.error(fb6, "fileio")
|
||||
argparse.release(args)
|
||||
return 1
|
||||
# 添加 null 终止符,确保 strlen 和 SHA1 计算正确
|
||||
if bytes_read < SRC_BUF_SIZE:
|
||||
src_buf[bytes_read] = 0
|
||||
else:
|
||||
src_buf[SRC_BUF_SIZE - 1] = 0
|
||||
if log is not None:
|
||||
log.info("文件读取完成", "fileio")
|
||||
fb7: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb7 is not None:
|
||||
viperlib.snprintf(fb7, 1024, "读取 %d 字节", bytes_read)
|
||||
log.info(fb7, "fileio")
|
||||
# 解析 AST(拆分为词法+语法两阶段,便于调试)
|
||||
ast._init_tables(mb)
|
||||
lx: ast.Lexer | t.CPtr = ast.new_lexer(mb)
|
||||
ast._lexer_init(lx, src_buf, mb)
|
||||
tokens: ast.Token | t.CPtr = ast.tokenize(lx)
|
||||
tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens)
|
||||
if tree is None:
|
||||
if log is not None:
|
||||
log.error("AST 解析失败", "ast")
|
||||
argparse.release(args)
|
||||
return 1
|
||||
|
||||
# === 翻译 AST → LLVM IR ===
|
||||
if log is not None:
|
||||
log.banner("LLVM IR 翻译")
|
||||
tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator()
|
||||
result: int = tr.translate(tree)
|
||||
if result == 0:
|
||||
IR_BUF_SIZE: t.CSizeT = 262144
|
||||
ir_buf: bytes = stdlib.malloc(IR_BUF_SIZE)
|
||||
if ir_buf is not None:
|
||||
tr.dump_ir(ir_buf, IR_BUF_SIZE, llvmlite.OUTPUT_FULL)
|
||||
|
||||
# === 编译管线: .ll → .obj → .exe ===
|
||||
if log is not None:
|
||||
log.banner("编译管线")
|
||||
|
||||
# module_name 用源代码内容的 SHA1(前 16 字符),与 Projectrans.py 一致
|
||||
# output_name 从文件名推导(如 test.py -> test.exe),保持可读性
|
||||
module_name: str = Utils.compute_sha1(mb, src_buf)
|
||||
if module_name is None:
|
||||
module_name = "main"
|
||||
output_name: str = "test_prog.exe"
|
||||
# 从文件名提取 output_name(去掉路径和 .py 扩展名)
|
||||
src_len: t.CSizeT = string.strlen(src_path)
|
||||
if src_len > 0:
|
||||
# 找到最后一个 / 或 \ 之后的部分
|
||||
base_start: t.CSizeT = src_len
|
||||
i: t.CSizeT = src_len
|
||||
while i > 0:
|
||||
i -= 1
|
||||
ch: t.CChar = src_path[i]
|
||||
if ch == '/' or ch == '\\':
|
||||
base_start = i + 1
|
||||
break
|
||||
if i == 0:
|
||||
base_start = 0
|
||||
# 找到 .py 扩展名
|
||||
base_end: t.CSizeT = src_len
|
||||
j: t.CSizeT = base_start
|
||||
while j < src_len:
|
||||
if src_path[j] == '.':
|
||||
base_end = j
|
||||
break
|
||||
j += 1
|
||||
# 输出名 = 文件名 + ".exe"
|
||||
name_len: t.CSizeT = base_end - base_start
|
||||
if name_len > 0:
|
||||
out_len: t.CSizeT = name_len + 5
|
||||
output_name = stdlib.malloc(out_len)
|
||||
if output_name is not None:
|
||||
# 手动复制文件名并追加 .exe(viperlib.snprintf 不支持 %.*s,string 无 strcat)
|
||||
string.strncpy(output_name, src_path + base_start, name_len)
|
||||
output_name[name_len] = '.'
|
||||
output_name[name_len + 1] = 'e'
|
||||
output_name[name_len + 2] = 'x'
|
||||
output_name[name_len + 3] = 'e'
|
||||
output_name[name_len + 4] = '\0'
|
||||
# 使用 project.vpj 中的配置
|
||||
temp_dir: str = Config.TempDir if Config.TempDir is not None else "."
|
||||
output_dir: str = Config.OutputDir if Config.OutputDir is not None else "."
|
||||
# 设置全局 temp_dir(供跨模块 CDefine 查找使用)
|
||||
HandlesType.set_temp_dir(temp_dir)
|
||||
cc_cmd: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc"
|
||||
cc_flags: str = "-filetype=obj -relocation-model=pic"
|
||||
linker_cmd: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++"
|
||||
linker_flags: str = "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition"
|
||||
# --project 模式且未显式指定 --src 时:使用 config 中的 linker_output(如 TransPyV.exe)
|
||||
# 显式指定 --src 时:使用从文件名推导的 output_name(如 test.exe),避免覆盖正在运行的 exe
|
||||
if project is not None and Config.LinkerOutput is not None and args.get_str("src") is None:
|
||||
linker_output: str = Config.LinkerOutput
|
||||
else:
|
||||
linker_output: str = output_name
|
||||
|
||||
# 计算 includes.binary 目录路径(链接时附加预编译 .obj)
|
||||
includes_binary_dir: str = Config.get_includes_binary_dir()
|
||||
|
||||
ir_len: t.CSizeT = string.strlen(ir_buf)
|
||||
|
||||
# (--phase 参数已在配置加载后处理,此处直接使用 do_phase1/do_phase2)
|
||||
|
||||
# === Phase1 stub 分离:使用 OUTPUT_STUB/TEXT 模式分别生成 stub.ll 和 text.ll ===
|
||||
if do_phase1 != 0 and temp_dir is not None and module_name is not None:
|
||||
if log is not None:
|
||||
log.banner("stub 分离")
|
||||
SF_IR_SIZE: t.CSizeT = 262144
|
||||
td_len_sf: t.CSizeT = string.strlen(temp_dir)
|
||||
# 保存 stub.ll
|
||||
sf_stub_buf: bytes = stdlib.malloc(SF_IR_SIZE)
|
||||
if sf_stub_buf is not None:
|
||||
tr.dump_ir(sf_stub_buf, SF_IR_SIZE, llvmlite.OUTPUT_STUB)
|
||||
sf_stub_len: t.CSizeT = string.strlen(sf_stub_buf)
|
||||
sf_stub_path: str = StubMerger._sliced_path(temp_dir, td_len_sf, module_name, "stub.ll")
|
||||
if sf_stub_path is not None:
|
||||
sf_f: fileio.File | t.CPtr = fileio.File(sf_stub_path, fileio.MODE.W)
|
||||
if not sf_f.closed:
|
||||
sf_f.write(sf_stub_buf, sf_stub_len)
|
||||
sf_f.close()
|
||||
stdlib.free(sf_stub_path)
|
||||
stdlib.free(sf_stub_buf)
|
||||
# 保存 text.ll
|
||||
sf_text_buf: bytes = stdlib.malloc(SF_IR_SIZE)
|
||||
if sf_text_buf is not None:
|
||||
tr.dump_ir(sf_text_buf, SF_IR_SIZE, llvmlite.OUTPUT_TEXT)
|
||||
sf_text_len: t.CSizeT = string.strlen(sf_text_buf)
|
||||
sf_text_path: str = StubMerger._sliced_path(temp_dir, td_len_sf, module_name, "text.ll")
|
||||
if sf_text_path is not None:
|
||||
sf_tf: fileio.File | t.CPtr = fileio.File(sf_text_path, fileio.MODE.W)
|
||||
if not sf_tf.closed:
|
||||
sf_tf.write(sf_text_buf, sf_text_len)
|
||||
sf_tf.close()
|
||||
stdlib.free(sf_text_path)
|
||||
stdlib.free(sf_text_buf)
|
||||
|
||||
# phase=1 模式:仅生成 stub,不执行编译
|
||||
if do_phase2 == 0:
|
||||
if log is not None:
|
||||
log.success("Phase1 完成(仅 stub 分离,跳过编译)")
|
||||
argparse.release(args)
|
||||
return 0
|
||||
|
||||
# === Phase2: 组合本地 stub + 依赖 stubs + 本地 text → 完整 IR ===
|
||||
final_ir: bytes = ir_buf
|
||||
final_ir_len: t.CSizeT = ir_len
|
||||
if temp_dir is not None and module_name is not None:
|
||||
if log is not None:
|
||||
log.banner("IR 组合")
|
||||
SF_COMBINED_SIZE: t.CSizeT = 4194304 # 4MB
|
||||
combined_buf: bytes = stdlib.malloc(SF_COMBINED_SIZE)
|
||||
if combined_buf is not None:
|
||||
combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, module_name, combined_buf, SF_COMBINED_SIZE)
|
||||
if combined_len > 0:
|
||||
final_ir = combined_buf
|
||||
final_ir_len = combined_len
|
||||
else:
|
||||
if log is not None:
|
||||
log.warning("BuildCombinedIR 失败,使用原始 IR", "stub")
|
||||
stdlib.free(combined_buf)
|
||||
|
||||
br: BuildPipeline.BuildResult | t.CPtr = BuildPipeline.run_pipeline(
|
||||
final_ir, final_ir_len, temp_dir, output_dir, module_name,
|
||||
cc_cmd, cc_flags, linker_cmd, linker_flags, linker_output,
|
||||
includes_binary_dir
|
||||
)
|
||||
if br is not None and br.Success == 1:
|
||||
if log is not None:
|
||||
log.success("编译管线完成")
|
||||
fb8: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb8 is not None:
|
||||
viperlib.snprintf(fb8, 1024, "输出: %s/%s", output_dir, linker_output)
|
||||
log.info(fb8)
|
||||
# --run 模式:执行生成的可执行文件
|
||||
if args.get_bool("run"):
|
||||
exe_path: bytes = stdlib.malloc(string.strlen(output_dir) + string.strlen(linker_output) + 2)
|
||||
if exe_path is not None:
|
||||
viperlib.snprintf(exe_path, 256, "%s/%s", output_dir, linker_output)
|
||||
if log is not None:
|
||||
fb9: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb9 is not None:
|
||||
viperlib.snprintf(fb9, 1024, "执行: %s", exe_path)
|
||||
log.info(fb9, "run")
|
||||
r: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False)
|
||||
if r is not None:
|
||||
if log is not None:
|
||||
fb10: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb10 is not None:
|
||||
viperlib.snprintf(fb10, 1024, "退出码: %d", r.returncode)
|
||||
log.info(fb10, "run")
|
||||
else:
|
||||
if log is not None:
|
||||
log.error("编译管线失败", "pipeline")
|
||||
if br is not None and br.ErrorMsg is not None:
|
||||
fb11: t.CChar | t.CPtr = VLogger.fmt_buf()
|
||||
if fb11 is not None:
|
||||
viperlib.snprintf(fb11, 1024, "编译管线失败: %s", br.ErrorMsg)
|
||||
log.error(fb11, "FATAL")
|
||||
sys.exit(1)
|
||||
else:
|
||||
if log is not None:
|
||||
log.error("malloc for IR buffer failed", "memhub")
|
||||
else:
|
||||
if log is not None:
|
||||
log.error("翻译失败", "translator")
|
||||
|
||||
argparse.release(args)
|
||||
if log is not None:
|
||||
log.success("TransPyV 完成")
|
||||
return 0
|
||||
@@ -1,47 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# c.Asm 内联汇编测试
|
||||
# ============================================================
|
||||
|
||||
def asm_test() -> int:
|
||||
# 1. 简单无操作数汇编(nop + clobber)
|
||||
c.Asm("nop", op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
stdio.printf("asm: nop ok\n")
|
||||
|
||||
# 2. 仅汇编文本无 clobber
|
||||
c.Asm("nop")
|
||||
stdio.printf("asm: nop2 ok\n")
|
||||
|
||||
# 3. 多 clobber
|
||||
c.Asm("nop", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_CC])
|
||||
stdio.printf("asm: multi-clobber ok\n")
|
||||
|
||||
# 4. 带输入操作数的汇编(读取 CPU ID)
|
||||
# 使用 f-string 内联 c.AsmInp
|
||||
# mov eax, 输入值; nop(保持简单,不使用会产生异常的指令)
|
||||
val: int = 42
|
||||
c.Asm(f"""mov eax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)}
|
||||
nop""", op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
stdio.printf("asm: input ok val=%d\n", val)
|
||||
|
||||
# 5. 带输出操作数的汇编
|
||||
# c.AsmOut 获取结果
|
||||
result: int = 0
|
||||
c.Asm(f"""mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, 123
|
||||
nop""", op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
stdio.printf("asm: output result=%d\n", result)
|
||||
|
||||
# 6. 带输入和输出操作数
|
||||
# result2 = val + 1
|
||||
result2: int = 0
|
||||
input_val: int = 10
|
||||
c.Asm(f"""mov eax, {c.AsmInp(input_val, t.ASM_DESCR.REG_ANY)}
|
||||
add eax, 1
|
||||
mov {c.AsmOut(result2, t.ASM_DESCR.OUTPUT_REG)}, eax
|
||||
nop""", op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
stdio.printf("asm: in+out result2=%d (expect 11)\n", result2)
|
||||
|
||||
return 0
|
||||
@@ -1,234 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# c.Attribute 装饰器测试
|
||||
#
|
||||
# 测试 @c.Attribute(...) 对函数属性的设置:
|
||||
# - t.attr.always_inline() -> alwaysinline
|
||||
# - t.attr.noinline() -> noinline
|
||||
# - t.attr.noreturn() -> noreturn
|
||||
# - t.attr.pure() -> readonly (LLVM 函数属性)
|
||||
# - t.attr.llvm.nounwind -> nounwind
|
||||
# ============================================================
|
||||
|
||||
|
||||
# Test 1: always_inline 属性
|
||||
@c.Attribute(t.attr.always_inline())
|
||||
def AlwaysInlineFunc(x: t.CInt) -> t.CInt:
|
||||
return x * 2
|
||||
|
||||
|
||||
# Test 2: noinline 属性
|
||||
@c.Attribute(t.attr.noinline())
|
||||
def NoInlineFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 100
|
||||
|
||||
|
||||
# Test 3: noreturn 属性(函数确实不返回)
|
||||
@c.Attribute(t.attr.noreturn())
|
||||
def NoReturnFunc() -> t.CInt:
|
||||
stdio.printf("NoReturnFunc called (does not return)\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 4: 普通函数对照(无装饰器)
|
||||
def NormalFunc(x: t.CInt) -> t.CInt:
|
||||
return x * 3
|
||||
|
||||
|
||||
# Test 5: 多属性组合
|
||||
@c.Attribute(t.attr.always_inline(), t.attr.pure())
|
||||
def MultiAttrFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 1
|
||||
|
||||
|
||||
# Test 6: 无括号属性引用 t.attr.packed
|
||||
@c.Attribute(t.attr.packed)
|
||||
def PackedAttrFunc(x: t.CInt) -> t.CInt:
|
||||
return x - 1
|
||||
|
||||
|
||||
def test_always_inline() -> t.CInt:
|
||||
stdio.printf("--- Test 1: c.Attribute(always_inline) ---\n")
|
||||
r: t.CInt = AlwaysInlineFunc(21)
|
||||
stdio.printf("AlwaysInlineFunc(21)=%d (expect 42)\n", r)
|
||||
if r == 42:
|
||||
stdio.printf("AlwaysInlineFunc OK\n")
|
||||
else:
|
||||
stdio.printf("AlwaysInlineFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_noinline() -> t.CInt:
|
||||
stdio.printf("--- Test 2: c.Attribute(noinline) ---\n")
|
||||
r: t.CInt = NoInlineFunc(5)
|
||||
stdio.printf("NoInlineFunc(5)=%d (expect 105)\n", r)
|
||||
if r == 105:
|
||||
stdio.printf("NoInlineFunc OK\n")
|
||||
else:
|
||||
stdio.printf("NoInlineFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_noreturn() -> t.CInt:
|
||||
stdio.printf("--- Test 3: c.Attribute(noreturn) ---\n")
|
||||
stdio.printf("NoReturnFunc declared with noreturn attr\n")
|
||||
stdio.printf("NoReturnFunc OK (not called to avoid UB)\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_normal() -> t.CInt:
|
||||
stdio.printf("--- Test 4: normal function (no attr) ---\n")
|
||||
r: t.CInt = NormalFunc(7)
|
||||
stdio.printf("NormalFunc(7)=%d (expect 21)\n", r)
|
||||
if r == 21:
|
||||
stdio.printf("NormalFunc OK\n")
|
||||
else:
|
||||
stdio.printf("NormalFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_multi_attr() -> t.CInt:
|
||||
stdio.printf("--- Test 5: c.Attribute(always_inline, pure) ---\n")
|
||||
r: t.CInt = MultiAttrFunc(10)
|
||||
stdio.printf("MultiAttrFunc(10)=%d (expect 11)\n", r)
|
||||
if r == 11:
|
||||
stdio.printf("MultiAttrFunc OK\n")
|
||||
else:
|
||||
stdio.printf("MultiAttrFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_packed_attr() -> t.CInt:
|
||||
stdio.printf("--- Test 6: c.Attribute(packed) ---\n")
|
||||
r: t.CInt = PackedAttrFunc(10)
|
||||
stdio.printf("PackedAttrFunc(10)=%d (expect 9)\n", r)
|
||||
if r == 9:
|
||||
stdio.printf("PackedAttrFunc OK\n")
|
||||
else:
|
||||
stdio.printf("PackedAttrFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 7: t.attr.llvm.nounwind 属性
|
||||
@c.Attribute(t.attr.llvm.nounwind)
|
||||
def NoUnwindFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 1
|
||||
|
||||
|
||||
# Test 8: t.attr.llvm.noredzone 属性
|
||||
@c.Attribute(t.attr.llvm.noredzone)
|
||||
def NoRedZoneFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 2
|
||||
|
||||
|
||||
# Test 9: t.attr.llvm.willreturn 属性
|
||||
@c.Attribute(t.attr.llvm.willreturn)
|
||||
def WillReturnFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 3
|
||||
|
||||
|
||||
# Test 10: t.attr.llvm.mustprogress 属性
|
||||
@c.Attribute(t.attr.llvm.mustprogress)
|
||||
def MustProgressFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 4
|
||||
|
||||
|
||||
# Test 11: t.attr.const() -> readnone
|
||||
@c.Attribute(t.attr.const())
|
||||
def ConstFunc(x: t.CInt) -> t.CInt:
|
||||
return x * 0 + 42
|
||||
|
||||
|
||||
# Test 12: 多属性组合(alwaysinline + nounwind + noredzone)
|
||||
@c.Attribute(t.attr.always_inline(), t.attr.llvm.nounwind, t.attr.llvm.noredzone)
|
||||
def TripleAttrFunc(x: t.CInt) -> t.CInt:
|
||||
return x + 5
|
||||
|
||||
|
||||
def test_nounwind() -> t.CInt:
|
||||
stdio.printf("--- Test 7: c.Attribute(llvm.nounwind) ---\n")
|
||||
r: t.CInt = NoUnwindFunc(10)
|
||||
stdio.printf("NoUnwindFunc(10)=%d (expect 11)\n", r)
|
||||
if r == 11:
|
||||
stdio.printf("NoUnwindFunc OK\n")
|
||||
else:
|
||||
stdio.printf("NoUnwindFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_noredzone() -> t.CInt:
|
||||
stdio.printf("--- Test 8: c.Attribute(llvm.noredzone) ---\n")
|
||||
r: t.CInt = NoRedZoneFunc(10)
|
||||
stdio.printf("NoRedZoneFunc(10)=%d (expect 12)\n", r)
|
||||
if r == 12:
|
||||
stdio.printf("NoRedZoneFunc OK\n")
|
||||
else:
|
||||
stdio.printf("NoRedZoneFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_willreturn() -> t.CInt:
|
||||
stdio.printf("--- Test 9: c.Attribute(llvm.willreturn) ---\n")
|
||||
r: t.CInt = WillReturnFunc(10)
|
||||
stdio.printf("WillReturnFunc(10)=%d (expect 13)\n", r)
|
||||
if r == 13:
|
||||
stdio.printf("WillReturnFunc OK\n")
|
||||
else:
|
||||
stdio.printf("WillReturnFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_mustprogress() -> t.CInt:
|
||||
stdio.printf("--- Test 10: c.Attribute(llvm.mustprogress) ---\n")
|
||||
r: t.CInt = MustProgressFunc(10)
|
||||
stdio.printf("MustProgressFunc(10)=%d (expect 14)\n", r)
|
||||
if r == 14:
|
||||
stdio.printf("MustProgressFunc OK\n")
|
||||
else:
|
||||
stdio.printf("MustProgressFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_const_attr() -> t.CInt:
|
||||
stdio.printf("--- Test 11: c.Attribute(const) ---\n")
|
||||
r: t.CInt = ConstFunc(99)
|
||||
stdio.printf("ConstFunc(99)=%d (expect 42)\n", r)
|
||||
if r == 42:
|
||||
stdio.printf("ConstFunc OK\n")
|
||||
else:
|
||||
stdio.printf("ConstFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def test_triple_attr() -> t.CInt:
|
||||
stdio.printf("--- Test 12: c.Attribute(always_inline, nounwind, noredzone) ---\n")
|
||||
r: t.CInt = TripleAttrFunc(10)
|
||||
stdio.printf("TripleAttrFunc(10)=%d (expect 15)\n", r)
|
||||
if r == 15:
|
||||
stdio.printf("TripleAttrFunc OK\n")
|
||||
else:
|
||||
stdio.printf("TripleAttrFunc FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def attr_test() -> t.CInt:
|
||||
stdio.printf("=== attr_test: c.Attribute 装饰器测试 ===\n\n")
|
||||
test_always_inline()
|
||||
test_noinline()
|
||||
test_noreturn()
|
||||
test_normal()
|
||||
test_multi_attr()
|
||||
test_packed_attr()
|
||||
test_nounwind()
|
||||
test_noredzone()
|
||||
test_willreturn()
|
||||
test_mustprogress()
|
||||
test_const_attr()
|
||||
test_triple_attr()
|
||||
stdio.printf("\n=== attr_test 完成 ===\n")
|
||||
return 0
|
||||
@@ -1,58 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# AugAssign 测试:+= -= *= /= %= &= |= ^= <<= >>=
|
||||
# ============================================================
|
||||
|
||||
g_count: int = 0
|
||||
|
||||
|
||||
def test_local() -> int:
|
||||
x: int = 10
|
||||
x += 5
|
||||
stdio.printf("local +=: %d\n", x)
|
||||
x -= 3
|
||||
stdio.printf("local -=: %d\n", x)
|
||||
x *= 2
|
||||
stdio.printf("local *=: %d\n", x)
|
||||
x /= 4
|
||||
stdio.printf("local /=: %d\n", x)
|
||||
x %= 7
|
||||
stdio.printf("local %%=: %d\n", x)
|
||||
return 0
|
||||
|
||||
|
||||
def test_global_aug() -> int:
|
||||
global g_count
|
||||
g_count += 1
|
||||
stdio.printf("global +=: %d\n", g_count)
|
||||
g_count += 10
|
||||
stdio.printf("global +=: %d\n", g_count)
|
||||
g_count -= 3
|
||||
stdio.printf("global -=: %d\n", g_count)
|
||||
return 0
|
||||
|
||||
|
||||
def test_bitops() -> int:
|
||||
b: int = 0xFF
|
||||
b &= 0x0F
|
||||
stdio.printf("bit &=: %d\n", b)
|
||||
b |= 0x30
|
||||
stdio.printf("bit |=: %d\n", b)
|
||||
b ^= 0xFF
|
||||
stdio.printf("bit ^=: %d\n", b)
|
||||
b = 1
|
||||
b <<= 4
|
||||
stdio.printf("bit <<=: %d\n", b)
|
||||
b >>= 2
|
||||
stdio.printf("bit >>=: %d\n", b)
|
||||
return 0
|
||||
|
||||
|
||||
def augassign_test() -> int:
|
||||
test_local()
|
||||
test_global_aug()
|
||||
test_bitops()
|
||||
return 0
|
||||
@@ -1,45 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 闭包 + nonlocal/global 测试
|
||||
# ============================================================
|
||||
|
||||
# 全局变量
|
||||
g_count: int = 0
|
||||
|
||||
|
||||
# global 关键字测试:修改全局变量
|
||||
def test_global() -> int:
|
||||
global g_count
|
||||
g_count = g_count + 1
|
||||
return g_count
|
||||
|
||||
|
||||
# nonlocal 关键字测试:嵌套函数修改外层局部变量
|
||||
def make_counter() -> t.CPtr:
|
||||
count: int = 0
|
||||
|
||||
# 内部函数(闭包)捕获 count
|
||||
def counter() -> int:
|
||||
nonlocal count
|
||||
count = count + 1
|
||||
return count
|
||||
|
||||
return counter
|
||||
|
||||
|
||||
def closure_test() -> int:
|
||||
# global 测试
|
||||
stdio.printf("global: %d\n", test_global())
|
||||
stdio.printf("global: %d\n", test_global())
|
||||
stdio.printf("global: %d\n", test_global())
|
||||
|
||||
# nonlocal/闭包测试
|
||||
f: t.CPtr = make_counter()
|
||||
stdio.printf("closure: %d\n", f())
|
||||
stdio.printf("closure: %d\n", f())
|
||||
stdio.printf("closure: %d\n", f())
|
||||
|
||||
return 0
|
||||
@@ -1,183 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# deco_test - t/c 装饰器测试
|
||||
#
|
||||
# 测试 t.CDefine / t.CExport / t.CInline / t.CExtern / t.State
|
||||
# ============================================================
|
||||
|
||||
|
||||
# Test 1: t.CDefine - 常量定义
|
||||
MAX_VALUE: t.CDefine = 256
|
||||
PI_APPROX: t.CDefine = 314
|
||||
# Test 10: t.CDefine 作为 t.CArray 的 count
|
||||
ARR_SIZE: t.CDefine = 8
|
||||
|
||||
|
||||
# Test 2: t.CExport - 导出函数标记
|
||||
def ExportedAdd(a: t.CInt, b: t.CInt) -> t.CInt | t.CExport:
|
||||
return a + b
|
||||
|
||||
|
||||
# Test 3: t.CInline - 内联函数标记
|
||||
def InlineSquare(x: t.CInt) -> t.CInt | t.CInline:
|
||||
return x * x
|
||||
|
||||
|
||||
# Test 4: 普通函数(无装饰器,作为对照)
|
||||
def NormalSub(a: t.CInt, b: t.CInt) -> t.CInt:
|
||||
return a - b
|
||||
|
||||
|
||||
# Test 5: t.CExport 与 t.CInline 组合
|
||||
def ExportedInlineCube(x: t.CInt) -> t.CInt | t.CExport | t.CInline:
|
||||
return x * x * x
|
||||
|
||||
|
||||
# Test 6: t.CExport 返回指针
|
||||
def ExportedFindChar(s: str, ch: t.CInt) -> str | t.CExport:
|
||||
return string.strchr(s, ch)
|
||||
|
||||
|
||||
def test_cdefine():
|
||||
stdio.printf("--- Test 1: t.CDefine ---\n")
|
||||
stdio.printf("MAX_VALUE=%d (expect 256)\n", MAX_VALUE)
|
||||
stdio.printf("PI_APPROX=%d (expect 314)\n", PI_APPROX)
|
||||
if MAX_VALUE == 256:
|
||||
stdio.printf("MAX_VALUE OK\n")
|
||||
else:
|
||||
stdio.printf("MAX_VALUE FAIL\n")
|
||||
if PI_APPROX == 314:
|
||||
stdio.printf("PI_APPROX OK\n")
|
||||
else:
|
||||
stdio.printf("PI_APPROX FAIL\n")
|
||||
|
||||
|
||||
def test_cexport():
|
||||
stdio.printf("--- Test 2: t.CExport ---\n")
|
||||
r: t.CInt = ExportedAdd(3, 4)
|
||||
stdio.printf("ExportedAdd(3,4)=%d (expect 7)\n", r)
|
||||
if r == 7:
|
||||
stdio.printf("ExportedAdd OK\n")
|
||||
else:
|
||||
stdio.printf("ExportedAdd FAIL\n")
|
||||
|
||||
|
||||
def test_cinline():
|
||||
stdio.printf("--- Test 3: t.CInline ---\n")
|
||||
r: t.CInt = InlineSquare(5)
|
||||
stdio.printf("InlineSquare(5)=%d (expect 25)\n", r)
|
||||
if r == 25:
|
||||
stdio.printf("InlineSquare OK\n")
|
||||
else:
|
||||
stdio.printf("InlineSquare FAIL\n")
|
||||
|
||||
|
||||
def test_deco_normal():
|
||||
stdio.printf("--- Test 4: normal function ---\n")
|
||||
r: t.CInt = NormalSub(10, 3)
|
||||
stdio.printf("NormalSub(10,3)=%d (expect 7)\n", r)
|
||||
if r == 7:
|
||||
stdio.printf("NormalSub OK\n")
|
||||
else:
|
||||
stdio.printf("NormalSub FAIL\n")
|
||||
|
||||
|
||||
def test_export_inline():
|
||||
stdio.printf("--- Test 5: t.CExport | t.CInline ---\n")
|
||||
r: t.CInt = ExportedInlineCube(3)
|
||||
stdio.printf("ExportedInlineCube(3)=%d (expect 27)\n", r)
|
||||
if r == 27:
|
||||
stdio.printf("ExportedInlineCube OK\n")
|
||||
else:
|
||||
stdio.printf("ExportedInlineCube FAIL\n")
|
||||
|
||||
|
||||
def test_export_ptr():
|
||||
stdio.printf("--- Test 6: t.CExport return ptr ---\n")
|
||||
p: str = ExportedFindChar("Hello", 108) # 'l' = 108
|
||||
if p is not None:
|
||||
stdio.printf("ExportedFindChar found, char=%d (expect 108)\n", c.Deref(p))
|
||||
if c.Deref(p) == 108:
|
||||
stdio.printf("ExportedFindChar OK\n")
|
||||
else:
|
||||
stdio.printf("ExportedFindChar FAIL\n")
|
||||
else:
|
||||
stdio.printf("ExportedFindChar NOT FOUND (FAIL)\n")
|
||||
|
||||
|
||||
# Test 7: t.CExtern | t.CExport - 外部声明函数(pass 体)
|
||||
# 声明一个外部函数,翻译器应生成 declare 而非 define
|
||||
def ExternalDecl(x: t.CInt) -> t.CInt | t.CExtern | t.CExport: pass
|
||||
|
||||
|
||||
# Test 8: t.State - 状态声明(等价于 CExtern | CExport)
|
||||
def StateDecl(x: t.CInt) -> t.CInt | t.State: pass
|
||||
|
||||
|
||||
# Test 9: t.State 返回 void
|
||||
def StateVoidDecl() -> t.State: pass
|
||||
|
||||
|
||||
def test_extern_decl():
|
||||
stdio.printf("--- Test 7: t.CExtern | t.CExport ---\n")
|
||||
# 外部声明函数,不调用(应由链接器解析符号)
|
||||
stdio.printf("ExternalDecl declared (not called)\n")
|
||||
stdio.printf("ExternalDecl OK\n")
|
||||
|
||||
|
||||
def test_state_decl():
|
||||
stdio.printf("--- Test 8: t.State ---\n")
|
||||
stdio.printf("StateDecl declared (not called)\n")
|
||||
stdio.printf("StateDecl OK\n")
|
||||
|
||||
|
||||
def test_state_void_decl():
|
||||
stdio.printf("--- Test 9: t.State (void) ---\n")
|
||||
stdio.printf("StateVoidDecl declared (not called)\n")
|
||||
stdio.printf("StateVoidDecl OK\n")
|
||||
|
||||
|
||||
# Test 10: t.CDefine 作为 t.CArray count
|
||||
# ARR_SIZE: t.CDefine = 8 已在文件顶部定义
|
||||
def test_cdefine_array_count():
|
||||
stdio.printf("--- Test 10: t.CArray[elem, CDefine] ---\n")
|
||||
# 使用 CDefine 常量名作为数组 count
|
||||
arr: t.CArray[t.CInt, ARR_SIZE]
|
||||
i: t.CInt
|
||||
# 初始化: arr[i] = i * 10
|
||||
for i in range(ARR_SIZE):
|
||||
arr[i] = i * 10
|
||||
# 求和验证: 0+10+20+...+70 = 280
|
||||
total: t.CInt = 0
|
||||
for i in range(ARR_SIZE):
|
||||
total += arr[i]
|
||||
stdio.printf("ARR_SIZE=%d (expect 8)\n", ARR_SIZE)
|
||||
stdio.printf("arr sum=%d (expect 280)\n", total)
|
||||
stdio.printf("arr[0]=%d (expect 0)\n", arr[0])
|
||||
stdio.printf("arr[7]=%d (expect 70)\n", arr[7])
|
||||
if ARR_SIZE == 8 and total == 280 and arr[0] == 0 and arr[7] == 70:
|
||||
stdio.printf("CArray CDefine count OK\n")
|
||||
else:
|
||||
stdio.printf("CArray CDefine count FAIL\n")
|
||||
|
||||
|
||||
def deco_test() -> int:
|
||||
stdio.printf("=== deco_test: t/c 装饰器测试 ===\n\n")
|
||||
|
||||
test_cdefine()
|
||||
test_cexport()
|
||||
test_cinline()
|
||||
test_deco_normal()
|
||||
test_export_inline()
|
||||
test_export_ptr()
|
||||
test_extern_decl()
|
||||
test_state_decl()
|
||||
test_state_void_decl()
|
||||
test_cdefine_array_count()
|
||||
|
||||
stdio.printf("\n=== deco_test 完成 ===\n")
|
||||
return 0
|
||||
@@ -1,9 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def deref_min_test() -> int:
|
||||
s: str = "hello"
|
||||
v: int = c.Deref(s)
|
||||
stdio.printf("deref: %d\n", v)
|
||||
return 0
|
||||
@@ -1,13 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def deref_test() -> int:
|
||||
s: str = "hello"
|
||||
sp: str = s
|
||||
slen: int = 0
|
||||
while c.Deref(sp) != 0:
|
||||
slen = slen + 1
|
||||
sp = sp + 1
|
||||
stdio.printf("ptr: len(hello)=%d\n", slen)
|
||||
return 0
|
||||
@@ -1,144 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# eq_test - ==、!=、is、is not、None 比较测试
|
||||
#
|
||||
# 验证比较表达式的翻译,特别是 None 常量和 is/is not 操作符
|
||||
# ============================================================
|
||||
|
||||
|
||||
def test_int_eq():
|
||||
stdio.printf("--- Test 1: int == / != ---\n")
|
||||
|
||||
a: t.CInt = 42
|
||||
b: t.CInt = 42
|
||||
c3: t.CInt = 99
|
||||
|
||||
if a == b:
|
||||
stdio.printf("int == int (same) OK\n")
|
||||
else:
|
||||
stdio.printf("int == int (same) FAIL\n")
|
||||
|
||||
if a != c3:
|
||||
stdio.printf("int != int (diff) OK\n")
|
||||
else:
|
||||
stdio.printf("int != int (diff) FAIL\n")
|
||||
|
||||
if not (a == c3):
|
||||
stdio.printf("not (int == diff) OK\n")
|
||||
else:
|
||||
stdio.printf("not (int == diff) FAIL\n")
|
||||
|
||||
|
||||
def test_int_cmp():
|
||||
stdio.printf("--- Test 2: int < > <= >= ---\n")
|
||||
|
||||
a: t.CInt = 5
|
||||
b: t.CInt = 10
|
||||
|
||||
if a < b:
|
||||
stdio.printf("int < OK\n")
|
||||
else:
|
||||
stdio.printf("int < FAIL\n")
|
||||
|
||||
if b > a:
|
||||
stdio.printf("int > OK\n")
|
||||
else:
|
||||
stdio.printf("int > FAIL\n")
|
||||
|
||||
if a <= 5:
|
||||
stdio.printf("int <= OK\n")
|
||||
else:
|
||||
stdio.printf("int <= FAIL\n")
|
||||
|
||||
if b >= 10:
|
||||
stdio.printf("int >= OK\n")
|
||||
else:
|
||||
stdio.printf("int >= FAIL\n")
|
||||
|
||||
|
||||
def test_ptr_is_none():
|
||||
stdio.printf("--- Test 3: ptr is None / is not None ---\n")
|
||||
|
||||
# strchr 找到字符返回非空指针,找不到返回 None
|
||||
p: str = string.strchr("Hello", 108) # 'l' = 108
|
||||
if p is not None:
|
||||
stdio.printf("strchr found, is not None OK\n")
|
||||
else:
|
||||
stdio.printf("strchr found, is not None FAIL\n")
|
||||
|
||||
p2: str = string.strchr("Hello", 122) # 'z' = 122, not found
|
||||
if p2 is None:
|
||||
stdio.printf("strchr not found, is None OK\n")
|
||||
else:
|
||||
stdio.printf("strchr not found, is None FAIL\n")
|
||||
|
||||
|
||||
def test_ptr_assign_none():
|
||||
stdio.printf("--- Test 4: assign None and compare ---\n")
|
||||
|
||||
p: str = None
|
||||
if p is None:
|
||||
stdio.printf("None assign, is None OK\n")
|
||||
else:
|
||||
stdio.printf("None assign, is None FAIL\n")
|
||||
|
||||
if p is not None:
|
||||
stdio.printf("None assign, is not None FAIL\n")
|
||||
else:
|
||||
stdio.printf("None assign, is not None OK\n")
|
||||
|
||||
|
||||
def test_ptr_eq_none():
|
||||
stdio.printf("--- Test 5: ptr == None / != None ---\n")
|
||||
|
||||
p: str = string.strstr("Hello World", "World")
|
||||
if p != None:
|
||||
stdio.printf("strstr found, != None OK\n")
|
||||
else:
|
||||
stdio.printf("strstr found, != None FAIL\n")
|
||||
|
||||
p2: str = string.strstr("Hello", "xyz")
|
||||
if p2 == None:
|
||||
stdio.printf("strstr not found, == None OK\n")
|
||||
else:
|
||||
stdio.printf("strstr not found, == None FAIL\n")
|
||||
|
||||
|
||||
def test_bool_logic():
|
||||
stdio.printf("--- Test 6: bool and/or ---\n")
|
||||
|
||||
a: t.CInt = 1
|
||||
b: t.CInt = 0
|
||||
|
||||
if a and b:
|
||||
stdio.printf("1 and 0 = true FAIL\n")
|
||||
else:
|
||||
stdio.printf("1 and 0 = false OK\n")
|
||||
|
||||
if a or b:
|
||||
stdio.printf("1 or 0 = true OK\n")
|
||||
else:
|
||||
stdio.printf("1 or 0 = true FAIL\n")
|
||||
|
||||
if not b:
|
||||
stdio.printf("not 0 = true OK\n")
|
||||
else:
|
||||
stdio.printf("not 0 = true FAIL\n")
|
||||
|
||||
|
||||
def eq_test() -> int:
|
||||
stdio.printf("=== eq_test: ==、!=、is、None 比较测试 ===\n\n")
|
||||
|
||||
test_int_eq()
|
||||
test_int_cmp()
|
||||
test_ptr_is_none()
|
||||
test_ptr_assign_none()
|
||||
test_ptr_eq_none()
|
||||
test_bool_logic()
|
||||
|
||||
stdio.printf("\n=== eq_test 完成 ===\n")
|
||||
return 0
|
||||
@@ -1,84 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 联合体(t.CUnion)含浮点字段
|
||||
# ============================================================
|
||||
|
||||
class DataUnion(t.CUnion):
|
||||
i: t.CInt
|
||||
f: t.CFloat
|
||||
l: t.CInt64T
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 主函数
|
||||
# ============================================================
|
||||
def float_test() -> int:
|
||||
# ============================================================
|
||||
# 测试 1: 基本浮点变量(float / double)
|
||||
# ============================================================
|
||||
f: t.CFloat = 3.14
|
||||
stdio.printf("float: f=%f\n", f)
|
||||
|
||||
d: t.CDouble = 3.141592653589793
|
||||
stdio.printf("double: d=%lf\n", d)
|
||||
|
||||
# 重新赋值
|
||||
f = 2.5
|
||||
stdio.printf("float: f=%f\n", f)
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 联合体浮点字段
|
||||
# ============================================================
|
||||
u: DataUnion
|
||||
u.f = 3.14
|
||||
stdio.printf("union: u.f=%f\n", u.f)
|
||||
|
||||
# 写入 i 字段后,f 的值已被覆盖
|
||||
u.i = 42
|
||||
stdio.printf("union: u.i=%d (after f overwritten)\n", u.i)
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: 联合体共享内存验证(float 与 int 共享)
|
||||
# ============================================================
|
||||
u2: DataUnion
|
||||
u2.i = 0
|
||||
u2.f = 1.0
|
||||
# 写入 f 后,i 的值应不再是 0
|
||||
if u2.i != 0:
|
||||
stdio.printf("union: float overwrites int verified\n")
|
||||
|
||||
# ============================================================
|
||||
# 测试 4: 浮点算术运算(fadd/fsub/fmul/fdiv/frem)
|
||||
# ============================================================
|
||||
a: t.CFloat = 1.5
|
||||
b: t.CFloat = 2.5
|
||||
stdio.printf("arith: %.2f + %.2f = %.2f\n", a, b, a + b)
|
||||
stdio.printf("arith: %.2f - %.2f = %.2f\n", a, b, a - b)
|
||||
stdio.printf("arith: %.2f * %.2f = %.2f\n", a, b, a * b)
|
||||
stdio.printf("arith: %.2f / %.2f = %.2f\n", a, b, a / b)
|
||||
|
||||
# ============================================================
|
||||
# 测试 5: double 算术运算
|
||||
# ============================================================
|
||||
x: t.CDouble = 10.0
|
||||
y: t.CDouble = 3.0
|
||||
stdio.printf("arith: %.4lf + %.4lf = %.4lf\n", x, y, x + y)
|
||||
stdio.printf("arith: %.4lf - %.4lf = %.4lf\n", x, y, x - y)
|
||||
stdio.printf("arith: %.4lf * %.4lf = %.4lf\n", x, y, x * y)
|
||||
stdio.printf("arith: %.4lf / %.4lf = %.4lf\n", x, y, x / y)
|
||||
|
||||
# ============================================================
|
||||
# 测试 6: 浮点取模 (frem)
|
||||
# ============================================================
|
||||
stdio.printf("arith: 10.0 %% 3.0 = %.4lf\n", x % y)
|
||||
|
||||
# ============================================================
|
||||
# 测试 7: int 与 float 混合运算(int 自动转 float)
|
||||
# ============================================================
|
||||
n: t.CInt = 3
|
||||
stdio.printf("arith: %d + %.2f = %.2f\n", n, a, n + a)
|
||||
|
||||
return 0
|
||||
@@ -1,23 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def flow_test() -> int:
|
||||
i: int = 0
|
||||
total: int = 0
|
||||
while i < 5:
|
||||
total = total + i
|
||||
i = i + 1
|
||||
stdio.printf("while: total=%d i=%d\n", total, i)
|
||||
|
||||
for k in range(10):
|
||||
if k == 3:
|
||||
break
|
||||
stdio.printf("break: k=%d\n", k)
|
||||
|
||||
for m in range(5):
|
||||
if m == 2:
|
||||
continue
|
||||
stdio.printf("continue: m=%d\n", m)
|
||||
|
||||
return 0
|
||||
@@ -1,8 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def for_test() -> int:
|
||||
for j in range(5):
|
||||
stdio.printf("for: j=%d\n", j)
|
||||
return 0
|
||||
@@ -1,68 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def add(a: int, b: int) -> int:
|
||||
return a + b
|
||||
|
||||
|
||||
def mul(a: int, b: int) -> int:
|
||||
return a * b
|
||||
|
||||
|
||||
def square(x: int) -> int:
|
||||
return mul(x, x)
|
||||
|
||||
|
||||
def factorial(n: int) -> int:
|
||||
if n <= 1:
|
||||
return 1
|
||||
return n * factorial(n - 1)
|
||||
|
||||
|
||||
def greet(greeting: str, name: str, times: int) -> int:
|
||||
i: int = 0
|
||||
while i < times:
|
||||
stdio.printf("%s, %s!\n", greeting, name)
|
||||
i = i + 1
|
||||
return times
|
||||
|
||||
|
||||
def sub(a: int, b: int) -> int:
|
||||
return a - b
|
||||
|
||||
|
||||
def func_test() -> int:
|
||||
r1: int = add(3, 4)
|
||||
stdio.printf("add(3,4)=%d\n", r1)
|
||||
|
||||
r2: int = mul(5, 6)
|
||||
stdio.printf("mul(5,6)=%d\n", r2)
|
||||
|
||||
r3: int = square(7)
|
||||
stdio.printf("square(7)=%d\n", r3)
|
||||
|
||||
r5: int = factorial(5)
|
||||
stdio.printf("factorial(5)=%d\n", r5)
|
||||
|
||||
# ============================================================
|
||||
# 测试: 函数乱序传参(关键字参数)
|
||||
# ============================================================
|
||||
# 乱序传参:b=4, a=3 等价于 add(3, 4)
|
||||
r6: int = add(b=4, a=3)
|
||||
stdio.printf("add(b=4,a=3)=%d\n", r6)
|
||||
|
||||
# 乱序传参:a=10, b=3 等价于 sub(10, 3)
|
||||
r7: int = sub(b=3, a=10)
|
||||
stdio.printf("sub(b=3,a=10)=%d\n", r7)
|
||||
|
||||
# 混合传参:位置参数 + 关键字参数
|
||||
# greeting="Hello" 是位置参数,name="World" 和 times=2 是关键字
|
||||
r8: int = greet("Hello", name="World", times=2)
|
||||
stdio.printf("greet mixed: returned=%d\n", r8)
|
||||
|
||||
# 全关键字乱序传参
|
||||
r9: int = greet(times=1, name="TransPyC", greeting="Hi")
|
||||
stdio.printf("greet kwargs: returned=%d\n", r9)
|
||||
|
||||
return 0
|
||||
@@ -1,116 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 场景 A: @t.NoVTable 类 + 函数级 @t.CVTable
|
||||
#
|
||||
# NoVTableClass 标记 @t.NoVTable(类级别禁用虚表)
|
||||
# 但 VirtualMethod 标记 @t.CVTable → 该方法单独进入虚表
|
||||
# NormalMethod 无装饰器 → 不进入虚表
|
||||
# 预期: 虚表 1 个方法 (VirtualMethod)
|
||||
# ============================================================
|
||||
@t.NoVTable
|
||||
class NoVTableClass:
|
||||
val: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.val = v
|
||||
|
||||
@t.CVTable
|
||||
def VirtualMethod(self) -> t.CInt:
|
||||
return self.val + 10
|
||||
|
||||
def NormalMethod(self) -> t.CInt:
|
||||
return self.val + 20
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 场景 B: @t.CVTable 类 + 函数级 @t.NoVTable
|
||||
#
|
||||
# CVTableClass 标记 @t.CVTable(所有方法进入虚表)
|
||||
# KeptMethod 无装饰器 → 进入虚表
|
||||
# ExcludedMethod 标记 @t.NoVTable → 排除出虚表
|
||||
# 预期: 虚表 1 个方法 (KeptMethod)
|
||||
# ============================================================
|
||||
@t.CVTable
|
||||
class CVTableClass:
|
||||
val: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.val = v
|
||||
|
||||
def KeptMethod(self) -> t.CInt:
|
||||
return self.val + 30
|
||||
|
||||
@t.NoVTable
|
||||
def ExcludedMethod(self) -> t.CInt:
|
||||
return self.val + 40
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 场景 C: 默认类(无装饰器无继承)+ 函数级 @t.CVTable
|
||||
#
|
||||
# DefaultClass 无装饰器(默认无虚表)
|
||||
# VirtualMethod 标记 @t.CVTable → 单独进入虚表
|
||||
# NormalMethod 无装饰器 → 不进入虚表
|
||||
# 预期: 虚表 1 个方法 (VirtualMethod)
|
||||
# ============================================================
|
||||
class DefaultClass:
|
||||
val: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.val = v
|
||||
|
||||
@t.CVTable
|
||||
def VirtualMethod(self) -> t.CInt:
|
||||
return self.val + 50
|
||||
|
||||
def NormalMethod(self) -> t.CInt:
|
||||
return self.val + 60
|
||||
|
||||
|
||||
def func_vtable_test() -> int:
|
||||
stdio.printf("funcvt: === Test Start ===\n")
|
||||
|
||||
# 场景 A: NoVTableClass
|
||||
nvt: NoVTableClass = NoVTableClass(5)
|
||||
a1: int = nvt.VirtualMethod()
|
||||
stdio.printf("funcvt: A.VirtualMethod()=%d (expected 15)\n", a1)
|
||||
if a1 != 15:
|
||||
stdio.printf("[FAIL] A.VirtualMethod()=%d expected 15\n", a1)
|
||||
return 1
|
||||
a2: int = nvt.NormalMethod()
|
||||
stdio.printf("funcvt: A.NormalMethod()=%d (expected 25)\n", a2)
|
||||
if a2 != 25:
|
||||
stdio.printf("[FAIL] A.NormalMethod()=%d expected 25\n", a2)
|
||||
return 1
|
||||
|
||||
# 场景 B: CVTableClass
|
||||
cvt: CVTableClass = CVTableClass(7)
|
||||
b1: int = cvt.KeptMethod()
|
||||
stdio.printf("funcvt: B.KeptMethod()=%d (expected 37)\n", b1)
|
||||
if b1 != 37:
|
||||
stdio.printf("[FAIL] B.KeptMethod()=%d expected 37\n", b1)
|
||||
return 1
|
||||
b2: int = cvt.ExcludedMethod()
|
||||
stdio.printf("funcvt: B.ExcludedMethod()=%d (expected 47)\n", b2)
|
||||
if b2 != 47:
|
||||
stdio.printf("[FAIL] B.ExcludedMethod()=%d expected 47\n", b2)
|
||||
return 1
|
||||
|
||||
# 场景 C: DefaultClass
|
||||
dfc: DefaultClass = DefaultClass(9)
|
||||
c1: int = dfc.VirtualMethod()
|
||||
stdio.printf("funcvt: C.VirtualMethod()=%d (expected 59)\n", c1)
|
||||
if c1 != 59:
|
||||
stdio.printf("[FAIL] C.VirtualMethod()=%d expected 59\n", c1)
|
||||
return 1
|
||||
c2: int = dfc.NormalMethod()
|
||||
stdio.printf("funcvt: C.NormalMethod()=%d (expected 69)\n", c2)
|
||||
if c2 != 69:
|
||||
stdio.printf("[FAIL] C.NormalMethod()=%d expected 69\n", c2)
|
||||
return 1
|
||||
|
||||
stdio.printf("funcvt: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,121 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 继承测试:字段展平 + vtable 继承 + 方法覆盖
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 基类 Animal(有虚方法)
|
||||
# ============================================================
|
||||
@t.CVTable
|
||||
class Animal:
|
||||
name: t.CInt
|
||||
|
||||
def __init__(self, n: t.CInt):
|
||||
self.name = n
|
||||
|
||||
def GetName(self) -> t.CInt:
|
||||
return self.name
|
||||
|
||||
def Speak(self) -> t.CInt:
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 子类 Dog(继承 Animal,覆盖 Speak,新增字段和方法)
|
||||
# ============================================================
|
||||
class Dog(Animal):
|
||||
breed: t.CInt
|
||||
|
||||
def __init__(self, n: t.CInt, b: t.CInt):
|
||||
self.name = n
|
||||
self.breed = b
|
||||
|
||||
def Speak(self) -> t.CInt:
|
||||
return 1
|
||||
|
||||
def GetBreed(self) -> t.CInt:
|
||||
return self.breed
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 子类 Cat(继承 Animal,不覆盖 Speak,新增字段和方法)
|
||||
# ============================================================
|
||||
class Cat(Animal):
|
||||
color: t.CInt
|
||||
|
||||
def __init__(self, n: t.CInt, col: t.CInt):
|
||||
self.name = n
|
||||
self.color = col
|
||||
|
||||
def GetColor(self) -> t.CInt:
|
||||
return self.color
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 主函数
|
||||
# ============================================================
|
||||
def inherit_test() -> int:
|
||||
# ============================================================
|
||||
# 测试 1: 基类 Animal
|
||||
# ============================================================
|
||||
stdio.printf("inherit: === Test 1: Base Class ===\n")
|
||||
a: Animal = Animal(42)
|
||||
aname: int = a.GetName()
|
||||
stdio.printf("inherit: a.GetName()=%d (expected 42)\n", aname)
|
||||
if aname != 42:
|
||||
stdio.printf("[FAIL] a.GetName()=%d expected 42\n", aname)
|
||||
return 1
|
||||
aspeak: int = a.Speak()
|
||||
stdio.printf("inherit: a.Speak()=%d (expected 0)\n", aspeak)
|
||||
if aspeak != 0:
|
||||
stdio.printf("[FAIL] a.Speak()=%d expected 0\n", aspeak)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 子类 Dog(覆盖 Speak,继承 GetName)
|
||||
# ============================================================
|
||||
stdio.printf("inherit: === Test 2: Dog (override Speak) ===\n")
|
||||
d: Dog = Dog(100, 7)
|
||||
dname: int = d.GetName()
|
||||
stdio.printf("inherit: d.GetName()=%d (expected 100)\n", dname)
|
||||
if dname != 100:
|
||||
stdio.printf("[FAIL] d.GetName()=%d expected 100\n", dname)
|
||||
return 1
|
||||
dspeak: int = d.Speak()
|
||||
stdio.printf("inherit: d.Speak()=%d (expected 1)\n", dspeak)
|
||||
if dspeak != 1:
|
||||
stdio.printf("[FAIL] d.Speak()=%d expected 1\n", dspeak)
|
||||
return 1
|
||||
dbreed: int = d.GetBreed()
|
||||
stdio.printf("inherit: d.GetBreed()=%d (expected 7)\n", dbreed)
|
||||
if dbreed != 7:
|
||||
stdio.printf("[FAIL] d.GetBreed()=%d expected 7\n", dbreed)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: 子类 Cat(不覆盖 Speak,继承 GetName)
|
||||
# ============================================================
|
||||
stdio.printf("inherit: === Test 3: Cat (inherit Speak) ===\n")
|
||||
ct: Cat = Cat(200, 3)
|
||||
cname: int = ct.GetName()
|
||||
stdio.printf("inherit: ct.GetName()=%d (expected 200)\n", cname)
|
||||
if cname != 200:
|
||||
stdio.printf("[FAIL] ct.GetName()=%d expected 200\n", cname)
|
||||
return 1
|
||||
cspeak: int = ct.Speak()
|
||||
stdio.printf("inherit: ct.Speak()=%d (expected 0)\n", cspeak)
|
||||
if cspeak != 0:
|
||||
stdio.printf("[FAIL] ct.Speak()=%d expected 0\n", cspeak)
|
||||
return 1
|
||||
ccolor: int = ct.GetColor()
|
||||
stdio.printf("inherit: ct.GetColor()=%d (expected 3)\n", ccolor)
|
||||
if ccolor != 3:
|
||||
stdio.printf("[FAIL] ct.GetColor()=%d expected 3\n", ccolor)
|
||||
return 1
|
||||
|
||||
stdio.printf("inherit: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,247 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
|
||||
|
||||
# ============================================================
|
||||
# c.LLVMIR / c.LInp / c.LOut 内联 LLVM IR 测试
|
||||
#
|
||||
# 测试 c.LLVMIR 内联 LLVM IR 指令的生成和执行
|
||||
# - c.LInp(expr) 标记输入操作数
|
||||
# - c.LOut(expr) 标记输出操作数
|
||||
# ============================================================
|
||||
|
||||
|
||||
# Test 1: 基本加法 add
|
||||
def test_add() -> t.CInt:
|
||||
stdio.printf("--- Test 1: LLVMIR add ---\n")
|
||||
a: t.CInt = 10
|
||||
b: t.CInt = 20
|
||||
r: t.CInt = c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("add(10, 20)=%d (expect 30)\n", r)
|
||||
if r == 30:
|
||||
stdio.printf("LLVMIR add OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR add FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 2: 基本减法 sub
|
||||
def test_sub() -> t.CInt:
|
||||
stdio.printf("--- Test 2: LLVMIR sub ---\n")
|
||||
a: t.CInt = 50
|
||||
b: t.CInt = 20
|
||||
r: t.CInt = c.LLVMIR(f"sub i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("sub(50, 20)=%d (expect 30)\n", r)
|
||||
if r == 30:
|
||||
stdio.printf("LLVMIR sub OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR sub FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 3: 基本乘法 mul
|
||||
def test_mul() -> t.CInt:
|
||||
stdio.printf("--- Test 3: LLVMIR mul ---\n")
|
||||
a: t.CInt = 6
|
||||
b: t.CInt = 7
|
||||
r: t.CInt = c.LLVMIR(f"mul i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("mul(6, 7)=%d (expect 42)\n", r)
|
||||
if r == 42:
|
||||
stdio.printf("LLVMIR mul OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR mul FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 4: 基本除法 sdiv
|
||||
def test_sdiv() -> t.CInt:
|
||||
stdio.printf("--- Test 4: LLVMIR sdiv ---\n")
|
||||
a: t.CInt = 100
|
||||
b: t.CInt = 4
|
||||
r: t.CInt = c.LLVMIR(f"sdiv i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("sdiv(100, 4)=%d (expect 25)\n", r)
|
||||
if r == 25:
|
||||
stdio.printf("LLVMIR sdiv OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR sdiv FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 5: 位运算 and
|
||||
def test_and() -> t.CInt:
|
||||
stdio.printf("--- Test 5: LLVMIR and ---\n")
|
||||
a: t.CInt = 255
|
||||
b: t.CInt = 15
|
||||
r: t.CInt = c.LLVMIR(f"and i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("and(255, 15)=%d (expect 15)\n", r)
|
||||
if r == 15:
|
||||
stdio.printf("LLVMIR and OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR and FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 6: 位运算 or
|
||||
def test_or() -> t.CInt:
|
||||
stdio.printf("--- Test 6: LLVMIR or ---\n")
|
||||
a: t.CInt = 240
|
||||
b: t.CInt = 15
|
||||
r: t.CInt = c.LLVMIR(f"or i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("or(240, 15)=%d (expect 255)\n", r)
|
||||
if r == 255:
|
||||
stdio.printf("LLVMIR or OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR or FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 7: 位运算 xor
|
||||
def test_xor() -> t.CInt:
|
||||
stdio.printf("--- Test 7: LLVMIR xor ---\n")
|
||||
a: t.CInt = 255
|
||||
b: t.CInt = 15
|
||||
r: t.CInt = c.LLVMIR(f"xor i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("xor(255, 15)=%d (expect 240)\n", r)
|
||||
if r == 240:
|
||||
stdio.printf("LLVMIR xor OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR xor FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 8: 左移 shl
|
||||
def test_shl() -> t.CInt:
|
||||
stdio.printf("--- Test 8: LLVMIR shl ---\n")
|
||||
a: t.CInt = 1
|
||||
b: t.CInt = 4
|
||||
r: t.CInt = c.LLVMIR(f"shl i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("shl(1, 4)=%d (expect 16)\n", r)
|
||||
if r == 16:
|
||||
stdio.printf("LLVMIR shl OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR shl FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 9: LOut 输出赋值
|
||||
def test_lout() -> t.CInt:
|
||||
stdio.printf("--- Test 9: LLVMIR LOut ---\n")
|
||||
a: t.CInt = 10
|
||||
b: t.CInt = 20
|
||||
out_val: t.CInt = 0
|
||||
c.LLVMIR(f"{c.LOut(out_val)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("LOut add(10, 20)=%d (expect 30)\n", out_val)
|
||||
if out_val == 30:
|
||||
stdio.printf("LLVMIR LOut OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR LOut FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 10: icmp eq 比较
|
||||
# 注意: TransPyV 用 sext i1 to i32 扩展布尔结果,true -> -1
|
||||
def test_icmp_eq() -> t.CInt:
|
||||
stdio.printf("--- Test 10: LLVMIR icmp eq ---\n")
|
||||
a: t.CInt = 5
|
||||
b: t.CInt = 5
|
||||
r: t.CInt = c.LLVMIR(f"icmp eq i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("icmp eq(5, 5)=%d (expect nonzero)\n", r)
|
||||
if r != 0:
|
||||
stdio.printf("LLVMIR icmp eq OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR icmp eq FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 11: icmp ne 比较
|
||||
def test_icmp_ne() -> t.CInt:
|
||||
stdio.printf("--- Test 11: LLVMIR icmp ne ---\n")
|
||||
a: t.CInt = 5
|
||||
b: t.CInt = 3
|
||||
r: t.CInt = c.LLVMIR(f"icmp ne i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("icmp ne(5, 3)=%d (expect nonzero)\n", r)
|
||||
if r != 0:
|
||||
stdio.printf("LLVMIR icmp ne OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR icmp ne FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 12: icmp slt 比较
|
||||
def test_icmp_slt() -> t.CInt:
|
||||
stdio.printf("--- Test 12: LLVMIR icmp slt ---\n")
|
||||
a: t.CInt = 3
|
||||
b: t.CInt = 5
|
||||
r: t.CInt = c.LLVMIR(f"icmp slt i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("icmp slt(3, 5)=%d (expect nonzero)\n", r)
|
||||
if r != 0:
|
||||
stdio.printf("LLVMIR icmp slt OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR icmp slt FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 13: srem 取余
|
||||
def test_srem() -> t.CInt:
|
||||
stdio.printf("--- Test 13: LLVMIR srem ---\n")
|
||||
a: t.CInt = 17
|
||||
b: t.CInt = 5
|
||||
r: t.CInt = c.LLVMIR(f"srem i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("srem(17, 5)=%d (expect 2)\n", r)
|
||||
if r == 2:
|
||||
stdio.printf("LLVMIR srem OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR srem FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 14: lshr 逻辑右移
|
||||
def test_lshr() -> t.CInt:
|
||||
stdio.printf("--- Test 14: LLVMIR lshr ---\n")
|
||||
a: t.CInt = 256
|
||||
b: t.CInt = 2
|
||||
r: t.CInt = c.LLVMIR(f"lshr i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
stdio.printf("lshr(256, 2)=%d (expect 64)\n", r)
|
||||
if r == 64:
|
||||
stdio.printf("LLVMIR lshr OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR lshr FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
# Test 15: 嵌套在表达式中使用
|
||||
def test_nested() -> t.CInt:
|
||||
stdio.printf("--- Test 15: LLVMIR nested in expression ---\n")
|
||||
a: t.CInt = 10
|
||||
b: t.CInt = 20
|
||||
# c.LLVMIR 结果参与后续运算
|
||||
llvmir_result: t.CInt = c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
|
||||
final_result: t.CInt = llvmir_result + 10
|
||||
stdio.printf("(LLVMIR add(10,20)) + 10 = %d (expect 40)\n", final_result)
|
||||
if final_result == 40:
|
||||
stdio.printf("LLVMIR nested OK\n")
|
||||
else:
|
||||
stdio.printf("LLVMIR nested FAIL\n")
|
||||
return 0
|
||||
|
||||
|
||||
def llvmir_test() -> t.CInt:
|
||||
stdio.printf("=== llvmir_test: c.LLVMIR 内联 LLVM IR 测试 ===\n\n")
|
||||
test_add()
|
||||
test_sub()
|
||||
test_mul()
|
||||
test_sdiv()
|
||||
test_and()
|
||||
test_or()
|
||||
test_xor()
|
||||
test_shl()
|
||||
test_lout()
|
||||
test_icmp_eq()
|
||||
test_icmp_ne()
|
||||
test_icmp_slt()
|
||||
test_srem()
|
||||
test_lshr()
|
||||
test_nested()
|
||||
stdio.printf("\n=== llvmir_test 完成 ===\n")
|
||||
return 0
|
||||
@@ -1,60 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 命名空间隔离测试:定义类模块
|
||||
#
|
||||
# 本文件定义供其他文件 import 使用的类,验证跨模块命名空间隔离:
|
||||
# - 裸名 Class(): 需要 from namespace_defs import Class
|
||||
# - 模块限定 namespace_defs.Class(): 需要 import namespace_defs
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 带虚表的类 Widget
|
||||
# ============================================================
|
||||
@t.CVTable
|
||||
class Widget:
|
||||
id: t.CInt
|
||||
|
||||
def __init__(self, i: t.CInt):
|
||||
self.id = i
|
||||
|
||||
def GetId(self) -> t.CInt:
|
||||
return self.id
|
||||
|
||||
def Render(self) -> t.CInt:
|
||||
return 100
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 子类 Gadget(继承 Widget,覆盖 Render)
|
||||
# ============================================================
|
||||
class Gadget(Widget):
|
||||
extra: t.CInt
|
||||
|
||||
def __init__(self, i: t.CInt, e: t.CInt):
|
||||
self.id = i
|
||||
self.extra = e
|
||||
|
||||
def Render(self) -> t.CInt:
|
||||
return 200
|
||||
|
||||
def GetExtra(self) -> t.CInt:
|
||||
return self.extra
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 普通结构体 PlainStruct(无虚表)
|
||||
# ============================================================
|
||||
class PlainStruct:
|
||||
x: t.CInt
|
||||
y: t.CInt
|
||||
|
||||
def __init__(self, ax: t.CInt, ay: t.CInt):
|
||||
self.x = ax
|
||||
self.y = ay
|
||||
|
||||
def Sum(self) -> t.CInt:
|
||||
return self.x + self.y
|
||||
@@ -1,111 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import namespace_defs
|
||||
from namespace_defs import Widget, Gadget, PlainStruct
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 命名空间隔离测试
|
||||
#
|
||||
# 验证跨模块类访问必须通过 import:
|
||||
# - Test 1: from X import Class → 裸名 Class() 构造
|
||||
# - Test 2: import X → 模块限定 X.Class() 构造
|
||||
# - Test 3: 类型注解使用导入的类
|
||||
# - Test 4: 继承类的虚分派(跨模块继承)
|
||||
# ============================================================
|
||||
|
||||
|
||||
def namespace_test() -> int:
|
||||
stdio.printf("nsisol: === Test Start ===\n")
|
||||
|
||||
# ============================================================
|
||||
# Test 1: from X import Class → 裸名 Class() 构造
|
||||
# ============================================================
|
||||
stdio.printf("nsisol: === Test 1: from-import bare constructor ===\n")
|
||||
|
||||
w: Widget = Widget(42)
|
||||
wid: int = w.GetId()
|
||||
stdio.printf("nsisol: w.GetId()=%d (expected 42)\n", wid)
|
||||
if wid != 42:
|
||||
stdio.printf("[FAIL] w.GetId()=%d expected 42\n", wid)
|
||||
return 1
|
||||
|
||||
wrender: int = w.Render()
|
||||
stdio.printf("nsisol: w.Render()=%d (expected 100)\n", wrender)
|
||||
if wrender != 100:
|
||||
stdio.printf("[FAIL] w.Render()=%d expected 100\n", wrender)
|
||||
return 1
|
||||
|
||||
g: Gadget = Gadget(7, 9)
|
||||
grender: int = g.Render()
|
||||
stdio.printf("nsisol: g.Render()=%d (expected 200)\n", grender)
|
||||
if grender != 200:
|
||||
stdio.printf("[FAIL] g.Render()=%d expected 200\n", grender)
|
||||
return 1
|
||||
|
||||
gextra: int = g.GetExtra()
|
||||
stdio.printf("nsisol: g.GetExtra()=%d (expected 9)\n", gextra)
|
||||
if gextra != 9:
|
||||
stdio.printf("[FAIL] g.GetExtra()=%d expected 9\n", gextra)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# Test 2: import X → 模块限定 X.Class() 构造
|
||||
# ============================================================
|
||||
stdio.printf("nsisol: === Test 2: module-qualified constructor ===\n")
|
||||
|
||||
ps: PlainStruct = PlainStruct(10, 20)
|
||||
psum: int = ps.Sum()
|
||||
stdio.printf("nsisol: ps.Sum()=%d (expected 30)\n", psum)
|
||||
if psum != 30:
|
||||
stdio.printf("[FAIL] ps.Sum()=%d expected 30\n", psum)
|
||||
return 1
|
||||
|
||||
ps2: namespace_defs.PlainStruct = namespace_defs.PlainStruct(5, 6)
|
||||
psum2: int = ps2.Sum()
|
||||
stdio.printf("nsisol: ps2.Sum()=%d (expected 11)\n", psum2)
|
||||
if psum2 != 11:
|
||||
stdio.printf("[FAIL] ps2.Sum()=%d expected 11\n", psum2)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# Test 3: 类型注解使用导入的类
|
||||
# ============================================================
|
||||
stdio.printf("nsisol: === Test 3: type annotation with imported class ===\n")
|
||||
|
||||
annot_w: Widget = Widget(99)
|
||||
annot_id: int = annot_w.GetId()
|
||||
stdio.printf("nsisol: annot_w.GetId()=%d (expected 99)\n", annot_id)
|
||||
if annot_id != 99:
|
||||
stdio.printf("[FAIL] annot_w.GetId()=%d expected 99\n", annot_id)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# Test 4: 跨模块继承的虚分派
|
||||
# ============================================================
|
||||
stdio.printf("nsisol: === Test 4: cross-module inheritance vtable ===\n")
|
||||
|
||||
# Gadget 继承 Widget,覆盖 Render
|
||||
# Widget.Render()=100, Gadget.Render()=200
|
||||
base: Widget = Widget(1)
|
||||
derived: Gadget = Gadget(2, 3)
|
||||
base_r: int = base.Render()
|
||||
deriv_r: int = derived.Render()
|
||||
stdio.printf("nsisol: base.Render()=%d (expected 100)\n", base_r)
|
||||
if base_r != 100:
|
||||
stdio.printf("[FAIL] base.Render()=%d expected 100\n", base_r)
|
||||
return 1
|
||||
stdio.printf("nsisol: derived.Render()=%d (expected 200)\n", deriv_r)
|
||||
if deriv_r != 200:
|
||||
stdio.printf("[FAIL] derived.Render()=%d expected 200\n", deriv_r)
|
||||
return 1
|
||||
|
||||
# 继承的方法:Gadget 继承 Widget.GetId
|
||||
gname: int = derived.GetId()
|
||||
stdio.printf("nsisol: derived.GetId()=%d (expected 2)\n", gname)
|
||||
if gname != 2:
|
||||
stdio.printf("[FAIL] derived.GetId()=%d expected 2\n", gname)
|
||||
return 1
|
||||
|
||||
stdio.printf("nsisol: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,119 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# __new__ 函数测试:验证 __new__ 在创建 OOP 结构体前被调用,
|
||||
# 返回的指针作为结构体存储空间。
|
||||
#
|
||||
# __new__ 签名默认和 __init__ 一样(self + args),返回 Ptr(struct_ty)。
|
||||
# 如果 __new__ 返回 self,则使用默认 alloca 作为存储空间。
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Test 1: __new__ 返回 self(默认 alloca)
|
||||
# 验证 __new__ 被调用且不破坏 __init__ 正常功能
|
||||
# ============================================================
|
||||
class WithNew:
|
||||
value: t.CInt
|
||||
|
||||
def __new__(self, v: t.CInt):
|
||||
stdio.printf("new: WithNew.__new__ called\n")
|
||||
return self
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
stdio.printf("new: WithNew.__init__ called\n")
|
||||
self.value = v
|
||||
|
||||
def GetValue(self) -> t.CInt:
|
||||
return self.value
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Test 2: __new__ 不接受额外参数(仅 self)
|
||||
# 验证 __new__ 签名可以与 __init__ 不同
|
||||
# ============================================================
|
||||
class WithNewNoArgs:
|
||||
value: t.CInt
|
||||
|
||||
def __new__(self):
|
||||
stdio.printf("new: WithNewNoArgs.__new__ called\n")
|
||||
return self
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.value = v
|
||||
|
||||
def GetValue(self) -> t.CInt:
|
||||
return self.value
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Test 3: __new__ + @t.CVTable 虚表类
|
||||
# 验证 __new__ 与虚表机制兼容(__new__ 不进入虚表)
|
||||
# ============================================================
|
||||
@t.CVTable
|
||||
class WithNewVTable:
|
||||
value: t.CInt
|
||||
|
||||
def __new__(self, v: t.CInt):
|
||||
stdio.printf("new: WithNewVTable.__new__ called\n")
|
||||
return self
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.value = v
|
||||
|
||||
def GetValue(self) -> t.CInt:
|
||||
return self.value
|
||||
|
||||
def Speak(self) -> t.CInt:
|
||||
return self.value + 1
|
||||
|
||||
|
||||
def new_test() -> int:
|
||||
stdio.printf("new: === Test Start ===\n")
|
||||
|
||||
# ============================================================
|
||||
# Test 1: __new__ 返回 self
|
||||
# ============================================================
|
||||
stdio.printf("new: === Test 1: __new__ returns self ===\n")
|
||||
|
||||
w: WithNew = WithNew(42)
|
||||
v: int = w.GetValue()
|
||||
stdio.printf("new: w.GetValue()=%d (expected 42)\n", v)
|
||||
if v != 42:
|
||||
stdio.printf("[FAIL] w.GetValue()=%d expected 42\n", v)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# Test 2: __new__ 不接受额外参数
|
||||
# ============================================================
|
||||
stdio.printf("new: === Test 2: __new__ no extra args ===\n")
|
||||
|
||||
n: WithNewNoArgs = WithNewNoArgs(99)
|
||||
nv: int = n.GetValue()
|
||||
stdio.printf("new: n.GetValue()=%d (expected 99)\n", nv)
|
||||
if nv != 99:
|
||||
stdio.printf("[FAIL] n.GetValue()=%d expected 99\n", nv)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# Test 3: __new__ + 虚表类
|
||||
# ============================================================
|
||||
stdio.printf("new: === Test 3: __new__ + vtable ===\n")
|
||||
|
||||
vt: WithNewVTable = WithNewVTable(10)
|
||||
vtv: int = vt.GetValue()
|
||||
stdio.printf("new: vt.GetValue()=%d (expected 10)\n", vtv)
|
||||
if vtv != 10:
|
||||
stdio.printf("[FAIL] vt.GetValue()=%d expected 10\n", vtv)
|
||||
return 1
|
||||
|
||||
vts: int = vt.Speak()
|
||||
stdio.printf("new: vt.Speak()=%d (expected 11)\n", vts)
|
||||
if vts != 11:
|
||||
stdio.printf("[FAIL] vt.Speak()=%d expected 11\n", vts)
|
||||
return 1
|
||||
|
||||
stdio.printf("new: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,129 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# OOP 测试:存在方法的 class 自动升级为 OOP 结构体
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# 测试 1: 基本方法(无 __init__,__before_init__ 零值填充)
|
||||
# ============================================================
|
||||
class Point:
|
||||
x: t.CInt
|
||||
y: t.CInt
|
||||
|
||||
def MoveTo(self, nx: t.CInt, ny: t.CInt) -> t.CInt:
|
||||
self.x = nx
|
||||
self.y = ny
|
||||
return 0
|
||||
|
||||
def GetX(self) -> t.CInt:
|
||||
return self.x
|
||||
|
||||
def GetY(self) -> t.CInt:
|
||||
return self.y
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 带默认值的 OOP 结构体(__before_init__ 应用默认值)
|
||||
# ============================================================
|
||||
class Counter:
|
||||
count: t.CInt = 0
|
||||
step: t.CInt = 1
|
||||
|
||||
def Increment(self) -> t.CInt:
|
||||
self.count = self.count + self.step
|
||||
return self.count
|
||||
|
||||
def Reset(self) -> t.CInt:
|
||||
self.count = 0
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: __init__ 构造函数
|
||||
# ============================================================
|
||||
class Rect:
|
||||
width: t.CInt
|
||||
height: t.CInt
|
||||
|
||||
def __init__(self, w: t.CInt, h: t.CInt):
|
||||
self.width = w
|
||||
self.height = h
|
||||
|
||||
def Area(self) -> t.CInt:
|
||||
return self.width * self.height
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 主函数
|
||||
# ============================================================
|
||||
def oop_test() -> int:
|
||||
# ============================================================
|
||||
# 测试 1: 基本方法调用
|
||||
# ============================================================
|
||||
stdio.printf("oop: === Test 1: Basic Methods ===\n")
|
||||
p: Point = Point()
|
||||
p.MoveTo(10, 20)
|
||||
stdio.printf("oop: p.x=%d p.y=%d\n", p.GetX(), p.GetY())
|
||||
|
||||
if p.GetX() != 10:
|
||||
stdio.printf("[FAIL] p.GetX()=%d expected 10\n", p.GetX())
|
||||
return 1
|
||||
if p.GetY() != 20:
|
||||
stdio.printf("[FAIL] p.GetY()=%d expected 20\n", p.GetY())
|
||||
return 1
|
||||
|
||||
# 修改字段后再次调用方法
|
||||
p.MoveTo(100, 200)
|
||||
stdio.printf("oop: after move p.x=%d p.y=%d\n", p.GetX(), p.GetY())
|
||||
if p.GetX() != 100:
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 默认值 + 方法
|
||||
# ============================================================
|
||||
stdio.printf("oop: === Test 2: Defaults + Methods ===\n")
|
||||
cnt: Counter = Counter()
|
||||
stdio.printf("oop: initial count=%d step=%d\n", cnt.count, cnt.step)
|
||||
if cnt.count != 0:
|
||||
stdio.printf("[FAIL] cnt.count=%d expected 0\n", cnt.count)
|
||||
return 1
|
||||
if cnt.step != 1:
|
||||
stdio.printf("[FAIL] cnt.step=%d expected 1\n", cnt.step)
|
||||
return 1
|
||||
|
||||
r1: int = cnt.Increment()
|
||||
r2: int = cnt.Increment()
|
||||
r3: int = cnt.Increment()
|
||||
stdio.printf("oop: after 3 increments: %d %d %d\n", r1, r2, r3)
|
||||
if r1 != 1 or r2 != 2 or r3 != 3:
|
||||
stdio.printf("[FAIL] increments: %d %d %d\n", r1, r2, r3)
|
||||
return 1
|
||||
|
||||
cnt.Reset()
|
||||
r4: int = cnt.Increment()
|
||||
stdio.printf("oop: after reset+increment: %d\n", r4)
|
||||
if r4 != 1:
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: __init__ 构造函数
|
||||
# ============================================================
|
||||
stdio.printf("oop: === Test 3: __init__ ===\n")
|
||||
rect: Rect = Rect(3, 4)
|
||||
area: int = rect.Area()
|
||||
stdio.printf("oop: rect %dx%d area=%d\n", rect.width, rect.height, area)
|
||||
if area != 12:
|
||||
stdio.printf("[FAIL] area=%d expected 12\n", area)
|
||||
return 1
|
||||
if rect.width != 3:
|
||||
stdio.printf("[FAIL] width=%d expected 3\n", rect.width)
|
||||
return 1
|
||||
if rect.height != 4:
|
||||
stdio.printf("[FAIL] height=%d expected 4\n", rect.height)
|
||||
return 1
|
||||
|
||||
stdio.printf("oop: === All OOP Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,253 +0,0 @@
|
||||
import stdio
|
||||
import stdlib
|
||||
import t, c
|
||||
import testcheck
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 运算符重载测试
|
||||
#
|
||||
# 验证: 当 lhs 是结构体指针时,二元/比较运算触发 dunder 方法调用
|
||||
# 支持: __add__/__sub__/__mul__/__div__/__mod__/__and__/__or__/__xor__
|
||||
# __lshift__/__rshift__/__floordiv__ (BinOp)
|
||||
# __eq__/__ne__/__lt__/__le__/__gt__/__ge__ (Compare)
|
||||
#
|
||||
# 三种测试场景:
|
||||
# 1. Counter/BitBox: dunder 返回 t.CInt(值类型变量触发重载)
|
||||
# 2. Vec2: dunder 返回 Vec2|t.CPtr(堆分配结构体,指针类型变量触发重载)
|
||||
# 3. 原生整数运算回退
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Counter: 演示 __add__/__mul__/__sub__ + 比较重载
|
||||
# dunder 返回 t.CInt
|
||||
# ============================================================
|
||||
class Counter:
|
||||
val: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.val = v
|
||||
|
||||
def __add__(self, n: t.CInt) -> t.CInt:
|
||||
return self.val + n
|
||||
|
||||
def __sub__(self, n: t.CInt) -> t.CInt:
|
||||
return self.val - n
|
||||
|
||||
def __mul__(self, n: t.CInt) -> t.CInt:
|
||||
return self.val * n
|
||||
|
||||
def __div__(self, n: t.CInt) -> t.CInt:
|
||||
return self.val / n
|
||||
|
||||
def __mod__(self, n: t.CInt) -> t.CInt:
|
||||
return self.val % n
|
||||
|
||||
def __eq__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val == n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __ne__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val != n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __lt__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val < n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __le__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val <= n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __gt__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val > n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __ge__(self, n: t.CInt) -> t.CInt:
|
||||
if self.val >= n:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# BitBox: 演示位运算重载
|
||||
# dunder 返回 t.CInt
|
||||
# ============================================================
|
||||
class BitBox:
|
||||
flags: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.flags = v
|
||||
|
||||
def __and__(self, mask: t.CInt) -> t.CInt:
|
||||
return self.flags & mask
|
||||
|
||||
def __or__(self, mask: t.CInt) -> t.CInt:
|
||||
return self.flags | mask
|
||||
|
||||
def __xor__(self, mask: t.CInt) -> t.CInt:
|
||||
return self.flags ^ mask
|
||||
|
||||
def __lshift__(self, n: t.CInt) -> t.CInt:
|
||||
return self.flags << n
|
||||
|
||||
def __rshift__(self, n: t.CInt) -> t.CInt:
|
||||
return self.flags >> n
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Vec2: 演示结构体运算重载
|
||||
#
|
||||
# __new__ + stdlib.malloc 在堆上分配内存,使 Vec2|t.CPtr 变量
|
||||
# 能正确工作(dunder 方法返回堆上新对象)。
|
||||
#
|
||||
# __new__ 返回 malloc 的堆指针作为结构体存储空间,
|
||||
# 后续 __init__ 在堆指针上初始化字段。
|
||||
# ============================================================
|
||||
class Vec2:
|
||||
x: t.CInt
|
||||
y: t.CInt
|
||||
|
||||
def __new__(self, x0: t.CInt, y0: t.CInt):
|
||||
r: Vec2 | t.CPtr = stdlib.malloc(Vec2.__sizeof__())
|
||||
return r
|
||||
|
||||
def __init__(self, x0: t.CInt, y0: t.CInt):
|
||||
self.x = x0
|
||||
self.y = y0
|
||||
|
||||
def __add__(self, other: Vec2 | t.CPtr) -> Vec2 | t.CPtr:
|
||||
r: Vec2 | t.CPtr = Vec2(0, 0)
|
||||
r.x = self.x + other.x
|
||||
r.y = self.y + other.y
|
||||
return r
|
||||
|
||||
def __sub__(self, other: Vec2 | t.CPtr) -> Vec2 | t.CPtr:
|
||||
r: Vec2 | t.CPtr = Vec2(0, 0)
|
||||
r.x = self.x - other.x
|
||||
r.y = self.y - other.y
|
||||
return r
|
||||
|
||||
def __eq__(self, other: Vec2 | t.CPtr) -> t.CInt:
|
||||
if self.x == other.x:
|
||||
if self.y == other.y:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def __ne__(self, other: Vec2 | t.CPtr) -> t.CInt:
|
||||
if self.x != other.x:
|
||||
return 1
|
||||
if self.y != other.y:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 主测试入口
|
||||
# ============================================================
|
||||
def opovl_test() -> int:
|
||||
testcheck.begin("Operator Overload Tests")
|
||||
|
||||
# ============================================================
|
||||
# 测试 1: Counter + int 触发 __add__
|
||||
# ============================================================
|
||||
testcheck.section("Counter __add__")
|
||||
cnt: Counter = Counter(10)
|
||||
sum_val: int = cnt + 5
|
||||
testcheck.check(sum_val == 15, "cnt(10)+5=15", "cnt+5 expected 15 got ??")
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: Counter - int / * int / / int / % int
|
||||
# ============================================================
|
||||
testcheck.section("Counter __sub__/__mul__/__div__/__mod__")
|
||||
sub_val: int = cnt - 3
|
||||
mul_val: int = cnt * 3
|
||||
div_val: int = cnt / 3
|
||||
mod_val: int = cnt % 3
|
||||
testcheck.check(sub_val == 7, "cnt-3=7", "cnt-3 expected 7")
|
||||
testcheck.check(mul_val == 30, "cnt*3=30", "cnt*3 expected 30")
|
||||
testcheck.check(div_val == 3, "cnt/3=3", "cnt/3 expected 3")
|
||||
testcheck.check(mod_val == 1, "cnt%3=1", "cnt%3 expected 1")
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: Counter 比较重载 (==, !=, <, <=, >, >=)
|
||||
# ============================================================
|
||||
testcheck.section("Counter compare overloads")
|
||||
eq_10: int = cnt == 10
|
||||
ne_10: int = cnt != 10
|
||||
lt_20: int = cnt < 20
|
||||
le_10: int = cnt <= 10
|
||||
gt_5: int = cnt > 5
|
||||
ge_10: int = cnt >= 10
|
||||
testcheck.check(eq_10 == 1, "cnt==10:1", "cnt==10 expected 1")
|
||||
testcheck.check(ne_10 == 0, "cnt!=10:0", "cnt!=10 expected 0")
|
||||
testcheck.check(lt_20 == 1, "cnt<20:1", "cnt<20 expected 1")
|
||||
testcheck.check(le_10 == 1, "cnt<=10:1", "cnt<=10 expected 1")
|
||||
testcheck.check(gt_5 == 1, "cnt>5:1", "cnt>5 expected 1")
|
||||
testcheck.check(ge_10 == 1, "cnt>=10:1", "cnt>=10 expected 1")
|
||||
|
||||
# ============================================================
|
||||
# 测试 4: BitBox 位运算重载
|
||||
# ============================================================
|
||||
testcheck.section("BitBox bitwise overloads")
|
||||
bb: BitBox = BitBox(0xFF)
|
||||
and_val: int = bb & 0x0F
|
||||
or_val: int = bb | 0x100
|
||||
xor_val: int = bb ^ 0x55
|
||||
lsh_val: int = bb << 4
|
||||
rsh_val: int = bb >> 4
|
||||
testcheck.check(and_val == 0x0F, "bb&0x0F=15", "bb&0x0F expected 15")
|
||||
testcheck.check(or_val == 0x1FF, "bb|0x100=511", "bb|0x100 expected 511")
|
||||
testcheck.check(xor_val == 0xAA, "bb^0x55=170", "bb^0x55 expected 170")
|
||||
testcheck.check(lsh_val == 0xFF0, "bb<<4=4080", "bb<<4 expected 4080")
|
||||
testcheck.check(rsh_val == 0x0F, "bb>>4=15", "bb>>4 expected 15")
|
||||
|
||||
# ============================================================
|
||||
# 测试 5: 原生整数运算不受影响(回退路径)
|
||||
# ============================================================
|
||||
testcheck.section("Native int binop")
|
||||
x: int = 7 + 8
|
||||
y: int = 10 - 3
|
||||
z: int = 4 * 5
|
||||
testcheck.check(x == 15, "7+8=15", "7+8 expected 15")
|
||||
testcheck.check(y == 7, "10-3=7", "10-3 expected 7")
|
||||
testcheck.check(z == 20, "4*5=20", "4*5 expected 20")
|
||||
|
||||
# ============================================================
|
||||
# 测试 6: 原生整数比较不受影响
|
||||
# ============================================================
|
||||
testcheck.section("Native int compare")
|
||||
testcheck.check(3 < 5, "3<5", "3<5 broken")
|
||||
testcheck.check(10 == 10, "10==10", "10==10 broken")
|
||||
|
||||
# ============================================================
|
||||
# 测试 7: Vec2 结构体运算重载
|
||||
# ============================================================
|
||||
testcheck.section("Vec2 struct overloads")
|
||||
a: Vec2 | t.CPtr = Vec2(3, 4)
|
||||
b: Vec2 | t.CPtr = Vec2(1, 2)
|
||||
c: Vec2 | t.CPtr = a + b
|
||||
d: Vec2 | t.CPtr = a - b
|
||||
testcheck.check(c.x == 4, "a+b x=4", "a+b x expected 4")
|
||||
testcheck.check(c.y == 6, "a+b y=6", "a+b y expected 6")
|
||||
testcheck.check(d.x == 2, "a-b x=2", "a-b x expected 2")
|
||||
testcheck.check(d.y == 2, "a-b y=2", "a-b y expected 2")
|
||||
|
||||
# ============================================================
|
||||
# 测试 8: Vec2 比较重载
|
||||
# ============================================================
|
||||
testcheck.section("Vec2 compare overloads")
|
||||
p: Vec2 | t.CPtr = Vec2(5, 5)
|
||||
q: Vec2 | t.CPtr = Vec2(5, 5)
|
||||
eq_v: int = p == q
|
||||
ne_v: int = p != q
|
||||
testcheck.check(eq_v == 1, "(5,5)==(5,5):1", "p==q expected 1")
|
||||
testcheck.check(ne_v == 0, "(5,5)!=(5,5):0", "p!=q expected 0")
|
||||
|
||||
return testcheck.end()
|
||||
@@ -1,26 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def ptr_only_test() -> int:
|
||||
s: str = "hello"
|
||||
sp: str = s
|
||||
slen: int = 0
|
||||
while c.Deref(sp) != 0:
|
||||
slen = slen + 1
|
||||
sp = sp + 1
|
||||
stdio.printf("ptr: len(hello)=%d\n", slen)
|
||||
|
||||
x: int = 65
|
||||
px: str = c.Addr(x)
|
||||
c.DerefAs(px, 88)
|
||||
stdio.printf("ptr: after DerefAs x=%d\n", x)
|
||||
|
||||
p2: str = "ABC"
|
||||
total_ch: int = 0
|
||||
while c.Deref(p2) != 0:
|
||||
total_ch = total_ch + c.Deref(p2)
|
||||
p2 = p2 + 1
|
||||
stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch)
|
||||
|
||||
return 0
|
||||
@@ -1,111 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 简单指针 + 逻辑测试
|
||||
# ============================================================
|
||||
|
||||
def ptr_test() -> int:
|
||||
# 逻辑测试:if 语句
|
||||
x: int = 10
|
||||
if x:
|
||||
stdio.printf("if: x is truthy\n")
|
||||
|
||||
if 1 == 1:
|
||||
stdio.printf("if: 1==1 is truthy\n")
|
||||
|
||||
# While 循环 + 累加
|
||||
i: int = 0
|
||||
total: int = 0
|
||||
while i < 5:
|
||||
total = total + i
|
||||
i = i + 1
|
||||
stdio.printf("while: total=%d i=%d\n", total, i)
|
||||
|
||||
# For 循环
|
||||
for j in range(5):
|
||||
stdio.printf("for: j=%d\n", j)
|
||||
|
||||
# Break 测试
|
||||
for k in range(10):
|
||||
if k == 3:
|
||||
break
|
||||
stdio.printf("break: k=%d\n", k)
|
||||
|
||||
# Continue 测试
|
||||
for m in range(5):
|
||||
if m == 2:
|
||||
continue
|
||||
stdio.printf("continue: m=%d\n", m)
|
||||
|
||||
# 布尔运算 and(短路求值)
|
||||
if x > 5 and x < 100:
|
||||
stdio.printf("bool: x>5 and x<100 is true\n")
|
||||
|
||||
# 布尔运算 or(短路求值)
|
||||
if x > 100 or x > 5:
|
||||
stdio.printf("bool: x>100 or x>5 is true\n")
|
||||
|
||||
# ============================================================
|
||||
# 指针 + c.Deref / c.DerefAs 测试
|
||||
# ============================================================
|
||||
|
||||
# 字符串遍历: while c.Deref(p) != 0
|
||||
s: str = "hello"
|
||||
sp: str = s
|
||||
slen: int = 0
|
||||
while c.Deref(sp) != 0:
|
||||
slen = slen + 1
|
||||
sp = sp + 1
|
||||
stdio.printf("ptr: len(hello)=%d\n", slen)
|
||||
|
||||
# c.DerefAs 写入字符(使用 c.Addr 获取栈变量地址,字符串字面量是只读的)
|
||||
v: int = 65 # 'A'
|
||||
px: str = c.Addr(v)
|
||||
c.DerefAs(px, 88) # *px = 88
|
||||
stdio.printf("ptr: after DerefAs v=%d\n", v)
|
||||
|
||||
# 遍历字符串并累加字符值
|
||||
p2: str = "ABC"
|
||||
total_ch: int = 0
|
||||
while c.Deref(p2) != 0:
|
||||
total_ch = total_ch + c.Deref(p2)
|
||||
p2 = p2 + 1
|
||||
stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch)
|
||||
|
||||
# ============================================================
|
||||
# c.Load 测试: *a = *b(加载源指针的值,存储到目标指针)
|
||||
# ============================================================
|
||||
|
||||
# 基本复制: v2 = v1
|
||||
v1: int = 42
|
||||
v2: int = 0
|
||||
c.Load(c.Addr(v2), c.Addr(v1))
|
||||
stdio.printf("ptr: c.Load v2=%d (expected 42)\n", v2)
|
||||
if v2 != 42:
|
||||
stdio.printf("[FAIL] c.Load expected 42 got %d\n", v2)
|
||||
return 1
|
||||
|
||||
# 覆盖已有值: v3 = v4
|
||||
v3: int = 100
|
||||
v4: int = 200
|
||||
c.Load(c.Addr(v3), c.Addr(v4))
|
||||
stdio.printf("ptr: c.Load overwrite v3=%d (expected 200)\n", v3)
|
||||
if v3 != 200:
|
||||
stdio.printf("[FAIL] c.Load overwrite expected 200 got %d\n", v3)
|
||||
return 1
|
||||
|
||||
# 验证源不被修改: v5 保持原值
|
||||
v5: int = 999
|
||||
v6: int = 0
|
||||
c.Load(c.Addr(v6), c.Addr(v5))
|
||||
stdio.printf("ptr: c.Load src unchanged v5=%d v6=%d (expected 999, 999)\n", v5, v6)
|
||||
if v5 != 999:
|
||||
stdio.printf("[FAIL] c.Load src changed v5=%d\n", v5)
|
||||
return 1
|
||||
if v6 != 999:
|
||||
stdio.printf("[FAIL] c.Load dst expected 999 got %d\n", v6)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -1,6 +0,0 @@
|
||||
import stdio
|
||||
|
||||
def simple_test() -> int:
|
||||
stdio.printf("hello\n")
|
||||
return 0
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
|
||||
|
||||
def string_min_test() -> int:
|
||||
l: t.CSizeT = string.strlen("Hello")
|
||||
stdio.printf("strlen(Hello)=%lu\n", l)
|
||||
return 0
|
||||
@@ -1,106 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
|
||||
|
||||
# ============================================================
|
||||
# string_test - string.py 库函数测试
|
||||
#
|
||||
# 测试 strlen / strcmp / strncmp / atoi / strchr / strstr
|
||||
# ============================================================
|
||||
|
||||
|
||||
def test_strlen():
|
||||
stdio.printf("--- Test 1: strlen ---\n")
|
||||
|
||||
l1: t.CSizeT = string.strlen("Hello")
|
||||
stdio.printf("strlen(Hello)=%lu (expect 5)\n", l1)
|
||||
|
||||
l2: t.CSizeT = string.strlen("")
|
||||
stdio.printf("strlen()=%lu (expect 0)\n", l2)
|
||||
|
||||
l3: t.CSizeT = string.strlen("Hello, World!")
|
||||
stdio.printf("strlen(Hello, World!)=%lu (expect 13)\n", l3)
|
||||
|
||||
|
||||
def test_strcmp():
|
||||
stdio.printf("--- Test 2: strcmp ---\n")
|
||||
|
||||
r1: t.CInt = string.strcmp("abc", "abc")
|
||||
stdio.printf("strcmp(abc,abc)=%d (expect 0)\n", r1)
|
||||
|
||||
r2: t.CInt = string.strcmp("abc", "abd")
|
||||
stdio.printf("strcmp(abc,abd)=%d (expect <0)\n", r2)
|
||||
|
||||
r3: t.CInt = string.strcmp("abd", "abc")
|
||||
stdio.printf("strcmp(abd,abc)=%d (expect >0)\n", r3)
|
||||
|
||||
|
||||
def test_strncmp():
|
||||
stdio.printf("--- Test 3: strncmp ---\n")
|
||||
|
||||
r1: t.CInt = string.strncmp("abcdef", "abcXYZ", 3)
|
||||
stdio.printf("strncmp(abcdef,abcXYZ,3)=%d (expect 0)\n", r1)
|
||||
|
||||
r2: t.CInt = string.strncmp("abcdef", "abcXYZ", 4)
|
||||
stdio.printf("strncmp(abcdef,abcXYZ,4)=%d (expect <0)\n", r2)
|
||||
|
||||
|
||||
def test_atoi():
|
||||
stdio.printf("--- Test 4: atoi ---\n")
|
||||
|
||||
n1: t.CInt = string.atoi("123")
|
||||
stdio.printf("atoi(123)=%d (expect 123)\n", n1)
|
||||
|
||||
n2: t.CInt = string.atoi("-456")
|
||||
stdio.printf("atoi(-456)=%d (expect -456)\n", n2)
|
||||
|
||||
n3: t.CInt = string.atoi(" 789")
|
||||
stdio.printf("atoi( 789)=%d (expect 789)\n", n3)
|
||||
|
||||
|
||||
def test_strchr():
|
||||
stdio.printf("--- Test 5: strchr ---\n")
|
||||
|
||||
# strchr 返回指向字符的指针,不为 None 表示找到
|
||||
p: str = string.strchr("Hello", 108) # 'l' = 108
|
||||
if p is not None:
|
||||
stdio.printf("strchr(Hello,'l') found, char=%d (expect 108)\n", c.Deref(p))
|
||||
else:
|
||||
stdio.printf("strchr(Hello,'l') NOT FOUND (FAIL)\n")
|
||||
|
||||
p2: str = string.strchr("Hello", 122) # 'z' = 122
|
||||
if p2 is None:
|
||||
stdio.printf("strchr(Hello,'z') not found OK\n")
|
||||
else:
|
||||
stdio.printf("strchr(Hello,'z') FAIL (should be None)\n")
|
||||
|
||||
|
||||
def test_strstr():
|
||||
stdio.printf("--- Test 6: strstr ---\n")
|
||||
|
||||
p: str = string.strstr("Hello World", "World")
|
||||
if p is not None:
|
||||
stdio.printf("strstr(Hello,World) found OK\n")
|
||||
else:
|
||||
stdio.printf("strstr(Hello,World) NOT FOUND (FAIL)\n")
|
||||
|
||||
p2: str = string.strstr("Hello World", "xyz")
|
||||
if p2 is None:
|
||||
stdio.printf("strstr(Hello,xyz) not found OK\n")
|
||||
else:
|
||||
stdio.printf("strstr(Hello,xyz) FAIL (should be None)\n")
|
||||
|
||||
|
||||
def string_test() -> int:
|
||||
stdio.printf("=== string_test: string.py 库函数测试 ===\n\n")
|
||||
|
||||
test_strlen()
|
||||
test_strcmp()
|
||||
test_strncmp()
|
||||
test_atoi()
|
||||
test_strchr()
|
||||
test_strstr()
|
||||
|
||||
stdio.printf("\n=== string_test 完成 ===\n")
|
||||
return 0
|
||||
@@ -1,235 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 纯内存结构体(class)测试
|
||||
# ============================================================
|
||||
|
||||
class Point:
|
||||
x: t.CInt
|
||||
y: t.CInt
|
||||
|
||||
|
||||
class Box:
|
||||
width: t.CInt
|
||||
height: t.CInt
|
||||
depth: t.CInt
|
||||
|
||||
|
||||
class Size:
|
||||
w: t.CInt = 100
|
||||
h: t.CInt = 200
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 枚举(t.CEnum)测试
|
||||
# ============================================================
|
||||
|
||||
class State(t.CEnum):
|
||||
Idle: t.State
|
||||
Run: t.State
|
||||
Stop: t.State
|
||||
|
||||
|
||||
class Color(t.CEnum):
|
||||
Red: t.State = 10
|
||||
Green: t.State
|
||||
Blue: t.State = 20
|
||||
Yellow: t.State
|
||||
|
||||
|
||||
class MixedType(t.CEnum):
|
||||
Small: t.CInt8T
|
||||
Big: t.CInt64T
|
||||
Medium: t.CInt16T
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 联合体(t.CUnion)测试
|
||||
# ============================================================
|
||||
|
||||
class DataUnion(t.CUnion):
|
||||
i: t.CInt
|
||||
f: t.CFloat
|
||||
l: t.CInt64T
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 主函数
|
||||
# ============================================================
|
||||
def struct_test() -> int:
|
||||
# ============================================================
|
||||
# 测试 1: 结构体字段读写
|
||||
# ============================================================
|
||||
p: Point = Point()
|
||||
p.x = 10
|
||||
p.y = 20
|
||||
stdio.printf("struct: p.x=%d p.y=%d\n", p.x, p.y)
|
||||
|
||||
# 修改字段
|
||||
p.x = 100
|
||||
p.y = 200
|
||||
stdio.printf("struct: modified p.x=%d p.y=%d\n", p.x, p.y)
|
||||
|
||||
# 字段运算
|
||||
sum_xy: int = p.x + p.y
|
||||
stdio.printf("struct: sum=%d\n", sum_xy)
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 多字段结构体
|
||||
# ============================================================
|
||||
b: Box
|
||||
b.width = 3
|
||||
b.height = 4
|
||||
b.depth = 5
|
||||
vol: int = b.width * b.height * b.depth
|
||||
stdio.printf("struct: volume=%d\n", vol)
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: t.CArray 数组遍历
|
||||
# ============================================================
|
||||
arr: t.CArray[t.CInt, 5]
|
||||
arr[0] = 100
|
||||
arr[1] = 200
|
||||
arr[2] = 300
|
||||
arr[3] = 400
|
||||
arr[4] = 500
|
||||
|
||||
arr_total: int = 0
|
||||
for i in range(5):
|
||||
arr_total = arr_total + arr[i]
|
||||
stdio.printf("array: total=%d\n", arr_total)
|
||||
|
||||
# 修改数组元素
|
||||
arr[2] = 999
|
||||
stdio.printf("array: arr[2]=%d\n", arr[2])
|
||||
|
||||
# ============================================================
|
||||
# 测试 4: 指针遍历(字符串)
|
||||
# ============================================================
|
||||
s: str = "hello"
|
||||
sp: str = s
|
||||
slen: int = 0
|
||||
while c.Deref(sp) != 0:
|
||||
slen = slen + 1
|
||||
sp = sp + 1
|
||||
stdio.printf("ptr: len(hello)=%d\n", slen)
|
||||
|
||||
# 累加字符值
|
||||
p2: str = "ABC"
|
||||
total_ch: int = 0
|
||||
while c.Deref(p2) != 0:
|
||||
total_ch = total_ch + c.Deref(p2)
|
||||
p2 = p2 + 1
|
||||
stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch)
|
||||
|
||||
# ============================================================
|
||||
# 测试 5: 结构体构造函数 Point() / Point(x, y)
|
||||
# ============================================================
|
||||
# 无参数构造:零初始化
|
||||
z: Point = Point()
|
||||
stdio.printf("ctor: z.x=%d z.y=%d\n", z.x, z.y)
|
||||
|
||||
# 带参数构造:按位置赋值
|
||||
p3: Point = Point(7, 8)
|
||||
stdio.printf("ctor: p3.x=%d p3.y=%d\n", p3.x, p3.y)
|
||||
|
||||
# 多字段构造
|
||||
bx: Box = Box(10, 20, 30)
|
||||
stdio.printf("ctor: bx.w=%d bx.h=%d bx.d=%d\n", bx.width, bx.height, bx.depth)
|
||||
|
||||
# ============================================================
|
||||
# 测试 6: 结构体关键字参数(乱序传参)
|
||||
# ============================================================
|
||||
# 全关键字乱序
|
||||
p4: Point = Point(y=20, x=10)
|
||||
stdio.printf("kw: p4.x=%d p4.y=%d\n", p4.x, p4.y)
|
||||
|
||||
# 混合:位置 + 关键字
|
||||
p5: Point = Point(5, y=15)
|
||||
stdio.printf("kw: p5.x=%d p5.y=%d\n", p5.x, p5.y)
|
||||
|
||||
# 多字段关键字乱序
|
||||
bx2: Box = Box(depth=30, width=10, height=20)
|
||||
stdio.printf("kw: bx2.w=%d bx2.h=%d bx2.d=%d\n", bx2.width, bx2.height, bx2.depth)
|
||||
|
||||
# ============================================================
|
||||
# 测试 7: 结构体默认赋值
|
||||
# ============================================================
|
||||
# 无参数构造:使用默认值
|
||||
sz: Size = Size()
|
||||
stdio.printf("def: sz.w=%d sz.h=%d\n", sz.w, sz.h)
|
||||
|
||||
# 位置参数覆盖默认值
|
||||
sz2: Size = Size(5, 6)
|
||||
stdio.printf("def: sz2.w=%d sz2.h=%d\n", sz2.w, sz2.h)
|
||||
|
||||
# 关键字参数覆盖默认值(乱序)
|
||||
sz3: Size = Size(h=999, w=888)
|
||||
stdio.printf("def: sz3.w=%d sz3.h=%d\n", sz3.w, sz3.h)
|
||||
|
||||
# 混合:位置参数 + 默认值(w=7 覆盖默认值,h 保持默认值 200)
|
||||
sz4: Size = Size(7)
|
||||
stdio.printf("def: sz4.w=%d sz4.h=%d\n", sz4.w, sz4.h)
|
||||
|
||||
# ============================================================
|
||||
# 测试 8: 枚举自动赋值(Idle=0, Run=1, Stop=2)
|
||||
# ============================================================
|
||||
s_idle: int = State.Idle
|
||||
s_run: int = State.Run
|
||||
s_stop: int = State.Stop
|
||||
stdio.printf("enum: Idle=%d Run=%d Stop=%d\n", s_idle, s_run, s_stop)
|
||||
|
||||
# ============================================================
|
||||
# 测试 9: 枚举手动赋值(Red=10, Green=11, Blue=20, Yellow=21)
|
||||
# ============================================================
|
||||
c_red: int = Color.Red
|
||||
c_green: int = Color.Green
|
||||
c_blue: int = Color.Blue
|
||||
c_yellow: int = Color.Yellow
|
||||
stdio.printf("enum: Red=%d Green=%d Blue=%d Yellow=%d\n",
|
||||
c_red, c_green, c_blue, c_yellow)
|
||||
|
||||
# ============================================================
|
||||
# 测试 10: 枚举混用数字类型(基准类型应为 i64)
|
||||
# ============================================================
|
||||
m_small: int = MixedType.Small
|
||||
m_big: int = MixedType.Big
|
||||
m_medium: int = MixedType.Medium
|
||||
stdio.printf("enum: Small=%d Big=%d Medium=%d\n", m_small, m_big, m_medium)
|
||||
|
||||
# 枚举参与运算
|
||||
s_sum: int = State.Idle + State.Run + State.Stop
|
||||
stdio.printf("enum: sum(Idle,Run,Stop)=%d\n", s_sum)
|
||||
|
||||
# 枚举比较
|
||||
if State.Idle == 0:
|
||||
stdio.printf("enum: Idle==0 true\n")
|
||||
if Color.Red == 10:
|
||||
stdio.printf("enum: Red==10 true\n")
|
||||
if State.Run != State.Stop:
|
||||
stdio.printf("enum: Run!=Stop true\n")
|
||||
|
||||
# ============================================================
|
||||
# 测试 11: 联合体字段读写
|
||||
# ============================================================
|
||||
u: DataUnion
|
||||
u.i = 42
|
||||
stdio.printf("union: u.i=%d\n", u.i)
|
||||
|
||||
# 写入 l 字段(覆盖 i 的内存,因为 l 是 i64)
|
||||
u.l = 20015998343868
|
||||
stdio.printf("union: u.l=%lld\n", u.l)
|
||||
|
||||
# ============================================================
|
||||
# 测试 12: 联合体共享内存验证
|
||||
# ============================================================
|
||||
u2: DataUnion
|
||||
u2.i = 1
|
||||
# 写入 l 后,i 的值已被覆盖(不再是 1)
|
||||
u2.l = 100
|
||||
if u2.i != 1:
|
||||
stdio.printf("union: shared memory verified\n")
|
||||
|
||||
return 0
|
||||
@@ -1,113 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import testcheck
|
||||
from stdint import *
|
||||
from asm_test import asm_test
|
||||
from attr_test import attr_test
|
||||
from augassign_test import augassign_test
|
||||
from closure_test import closure_test
|
||||
from deco_test import deco_test
|
||||
from deref_min_test import deref_min_test
|
||||
from deref_test import deref_test
|
||||
from eq_test import eq_test
|
||||
from float_test import float_test
|
||||
from flow_test import flow_test
|
||||
from for_test import for_test
|
||||
from func_test import func_test
|
||||
from llvmir_test import llvmir_test
|
||||
from oop_test import oop_test
|
||||
from ptr_only_test import ptr_only_test
|
||||
from ptr_test import ptr_test
|
||||
from simple_test import simple_test
|
||||
from string_min_test import string_min_test
|
||||
from string_test import string_test
|
||||
from struct_test import struct_test
|
||||
from type_bit_test import type_bit_test
|
||||
from vtable_test import vtable_test
|
||||
from inherit_test import inherit_test
|
||||
from func_vtable_test import func_vtable_test
|
||||
from virtual_dispatch_test import virtual_dispatch_test
|
||||
from new_test import new_test
|
||||
from namespace_test import namespace_test
|
||||
from testcheck_test import testcheck_test
|
||||
from opovl_test import opovl_test
|
||||
from circ_test import circ_test
|
||||
# from generic_test import generic_test # 屏蔽泛型模块(GenericTest 运行时崩溃,待修复)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
stdio.printf("===== TransPyV Test Suite =====\n\n")
|
||||
|
||||
r: int = 0
|
||||
|
||||
stdio.fflush(None)
|
||||
r = asm_test()
|
||||
stdio.fflush(None)
|
||||
r = attr_test()
|
||||
stdio.fflush(None)
|
||||
r = augassign_test()
|
||||
stdio.fflush(None)
|
||||
r = closure_test()
|
||||
stdio.fflush(None)
|
||||
r = deco_test()
|
||||
stdio.fflush(None)
|
||||
r = deref_min_test()
|
||||
stdio.fflush(None)
|
||||
r = deref_test()
|
||||
stdio.fflush(None)
|
||||
r = eq_test()
|
||||
stdio.fflush(None)
|
||||
r = float_test()
|
||||
stdio.fflush(None)
|
||||
r = flow_test()
|
||||
stdio.fflush(None)
|
||||
r = for_test()
|
||||
stdio.fflush(None)
|
||||
r = func_test()
|
||||
stdio.fflush(None)
|
||||
r = llvmir_test()
|
||||
stdio.fflush(None)
|
||||
r = oop_test()
|
||||
stdio.fflush(None)
|
||||
r = ptr_only_test()
|
||||
stdio.fflush(None)
|
||||
r = ptr_test()
|
||||
stdio.fflush(None)
|
||||
r = simple_test()
|
||||
stdio.fflush(None)
|
||||
r = string_min_test()
|
||||
stdio.fflush(None)
|
||||
r = string_test()
|
||||
stdio.fflush(None)
|
||||
r = struct_test()
|
||||
stdio.fflush(None)
|
||||
r = type_bit_test()
|
||||
stdio.fflush(None)
|
||||
r = vtable_test()
|
||||
stdio.fflush(None)
|
||||
r = inherit_test()
|
||||
stdio.fflush(None)
|
||||
r = func_vtable_test()
|
||||
stdio.fflush(None)
|
||||
r = virtual_dispatch_test()
|
||||
stdio.fflush(None)
|
||||
r = new_test()
|
||||
stdio.fflush(None)
|
||||
r = namespace_test()
|
||||
stdio.fflush(None)
|
||||
r = testcheck_test()
|
||||
stdio.fflush(None)
|
||||
r = opovl_test()
|
||||
stdio.fflush(None)
|
||||
r = circ_test()
|
||||
stdio.fflush(None)
|
||||
|
||||
# 屏蔽泛型模块(GenericTest 运行时崩溃,待修复)
|
||||
# stdio.printf("[TM] before generic_test\n")
|
||||
# stdio.fflush(None)
|
||||
# r = generic_test()
|
||||
# stdio.printf("[TM] after generic_test r=%d\n", r)
|
||||
# stdio.fflush(None)
|
||||
|
||||
stdio.printf("\n===== Test Suite Complete =====\n")
|
||||
return r
|
||||
@@ -1,37 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
import testcheck
|
||||
|
||||
|
||||
# ============================================================
|
||||
# testcheck_test - 测试 includes/testcheck 库导入与调用
|
||||
#
|
||||
# 验证命名空间隔离下,import testcheck + 模块限定函数调用能正常工作。
|
||||
# 同时测试 string 库的模块限定调用。
|
||||
# ============================================================
|
||||
def testcheck_test() -> int:
|
||||
testcheck.begin("testcheck_test")
|
||||
|
||||
testcheck.section("Arithmetic")
|
||||
a: int = 3 + 4
|
||||
testcheck.check(a == 7, "3+4=7", "3+4!=7")
|
||||
|
||||
b: int = 10 - 3
|
||||
testcheck.check(b == 7, "10-3=7", "10-3!=7")
|
||||
|
||||
m: int = 6 * 7
|
||||
testcheck.check(m == 42, "6*7=42", "6*7!=42")
|
||||
|
||||
testcheck.section("String")
|
||||
slen: int = string.strlen("hello")
|
||||
testcheck.check(slen == 5, "strlen(hello)=5", "strlen(hello)!=5")
|
||||
|
||||
scmp: int = string.strcmp("abc", "abc")
|
||||
testcheck.check(scmp == 0, "strcmp(abc,abc)=0", "strcmp(abc,abc)!=0")
|
||||
|
||||
testcheck.section("Module Import")
|
||||
testcheck.info("testcheck module imported and called successfully")
|
||||
testcheck.ok("import testcheck works")
|
||||
|
||||
return testcheck.end()
|
||||
@@ -1,26 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
def type_bit_test() -> int:
|
||||
ti: t.CInt = 100
|
||||
ti32: t.CInt32T = 200
|
||||
tui32: t.CUInt32T = 300
|
||||
stdio.printf("type: CInt=%d CInt32T=%d CUInt32T=%d\n", ti, ti32, tui32)
|
||||
|
||||
tl: t.CLong = 1000
|
||||
tll: t.CLongLong = 2000
|
||||
ti64: t.CInt64T = 3000
|
||||
tsize: t.CSizeT = 4000
|
||||
stdio.printf("type: CLong=%d CLongLong=%d CInt64T=%d CSizeT=%d\n", tl, tll, ti64, tsize)
|
||||
|
||||
ba: int = 240
|
||||
bb: int = 15
|
||||
stdio.printf("bit: 240&15=%d\n", ba & bb)
|
||||
stdio.printf("bit: 240|15=%d\n", ba | bb)
|
||||
stdio.printf("bit: 240^15=%d\n", ba ^ bb)
|
||||
stdio.printf("bit: 240<<2=%d\n", ba << 2)
|
||||
stdio.printf("bit: 240>>2=%d\n", ba >> 2)
|
||||
stdio.printf("bit: 17%%5=%d\n", 17 % 5)
|
||||
|
||||
return 0
|
||||
@@ -1,83 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
import string
|
||||
from inherit_test import Animal, Dog
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 虚分派测试:通过虚表指针验证虚分派机制
|
||||
#
|
||||
# 本测试验证:方法调用通过对象的 __vtable__ 字段进行虚分派,
|
||||
# 而非通过变量声明类型直接调用。
|
||||
#
|
||||
# 测试方法:
|
||||
# 1. 创建 Animal 对象 a(Animal 虚表,Speak 返回 0)
|
||||
# 2. 创建 Dog 对象 d
|
||||
# 3. 用内联汇编将 d 的虚表指针复制到 a
|
||||
# 4. 调用 a.Speak() — 应返回 1(Dog.Speak),证明虚分派生效
|
||||
#
|
||||
# 如果是直接调用(非虚分派),a.Speak() 会调用 Animal.Speak 返回 0
|
||||
#
|
||||
# 注意:Animal 和 Dog 类从 inherit_test.py 导入(命名空间隔离)
|
||||
# ============================================================
|
||||
|
||||
|
||||
def virtual_dispatch_test() -> int:
|
||||
stdio.printf("vdispatch: === Test Start ===\n")
|
||||
|
||||
# 创建对象
|
||||
a: Animal = Animal(42)
|
||||
d: Dog = Dog(100, 7)
|
||||
|
||||
# ============================================================
|
||||
# 测试 1: 直接分派(基线验证)
|
||||
# ============================================================
|
||||
stdio.printf("vdispatch: === Test 1: Direct Dispatch ===\n")
|
||||
|
||||
a_speak: int = a.Speak()
|
||||
stdio.printf("vdispatch: a.Speak()=%d (expected 0)\n", a_speak)
|
||||
if a_speak != 0:
|
||||
stdio.printf("[FAIL] a.Speak()=%d expected 0\n", a_speak)
|
||||
return 1
|
||||
|
||||
d_speak: int = d.Speak()
|
||||
stdio.printf("vdispatch: d.Speak()=%d (expected 1)\n", d_speak)
|
||||
if d_speak != 1:
|
||||
stdio.printf("[FAIL] d.Speak()=%d expected 1\n", d_speak)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 2: 虚分派验证(复制虚表指针)
|
||||
#
|
||||
# 将 Dog 的虚表指针复制到 Animal 对象 a
|
||||
# 虚表指针位于结构体偏移 0(__vtable__ 字段)
|
||||
# 复制后 a.Speak() 应通过虚表分发到 Dog.Speak(返回 1)
|
||||
# ============================================================
|
||||
stdio.printf("vdispatch: === Test 2: Virtual Dispatch ===\n")
|
||||
|
||||
# 使用 string.memcpy 复制虚表指针(8字节,结构体偏移0)
|
||||
# 将 d 的虚表指针复制到 a,使 a.Speak() 分发到 Dog.Speak
|
||||
string.memcpy(c.Addr(a), c.Addr(d), 8)
|
||||
|
||||
a_speak2: int = a.Speak()
|
||||
stdio.printf("vdispatch: a.Speak()=%d (expected 1 after vtable copy)\n", a_speak2)
|
||||
if a_speak2 != 1:
|
||||
stdio.printf("[FAIL] a.Speak()=%d expected 1 after vtable copy\n", a_speak2)
|
||||
return 1
|
||||
|
||||
# ============================================================
|
||||
# 测试 3: GetName 验证(未被覆盖的虚方法)
|
||||
#
|
||||
# Dog 没有覆盖 GetName,Dog 虚表中 GetName 槽位指向 Animal.GetName
|
||||
# a.GetName() 应返回 a.name (42),证明虚表槽位一致性
|
||||
# ============================================================
|
||||
stdio.printf("vdispatch: === Test 3: GetName After VTable Copy ===\n")
|
||||
|
||||
a_name: int = a.GetName()
|
||||
stdio.printf("vdispatch: a.GetName()=%d (expected 42)\n", a_name)
|
||||
if a_name != 42:
|
||||
stdio.printf("[FAIL] a.GetName()=%d expected 42\n", a_name)
|
||||
return 1
|
||||
|
||||
stdio.printf("vdispatch: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,63 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
@t.CVTable
|
||||
class Animal:
|
||||
name: t.CInt
|
||||
|
||||
def __init__(self, n: t.CInt):
|
||||
self.name = n
|
||||
|
||||
def GetName(self) -> t.CInt:
|
||||
return self.name
|
||||
|
||||
def Speak(self) -> t.CInt:
|
||||
return 0
|
||||
|
||||
|
||||
@t.CVTable
|
||||
class Shape:
|
||||
sides: t.CInt
|
||||
|
||||
def SetSides(self, n: t.CInt) -> t.CInt:
|
||||
self.sides = n
|
||||
return 0
|
||||
|
||||
def GetSides(self) -> t.CInt:
|
||||
return self.sides
|
||||
|
||||
|
||||
def vtable_test() -> int:
|
||||
stdio.printf("vtable: === Test Start ===\n")
|
||||
|
||||
# 测试 1: Animal 虚方法调用(无参,访问 self 字段)
|
||||
a: Animal = Animal(42)
|
||||
name: int = a.GetName()
|
||||
stdio.printf("vtable: a.GetName()=%d (expected 42)\n", name)
|
||||
if name != 42:
|
||||
stdio.printf("[FAIL] a.GetName()=%d expected 42\n", name)
|
||||
return 1
|
||||
|
||||
speak: int = a.Speak()
|
||||
stdio.printf("vtable: a.Speak()=%d (expected 0)\n", speak)
|
||||
if speak != 0:
|
||||
stdio.printf("[FAIL] a.Speak()=%d expected 0\n", speak)
|
||||
return 1
|
||||
|
||||
# 测试 2: Shape 虚方法调用(带参,修改 self 字段)
|
||||
s: Shape = Shape()
|
||||
r: int = s.SetSides(4)
|
||||
stdio.printf("vtable: s.SetSides(4)=%d (expected 0)\n", r)
|
||||
if r != 0:
|
||||
stdio.printf("[FAIL] s.SetSides(4)=%d expected 0\n", r)
|
||||
return 1
|
||||
|
||||
sides: int = s.GetSides()
|
||||
stdio.printf("vtable: s.GetSides()=%d (expected 4)\n", sides)
|
||||
if sides != 4:
|
||||
stdio.printf("[FAIL] s.GetSides()=%d expected 4\n", sides)
|
||||
return 1
|
||||
|
||||
stdio.printf("vtable: === All Tests Passed ===\n")
|
||||
return 0
|
||||
@@ -1,20 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 负向测试定义模块:定义 SecretClass
|
||||
#
|
||||
# 此文件定义 SecretClass,但 main.py 不 import 它。
|
||||
# 严格模式下 main.py 中的 SecretClass() 构造应编译失败。
|
||||
# ============================================================
|
||||
|
||||
|
||||
class SecretClass:
|
||||
val: t.CInt
|
||||
|
||||
def __init__(self, v: t.CInt):
|
||||
self.val = v
|
||||
|
||||
def GetVal(self) -> t.CInt:
|
||||
return self.val
|
||||
@@ -1,21 +0,0 @@
|
||||
import stdio
|
||||
import t, c
|
||||
# 故意不 import defs.SecretClass — 严格模式下应编译失败
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 负向测试主入口
|
||||
#
|
||||
# 此文件故意不 import SecretClass,但尝试使用 SecretClass()。
|
||||
# 命名空间隔离严格模式下,SecretClass 不可见,
|
||||
# 构造器路径被跳过,生成 call i32 @SecretClass(...),
|
||||
# llc 报错 "use of undefined value '@SecretClass'"。
|
||||
#
|
||||
# 预期:TransPyV 编译失败(exit code != 0)
|
||||
# ============================================================
|
||||
def main() -> int:
|
||||
# SecretClass 未导入,严格模式下不可见
|
||||
s: SecretClass = SecretClass(42)
|
||||
v: int = s.GetVal()
|
||||
stdio.printf("negtest: v=%d (should not reach here)\n", v)
|
||||
return 0
|
||||
@@ -1,62 +0,0 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import stdlib
|
||||
import memhub
|
||||
import hashlib
|
||||
|
||||
|
||||
POOL_SIZE: t.CDefine = 16777480
|
||||
|
||||
|
||||
@t.CExport
|
||||
def main() -> int:
|
||||
arena: bytes = stdlib.malloc(POOL_SIZE)
|
||||
if arena is None:
|
||||
return 1
|
||||
mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE)
|
||||
if mb is None:
|
||||
return 1
|
||||
hashlib._mbuddy = (memhub.MemManager | t.CPtr)(mb)
|
||||
|
||||
# 测试 "abc" 的 SHA1
|
||||
# 期望: a9993e364706816aba3e25717850c26c9cd0d89d
|
||||
s: str = "abc"
|
||||
stdio.printf("input: %s\n", s)
|
||||
|
||||
# 计算 len(s)
|
||||
n: t.CSizeT = len(s)
|
||||
stdio.printf("len=%d\n", n)
|
||||
|
||||
# 构造 sha1 对象
|
||||
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
|
||||
if ctx is None:
|
||||
stdio.printf("ctx is None\n")
|
||||
return 1
|
||||
|
||||
ctx.update(s)
|
||||
|
||||
digest: bytes = mb.alloc(hashlib.SHA1_DIGEST_LEN)
|
||||
if digest is None:
|
||||
stdio.printf("digest alloc failed\n")
|
||||
return 1
|
||||
|
||||
ctx.final(digest)
|
||||
|
||||
# 打印 digest(十六进制)
|
||||
stdio.printf("SHA1: ")
|
||||
for i in range(hashlib.SHA1_DIGEST_LEN):
|
||||
b: t.CUInt8T = digest[i]
|
||||
hi: t.CInt = (b >> 4) & 0xF
|
||||
lo: t.CInt = b & 0xF
|
||||
if hi < 10:
|
||||
stdio.printf("%c", '0' + hi)
|
||||
else:
|
||||
stdio.printf("%c", 'a' + (hi - 10))
|
||||
if lo < 10:
|
||||
stdio.printf("%c", '0' + lo)
|
||||
else:
|
||||
stdio.printf("%c", 'a' + (lo - 10))
|
||||
stdio.printf("\n")
|
||||
stdio.printf("expect: a9993e364706816aba3e25717850c26c9cd0d89d\n")
|
||||
return 0
|
||||
@@ -1 +0,0 @@
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "fLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdinLine truncated
|
||||
@@ -1 +1 @@
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": Line truncated
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "main": "484879ffecdf2b08", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "lib.core.Handles.HandlesReturn": "4c644ade1f0d6d02", "HandlesReturn": "4c644ade1f0d6d02", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "_list": "7cadfe07e983fd90", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "lib.core.IncludesScanner": "8d6185cf886c0334", "IncludesScanner": "8d6185cf886c0334", "lib.core.Handles.HandlesWhile": "8dc65d4c71e2936a", "HandlesWhile": "8dc65d4c71e2936a", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "lib.core.StubMerger": "9dbc46e5249ed198", "StubMerger": "9dbc46e5249ed198", "subprocess": "a335eb99f2e34479", "lib.core.BuildPipeline": "a38b726f4a82545f", "BuildPipeline": "a38b726f4a82545f", "linkedlist": "a5e9a83e9db303ad", "atom": "aa246c6e6aa30484", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.Handles.HandlesExpr": "bde6b4cc0847ee6d", "HandlesExpr": "bde6b4cc0847ee6d", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "lib.core.Phase2": "c1bb03b1eae141e0", "Phase2": "c1bb03b1eae141e0", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.Handles.HandlesExprCall": "efefa18c5d6c2d81", "HandlesExprCall": "efefa18c5d6c2d81", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "lib.core.Handles.HandlesIf": "f4cdbca2f8802c12", "HandlesIf": "f4cdbca2f8802c12", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file":Line truncated
|
||||
@@ -1 +1 @@
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "f552257Line truncated
|
||||
{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "main": "484879ffecdf2b08", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "lib.core.Handles.HandlesReturn": "4c644ade1f0d6d02", "HandlesReturn": "4c644ade1f0d6d02", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "lib.core.IncludesScanner": "8d6185cf886c0334", "IncludesScanner": "8d6185cf886c0334", "lib.core.Handles.HandlesWhile": "8dc65d4c71e2936a", "HandlesWhile": "8dc65d4c71e2936a", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "lib.core.StubMerger": "9dbc46e5249ed198", "StubMerger": "9dbc46e5249ed198", "subprocess": "a335eb99f2e34479", "lib.core.BuildPipeline": "a38b726f4a82545f", "BuildPipeline": "a38b726f4a82545f", "linkedlist": "a5e9a83e9db303ad", "atom": "aa246c6e6aa30484", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.Handles.HandlesExpr": "bde6b4cc0847ee6d", "HandlesExpr": "bde6b4cc0847ee6d", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "lib.core.Phase2": "c1bb03b1eae141e0", "Phase2": "c1bb03b1eae141e0", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.Handles.HandlesExprCall": "efefa18c5d6c2d81", "HandlesExprCall": "efefa18c5d6c2d81", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "lib.core.Handles.HandlesIf": "f4cdbca2f8802c12", "HandlesIf": "f4cdbca2f8802c12", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b518Line truncated
|
||||
@@ -22,7 +22,7 @@
|
||||
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
},
|
||||
"options": {
|
||||
"slice_level": 3,
|
||||
"slice_level": 3,
|
||||
"sha1_slice_level": 1,
|
||||
"target": "llvm",
|
||||
"strict_mode": true
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from w32.win32process.py
|
||||
Module: w32.win32process
|
||||
"""
|
||||
|
||||
import c
|
||||
|
||||
|
||||
import t
|
||||
from stdint import *
|
||||
from w32.win32base import *
|
||||
|
||||
PROCESS_TERMINATE: t.CDefine = 0x0001
|
||||
PROCESS_CREATE_THREAD: t.CDefine = 0x0002
|
||||
PROCESS_VM_OPERATION: t.CDefine = 0x0008
|
||||
PROCESS_VM_READ: t.CDefine = 0x0010
|
||||
PROCESS_VM_WRITE: t.CDefine = 0x0020
|
||||
PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400
|
||||
PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF
|
||||
THREAD_TERMINATE: t.CDefine = 0x0001
|
||||
THREAD_SUSPEND_RESUME: t.CDefine = 0x0002
|
||||
THREAD_GET_CONTEXT: t.CDefine = 0x0008
|
||||
THREAD_SET_CONTEXT: t.CDefine = 0x0010
|
||||
THREAD_QUERY_INFORMATION: t.CDefine = 0x0040
|
||||
THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF
|
||||
CREATE_SUSPENDED: t.CDefine = 0x00000004
|
||||
CREATE_NEW_CONSOLE: t.CDefine = 0x00000010
|
||||
CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200
|
||||
CREATE_NO_WINDOW: t.CDefine = 0x08000000
|
||||
DETACHED_PROCESS: t.CDefine = 0x00000008
|
||||
STARTF_USESHOWWINDOW: t.CDefine = 0x00000001
|
||||
STARTF_USESTDHANDLES: t.CDefine = 0x00000100
|
||||
SW_HIDE: t.CDefine = 0
|
||||
SW_SHOW: t.CDefine = 5
|
||||
SW_MINIMIZE: t.CDefine = 6
|
||||
NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020
|
||||
IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040
|
||||
HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080
|
||||
REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100
|
||||
BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000
|
||||
ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000
|
||||
STILL_ACTIVE: t.CDefine = 259
|
||||
|
||||
class STARTUPINFOA:
|
||||
cb: ULONG
|
||||
lpReserved: CHARPTR
|
||||
lpDesktop: CHARPTR
|
||||
lpTitle: CHARPTR
|
||||
dwX: ULONG
|
||||
dwY: ULONG
|
||||
dwXSize: ULONG
|
||||
dwYSize: ULONG
|
||||
dwXCountChars: ULONG
|
||||
dwYCountChars: ULONG
|
||||
dwFillAttribute: ULONG
|
||||
dwFlags: ULONG
|
||||
wShowWindow: WORD
|
||||
cbReserved2: WORD
|
||||
lpReserved2: VOIDPTR
|
||||
hStdInput: HANDLE
|
||||
hStdOutput: HANDLE
|
||||
hStdError: HANDLE
|
||||
class STARTUPINFOW:
|
||||
cb: ULONG
|
||||
lpReserved: WCHARPTR
|
||||
lpDesktop: WCHARPTR
|
||||
lpTitle: WCHARPTR
|
||||
dwX: ULONG
|
||||
dwY: ULONG
|
||||
dwXSize: ULONG
|
||||
dwYSize: ULONG
|
||||
dwXCountChars: ULONG
|
||||
dwYCountChars: ULONG
|
||||
dwFillAttribute: ULONG
|
||||
dwFlags: ULONG
|
||||
wShowWindow: WORD
|
||||
cbReserved2: WORD
|
||||
lpReserved2: VOIDPTR
|
||||
hStdInput: HANDLE
|
||||
hStdOutput: HANDLE
|
||||
hStdError: HANDLE
|
||||
class PROCESS_INFORMATION:
|
||||
hProcess: HANDLE
|
||||
hThread: HANDLE
|
||||
dwProcessId: ULONG
|
||||
dwThreadId: ULONG
|
||||
|
||||
def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass
|
||||
|
||||
def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass
|
||||
|
||||
def GetCurrentProcess() -> HANDLE | t.State: pass
|
||||
|
||||
def GetCurrentProcessId() -> ULONG | t.State: pass
|
||||
|
||||
def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass
|
||||
|
||||
def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass
|
||||
|
||||
def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass
|
||||
|
||||
def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def GetCurrentThread() -> HANDLE | t.State: pass
|
||||
|
||||
def GetCurrentThreadId() -> ULONG | t.State: pass
|
||||
|
||||
def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass
|
||||
|
||||
def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass
|
||||
|
||||
def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass
|
||||
|
||||
def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass
|
||||
|
||||
def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass
|
||||
|
||||
def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass
|
||||
|
||||
def TlsAlloc() -> ULONG | t.State: pass
|
||||
|
||||
def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass
|
||||
|
||||
def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass
|
||||
@@ -1,109 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from w32.win32sync.py
|
||||
Module: w32.win32sync
|
||||
"""
|
||||
|
||||
import c
|
||||
|
||||
|
||||
import t
|
||||
from stdint import *
|
||||
from w32.win32base import *
|
||||
|
||||
class CRITICAL_SECTION:
|
||||
DebugInfo: VOIDPTR
|
||||
LockCount: LONG
|
||||
RecursionCount: LONG
|
||||
OwningThread: HANDLE
|
||||
LockSemaphore: HANDLE
|
||||
SpinCount: QWORD
|
||||
|
||||
def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
|
||||
|
||||
def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
|
||||
|
||||
def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
|
||||
|
||||
def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
|
||||
|
||||
def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass
|
||||
|
||||
def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass
|
||||
|
||||
def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass
|
||||
|
||||
def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass
|
||||
|
||||
def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass
|
||||
|
||||
def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
|
||||
|
||||
def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass
|
||||
|
||||
def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass
|
||||
|
||||
def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass
|
||||
|
||||
def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass
|
||||
|
||||
def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
|
||||
CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1
|
||||
|
||||
def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
|
||||
|
||||
|
||||
INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001
|
||||
INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002
|
||||
INIT_ONCE_ASYNC: t.CDefine = 0x00000004
|
||||
INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008
|
||||
|
||||
class INIT_ONCE:
|
||||
Ptr: t.CPtr
|
||||
|
||||
def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass
|
||||
@@ -1,30 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from hashlib.__sha1.py
|
||||
Module: hashlib.__sha1
|
||||
"""
|
||||
|
||||
|
||||
import string
|
||||
import t, c
|
||||
|
||||
SHA1_BLOCK_LEN: t.CDefine = 64
|
||||
SHA1_DIGEST_LEN: t.CDefine = 20
|
||||
|
||||
def sha1_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: pass
|
||||
|
||||
def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
|
||||
@t.Object
|
||||
class sha1:
|
||||
state: t.CArray[t.CUInt32T, 5]
|
||||
count: t.CUInt64T
|
||||
buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN]
|
||||
def __init__(self: sha1) -> t.CInt: pass
|
||||
def transform(self: sha1, block: t.CUInt8T | t.CPtr) -> t.CInt: pass
|
||||
def update(self: sha1, s: str) -> t.CInt: pass
|
||||
def final(self: sha1, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]) -> t.CInt: pass
|
||||
@@ -1,35 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from hashlib.__md5.py
|
||||
Module: hashlib.__md5
|
||||
"""
|
||||
|
||||
|
||||
import string
|
||||
import t, c
|
||||
|
||||
MD5_BLOCK_LEN: t.CDefine = 64 # 分组块大小
|
||||
MD5_DIGEST_LEN: t.CDefine = 16 # 摘要输出长度
|
||||
|
||||
def md5_F(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def md5_G(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def md5_H(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass
|
||||
|
||||
def md5_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: pass
|
||||
|
||||
|
||||
md5_T: t.CExtern | t.CArray[t.CUInt32T, 64]
|
||||
md5_S: t.CExtern | t.CArray[t.CInt, 64]
|
||||
|
||||
@t.Object
|
||||
class md5:
|
||||
state: t.CArray[t.CUInt32T, 4]
|
||||
count: t.CUInt64T
|
||||
buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN]
|
||||
def __init__(self: md5) -> t.CInt: pass
|
||||
def transform(self: md5, block: t.CUInt8T | t.CPtr) -> t.CInt: pass
|
||||
def update(self: md5, s: str) -> t.CInt: pass
|
||||
def final(self: md5, out: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]) -> t.CInt: pass
|
||||
@@ -1,22 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from json.__writer.py
|
||||
Module: json.__writer
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from stdio import snprintf
|
||||
from . import JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT, JSON_STRING, JSON_ARRAY, JSON_OBJECT
|
||||
|
||||
def _write_char(buf: t.CChar | t.CPtr, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT: pass
|
||||
|
||||
def _write_str(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: pass
|
||||
|
||||
def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: pass
|
||||
|
||||
def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT: pass
|
||||
|
||||
def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr: pass
|
||||
@@ -1,38 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from json.__parser.py
|
||||
Module: json.__parser
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from . import JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT, JSON_STRING, JSON_ARRAY, JSON_OBJECT, null, bool_val, int_val, float_val, string_val, array, object
|
||||
|
||||
class ParseState:
|
||||
src: t.CChar | t.CPtr
|
||||
pos: t.CSizeT
|
||||
len: t.CSizeT
|
||||
pool: memhub.MemManager | t.CPtr
|
||||
def __init__(self: ParseState, src: t.CChar | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def _peek(s: ParseState | t.CPtr) -> t.CChar: pass
|
||||
|
||||
def _advance(s: ParseState | t.CPtr) -> t.CChar: pass
|
||||
|
||||
def _skip_whitespace(s: ParseState | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool: pass
|
||||
|
||||
def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr: pass
|
||||
|
||||
def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def parse(pool: memhub.MemManager | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
@@ -1,26 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from atom.py
|
||||
Module: atom
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
|
||||
ATOMIC_RELAXED: t.CDefine = 0
|
||||
ATOMIC_CONSUME: t.CDefine = 1
|
||||
ATOMIC_ACQUIRE: t.CDefine = 2
|
||||
ATOMIC_RELEASE: t.CDefine = 3
|
||||
ATOMIC_ACQ_REL: t.CDefine = 4
|
||||
ATOMIC_SEQ_CST: t.CDefine = 5
|
||||
|
||||
def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass
|
||||
|
||||
def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass
|
||||
|
||||
def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass
|
||||
|
||||
def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass
|
||||
|
||||
def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass
|
||||
|
||||
def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass
|
||||
@@ -1,73 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from ast.astaux.py
|
||||
Module: ast.astaux
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from .base import AST, ASTKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list
|
||||
|
||||
class ExceptHandler(AST):
|
||||
type: AST | t.CPtr
|
||||
name: str
|
||||
def __new__(self: ExceptHandler, pool: memhub.MemManager | t.CPtr, type: AST | t.CPtr, name: str) -> t.CInt: pass
|
||||
def __init__(self: ExceptHandler, pool: memhub.MemManager | t.CPtr, type: AST | t.CPtr, name: str) -> t.CInt: pass
|
||||
def kind(self: ExceptHandler) -> t.CInt: pass
|
||||
def type_name(self: ExceptHandler) -> str: pass
|
||||
def dump(self: ExceptHandler, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Arguments(AST):
|
||||
args: list[AST | t.CPtr] | t.CPtr
|
||||
vararg: AST | t.CPtr
|
||||
kwarg: AST | t.CPtr
|
||||
defaults: list[AST | t.CPtr] | t.CPtr
|
||||
kw_defaults: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Arguments, pool: memhub.MemManager | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, vararg: AST | t.CPtr, kwarg: AST | t.CPtr, defaults: list[AST | t.CPtr] | t.CPtr, kw_defaults: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Arguments, pool: memhub.MemManager | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, vararg: AST | t.CPtr, kwarg: AST | t.CPtr, defaults: list[AST | t.CPtr] | t.CPtr, kw_defaults: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Arguments) -> t.CInt: pass
|
||||
def type_name(self: Arguments) -> str: pass
|
||||
def dump(self: Arguments, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Arg(AST):
|
||||
arg: str
|
||||
annotation: AST | t.CPtr
|
||||
def __new__(self: Arg, pool: memhub.MemManager | t.CPtr, arg: str, annotation: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Arg, pool: memhub.MemManager | t.CPtr, arg: str, annotation: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Arg) -> t.CInt: pass
|
||||
def type_name(self: Arg) -> str: pass
|
||||
def dump(self: Arg, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Keyword(AST):
|
||||
arg: str
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: Keyword, pool: memhub.MemManager | t.CPtr, arg: str, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Keyword, pool: memhub.MemManager | t.CPtr, arg: str, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Keyword) -> t.CInt: pass
|
||||
def type_name(self: Keyword) -> str: pass
|
||||
def dump(self: Keyword, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Alias(AST):
|
||||
name: str
|
||||
asname: str
|
||||
def __new__(self: Alias, pool: memhub.MemManager | t.CPtr, name: str, asname: str) -> t.CInt: pass
|
||||
def __init__(self: Alias, pool: memhub.MemManager | t.CPtr, name: str, asname: str) -> t.CInt: pass
|
||||
def kind(self: Alias) -> t.CInt: pass
|
||||
def type_name(self: Alias) -> str: pass
|
||||
def dump(self: Alias, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class WithItem(AST):
|
||||
context_expr: AST | t.CPtr
|
||||
optional_vars: AST | t.CPtr
|
||||
def __new__(self: WithItem, pool: memhub.MemManager | t.CPtr, context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: WithItem, pool: memhub.MemManager | t.CPtr, context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: WithItem) -> t.CInt: pass
|
||||
def type_name(self: WithItem) -> str: pass
|
||||
def dump(self: WithItem, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Comprehension(AST):
|
||||
target: AST | t.CPtr
|
||||
iter: AST | t.CPtr
|
||||
ifs: list[AST | t.CPtr] | t.CPtr
|
||||
is_async: t.CInt
|
||||
def __new__(self: Comprehension, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: Comprehension, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def kind(self: Comprehension) -> t.CInt: pass
|
||||
def type_name(self: Comprehension) -> str: pass
|
||||
def dump(self: Comprehension, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
@@ -1,82 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from ast.match.py
|
||||
Module: ast.match
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from .base import AST, ASTKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list
|
||||
|
||||
class MatchCase(AST):
|
||||
pattern: AST | t.CPtr
|
||||
guard: AST | t.CPtr
|
||||
def __new__(self: MatchCase, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, guard: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchCase, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, guard: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchCase) -> t.CInt: pass
|
||||
def type_name(self: MatchCase) -> str: pass
|
||||
def dump(self: MatchCase, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchValue(AST):
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: MatchValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchValue) -> t.CInt: pass
|
||||
def type_name(self: MatchValue) -> str: pass
|
||||
def dump(self: MatchValue, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchSingleton(AST):
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: MatchSingleton, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchSingleton, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchSingleton) -> t.CInt: pass
|
||||
def type_name(self: MatchSingleton) -> str: pass
|
||||
def dump(self: MatchSingleton, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchSequence(AST):
|
||||
patterns: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: MatchSequence, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchSequence, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchSequence) -> t.CInt: pass
|
||||
def type_name(self: MatchSequence) -> str: pass
|
||||
def dump(self: MatchSequence, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchMapping(AST):
|
||||
keys: list[AST | t.CPtr] | t.CPtr
|
||||
patterns: list[AST | t.CPtr] | t.CPtr
|
||||
rest: str
|
||||
def __new__(self: MatchMapping, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, rest: str) -> t.CInt: pass
|
||||
def __init__(self: MatchMapping, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, rest: str) -> t.CInt: pass
|
||||
def kind(self: MatchMapping) -> t.CInt: pass
|
||||
def type_name(self: MatchMapping) -> str: pass
|
||||
def dump(self: MatchMapping, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchClass(AST):
|
||||
cls: AST | t.CPtr
|
||||
patterns: list[AST | t.CPtr] | t.CPtr
|
||||
kwd_attrs: list[AST | t.CPtr] | t.CPtr
|
||||
kwd_patterns: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: MatchClass, pool: memhub.MemManager | t.CPtr, cls: AST | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, kwd_attrs: list[AST | t.CPtr] | t.CPtr, kwd_patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchClass, pool: memhub.MemManager | t.CPtr, cls: AST | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, kwd_attrs: list[AST | t.CPtr] | t.CPtr, kwd_patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchClass) -> t.CInt: pass
|
||||
def type_name(self: MatchClass) -> str: pass
|
||||
def dump(self: MatchClass, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchStar(AST):
|
||||
name: str
|
||||
def __new__(self: MatchStar, pool: memhub.MemManager | t.CPtr, name: str) -> t.CInt: pass
|
||||
def __init__(self: MatchStar, pool: memhub.MemManager | t.CPtr, name: str) -> t.CInt: pass
|
||||
def kind(self: MatchStar) -> t.CInt: pass
|
||||
def type_name(self: MatchStar) -> str: pass
|
||||
def dump(self: MatchStar, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchAs(AST):
|
||||
pattern: AST | t.CPtr
|
||||
name: str
|
||||
def __new__(self: MatchAs, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, name: str) -> t.CInt: pass
|
||||
def __init__(self: MatchAs, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, name: str) -> t.CInt: pass
|
||||
def kind(self: MatchAs) -> t.CInt: pass
|
||||
def type_name(self: MatchAs) -> str: pass
|
||||
def dump(self: MatchAs, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class MatchOr(AST):
|
||||
patterns: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: MatchOr, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: MatchOr, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: MatchOr) -> t.CInt: pass
|
||||
def type_name(self: MatchOr) -> str: pass
|
||||
def dump(self: MatchOr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
@@ -1 +0,0 @@
|
||||
{"WhileHandle": "while 循环语句处理器:继承 Mixin 获得 Trans 回指针", "WhileHandle.Handle": "翻译 while 循环语句"}
|
||||
@@ -1,25 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from lib.core.Handles.HandlesWhile.py
|
||||
Module: lib.core.Handles.HandlesWhile
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
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.HandlesBody as HandlesBody
|
||||
|
||||
@t.NoVTable
|
||||
class WhileHandle(HandlesBase.Mixin):
|
||||
def __init__(self: WhileHandle, trans: HT.Translator | t.CPtr) -> t.CInt: pass
|
||||
def Handle(self: WhileHandle, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr, trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr: pass
|
||||
@@ -1,71 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from json.__init__.py
|
||||
Module: json.__init__
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import viperio
|
||||
|
||||
JSON_NULL: t.CDefine = 0
|
||||
JSON_BOOL: t.CDefine = 1
|
||||
JSON_INT: t.CDefine = 2
|
||||
JSON_FLOAT: t.CDefine = 3
|
||||
JSON_STRING: t.CDefine = 4
|
||||
JSON_ARRAY: t.CDefine = 5
|
||||
JSON_OBJECT: t.CDefine = 6
|
||||
|
||||
class JsonValue:
|
||||
vtype: t.CInt
|
||||
bool_val: t.CInt
|
||||
int_val: t.CInt64T
|
||||
float_val: t.CDouble
|
||||
str_val: t.CChar | t.CPtr
|
||||
next: 'JsonValue' | t.CPtr
|
||||
key: t.CChar | t.CPtr
|
||||
child: 'JsonValue' | t.CPtr
|
||||
child_count: t.CSizeT
|
||||
def __new__(self: JsonValue, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def type(self: JsonValue) -> t.CInt: pass
|
||||
def is_null(self: JsonValue) -> bool: pass
|
||||
def is_bool(self: JsonValue) -> bool: pass
|
||||
def is_int(self: JsonValue) -> bool: pass
|
||||
def is_float(self: JsonValue) -> bool: pass
|
||||
def is_string(self: JsonValue) -> bool: pass
|
||||
def is_array(self: JsonValue) -> bool: pass
|
||||
def is_object(self: JsonValue) -> bool: pass
|
||||
def as_bool(self: JsonValue) -> bool: pass
|
||||
def as_int(self: JsonValue) -> t.CInt64T: pass
|
||||
def as_float(self: JsonValue) -> t.CDouble: pass
|
||||
def as_string(self: JsonValue) -> t.CChar | t.CPtr: pass
|
||||
def __len__(self: JsonValue) -> t.CSizeT: pass
|
||||
def __getitem__(self: JsonValue, key: t.CChar | t.CPtr) -> 'JsonValue' | t.CPtr: pass
|
||||
def __setitem__(self: JsonValue, key: t.CChar | t.CPtr, val: 'JsonValue' | t.CPtr) -> t.CInt: pass
|
||||
def get_item(self: JsonValue, index: t.CSizeT) -> 'JsonValue' | t.CPtr: pass
|
||||
def _pool_alloc(self: JsonValue, size: t.CSizeT) -> t.CChar | t.CPtr: pass
|
||||
def _append_child(self: JsonValue, child: 'JsonValue' | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def null(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def string_val(pool: memhub.MemManager | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass
|
||||
|
||||
def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr) -> t.CInt: pass
|
||||
|
||||
|
||||
from .__parser import parse
|
||||
from .__writer import write
|
||||
@@ -1,86 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from w32.winsock2.py
|
||||
Module: w32.winsock2
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
from w32.win32base import *
|
||||
|
||||
WINSOCK_VERSION: t.CDefine = 0x0202 # 2.2
|
||||
AF_INET: t.CDefine = 2
|
||||
AF_INET6: t.CDefine = 23
|
||||
SOCK_STREAM: t.CDefine = 1 # TCP
|
||||
SOCK_DGRAM: t.CDefine = 2 # UDP
|
||||
SOCK_RAW: t.CDefine = 3 # 原始套接字
|
||||
IPPROTO_TCP: t.CDefine = 6
|
||||
IPPROTO_UDP: t.CDefine = 17
|
||||
SOL_SOCKET: t.CDefine = 0xFFFF # WinSock2 值
|
||||
SO_RCVTIMEO: t.CDefine = 0x1006 # WinSock2 值
|
||||
SO_SNDTIMEO: t.CDefine = 0x1005 # WinSock2 值
|
||||
SO_REUSEADDR: t.CDefine = 0x0004 # WinSock2 值
|
||||
INADDR_ANY: t.CDefine = 0
|
||||
SOCKET_ERROR: t.CDefine = -1
|
||||
INVALID_SOCKET: t.CDefine = 0xFFFFFFFF # WinSock2: ~0
|
||||
MSG_NOSIGNAL: t.CDefine = 0 # Windows 不支持,设为 0
|
||||
SD_SEND: t.CDefine = 1
|
||||
SD_RECV: t.CDefine = 0
|
||||
SD_BOTH: t.CDefine = 2
|
||||
|
||||
class WSASocketAddr:
|
||||
family: u16
|
||||
port: u16
|
||||
addr: u32
|
||||
zero: u64
|
||||
class WSAData:
|
||||
wVersion: WORD
|
||||
wHighVersion: WORD
|
||||
szDescription: BYTE
|
||||
szSystemStatus: BYTE
|
||||
iMaxSockets: u16
|
||||
iMaxUdpDg: u16
|
||||
lpVendorInfo: CHARPTR
|
||||
class WSAHostEnt:
|
||||
h_name: CHARPTR
|
||||
h_aliases: CHARPTR
|
||||
h_addrtype: SHORT
|
||||
h_length: SHORT
|
||||
h_addr_list: CHARPTR
|
||||
class WinTimeVal:
|
||||
tv_sec: LONG
|
||||
tv_usec: LONG
|
||||
|
||||
def WSAStartup(wVersionRequested: WORD, lpWSAData: WSAData | t.CPtr) -> INT | t.State: pass
|
||||
|
||||
def WSACleanup() -> INT | t.State: pass
|
||||
|
||||
def WSAGetLastError() -> INT | t.State: pass
|
||||
|
||||
def socket(family: INT, type: INT, protocol: INT) -> u64 | t.State: pass
|
||||
|
||||
def closesocket(s: u64) -> INT | t.State: pass
|
||||
|
||||
def connect(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass
|
||||
|
||||
def send(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass
|
||||
|
||||
def recv(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass
|
||||
|
||||
def bind(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass
|
||||
|
||||
def listen(s: u64, backlog: INT) -> INT | t.State: pass
|
||||
|
||||
def accept(s: u64, addr: WSASocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.State: pass
|
||||
|
||||
def setsockopt(s: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.State: pass
|
||||
|
||||
def shutdown(s: u64, how: INT) -> INT | t.State: pass
|
||||
|
||||
def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> WSAHostEnt | t.CPtr | t.State: pass
|
||||
|
||||
def ntohs(netshort: u16) -> u16 | t.State: pass
|
||||
|
||||
def htons(hostshort: u16) -> u16 | t.State: pass
|
||||
|
||||
def inet_addr(cp: t.CChar | t.CConst | t.CPtr) -> u32 | t.State: pass
|
||||
@@ -1,226 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from ast.stmts.py
|
||||
Module: ast.stmts
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from .base import AST, ASTKind, ASTCtx, OpKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list, FLAG_IS_ASYNC
|
||||
|
||||
@t.CVTable
|
||||
class Module(AST):
|
||||
def __new__(self: Module, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Module, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Module) -> t.CInt: pass
|
||||
def type_name(self: Module) -> str: pass
|
||||
def dump(self: Module, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Assign(AST):
|
||||
targets: list[AST | t.CPtr] | t.CPtr
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: Assign, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Assign, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Assign) -> t.CInt: pass
|
||||
def type_name(self: Assign) -> str: pass
|
||||
def dump(self: Assign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class If(AST):
|
||||
test: AST | t.CPtr
|
||||
orelse: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: If, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: If, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: If) -> t.CInt: pass
|
||||
def type_name(self: If) -> str: pass
|
||||
def dump(self: If, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class For(AST):
|
||||
target: AST | t.CPtr
|
||||
iter: AST | t.CPtr
|
||||
orelse: list[AST | t.CPtr] | t.CPtr
|
||||
flags: t.CInt
|
||||
def __new__(self: For, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: For, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def kind(self: For) -> t.CInt: pass
|
||||
def type_name(self: For) -> str: pass
|
||||
def dump(self: For, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class While(AST):
|
||||
test: AST | t.CPtr
|
||||
orelse: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: While, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: While, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: While) -> t.CInt: pass
|
||||
def type_name(self: While) -> str: pass
|
||||
def dump(self: While, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Return(AST):
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: Return, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Return, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Return) -> t.CInt: pass
|
||||
def type_name(self: Return) -> str: pass
|
||||
def dump(self: Return, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Expr(AST):
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: Expr, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Expr, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Expr) -> t.CInt: pass
|
||||
def type_name(self: Expr) -> str: pass
|
||||
def dump(self: Expr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class FunctionDef(AST):
|
||||
name: str
|
||||
args: AST | t.CPtr
|
||||
decorator_list: list[AST | t.CPtr] | t.CPtr
|
||||
returns: AST | t.CPtr
|
||||
flags: t.CInt
|
||||
def __new__(self: FunctionDef, pool: memhub.MemManager | t.CPtr, name: str, args: AST | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: FunctionDef, pool: memhub.MemManager | t.CPtr, name: str, args: AST | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def kind(self: FunctionDef) -> t.CInt: pass
|
||||
def type_name(self: FunctionDef) -> str: pass
|
||||
def dump(self: FunctionDef, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Expression(AST):
|
||||
body: AST | t.CPtr
|
||||
def __new__(self: Expression, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Expression, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Expression) -> t.CInt: pass
|
||||
def type_name(self: Expression) -> str: pass
|
||||
def dump(self: Expression, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Interactive(AST):
|
||||
body: AST | t.CPtr
|
||||
def __new__(self: Interactive, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Interactive, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Interactive) -> t.CInt: pass
|
||||
def type_name(self: Interactive) -> str: pass
|
||||
def dump(self: Interactive, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class FunctionType(AST):
|
||||
argtypes: list[AST | t.CPtr] | t.CPtr
|
||||
returns: AST | t.CPtr
|
||||
def __new__(self: FunctionType, pool: memhub.MemManager | t.CPtr, argtypes: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: FunctionType, pool: memhub.MemManager | t.CPtr, argtypes: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: FunctionType) -> t.CInt: pass
|
||||
def type_name(self: FunctionType) -> str: pass
|
||||
def dump(self: FunctionType, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class ClassDef(AST):
|
||||
name: str
|
||||
bases: list[AST | t.CPtr] | t.CPtr
|
||||
keywords: list[AST | t.CPtr] | t.CPtr
|
||||
decorator_list: list[AST | t.CPtr] | t.CPtr
|
||||
type_params: list[str] | t.CPtr
|
||||
def __new__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass
|
||||
def __init__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass
|
||||
def kind(self: ClassDef) -> t.CInt: pass
|
||||
def type_name(self: ClassDef) -> str: pass
|
||||
def dump(self: ClassDef, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Delete(AST):
|
||||
targets: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Delete, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Delete, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Delete) -> t.CInt: pass
|
||||
def type_name(self: Delete) -> str: pass
|
||||
def dump(self: Delete, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class AugAssign(AST):
|
||||
target: AST | t.CPtr
|
||||
op: t.CInt
|
||||
value: AST | t.CPtr
|
||||
def __new__(self: AugAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, op: t.CInt, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: AugAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, op: t.CInt, value: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: AugAssign) -> t.CInt: pass
|
||||
def type_name(self: AugAssign) -> str: pass
|
||||
def dump(self: AugAssign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class AnnAssign(AST):
|
||||
target: AST | t.CPtr
|
||||
annotation: AST | t.CPtr
|
||||
value: AST | t.CPtr
|
||||
simple: t.CInt
|
||||
def __new__(self: AnnAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, annotation: AST | t.CPtr, value: AST | t.CPtr, simple: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: AnnAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, annotation: AST | t.CPtr, value: AST | t.CPtr, simple: t.CInt) -> t.CInt: pass
|
||||
def kind(self: AnnAssign) -> t.CInt: pass
|
||||
def type_name(self: AnnAssign) -> str: pass
|
||||
def dump(self: AnnAssign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class With(AST):
|
||||
items: list[AST | t.CPtr] | t.CPtr
|
||||
flags: t.CInt
|
||||
def __new__(self: With, pool: memhub.MemManager | t.CPtr, items: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: With, pool: memhub.MemManager | t.CPtr, items: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass
|
||||
def kind(self: With) -> t.CInt: pass
|
||||
def type_name(self: With) -> str: pass
|
||||
def dump(self: With, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Raise(AST):
|
||||
exc: AST | t.CPtr
|
||||
cause: AST | t.CPtr
|
||||
def __new__(self: Raise, pool: memhub.MemManager | t.CPtr, exc: AST | t.CPtr, cause: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Raise, pool: memhub.MemManager | t.CPtr, exc: AST | t.CPtr, cause: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Raise) -> t.CInt: pass
|
||||
def type_name(self: Raise) -> str: pass
|
||||
def dump(self: Raise, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Try(AST):
|
||||
handlers: list[AST | t.CPtr] | t.CPtr
|
||||
orelse: list[AST | t.CPtr] | t.CPtr
|
||||
finalbody: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Try, pool: memhub.MemManager | t.CPtr, handlers: list[AST | t.CPtr] | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, finalbody: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Try, pool: memhub.MemManager | t.CPtr, handlers: list[AST | t.CPtr] | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, finalbody: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Try) -> t.CInt: pass
|
||||
def type_name(self: Try) -> str: pass
|
||||
def dump(self: Try, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Assert(AST):
|
||||
test: AST | t.CPtr
|
||||
msg: AST | t.CPtr
|
||||
def __new__(self: Assert, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, msg: AST | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Assert, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, msg: AST | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Assert) -> t.CInt: pass
|
||||
def type_name(self: Assert) -> str: pass
|
||||
def dump(self: Assert, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Global(AST):
|
||||
names: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Global, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Global, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Global) -> t.CInt: pass
|
||||
def type_name(self: Global) -> str: pass
|
||||
def dump(self: Global, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Nonlocal(AST):
|
||||
names: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Nonlocal, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Nonlocal, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Nonlocal) -> t.CInt: pass
|
||||
def type_name(self: Nonlocal) -> str: pass
|
||||
def dump(self: Nonlocal, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Pass(AST):
|
||||
def __new__(self: Pass, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Pass, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Pass) -> t.CInt: pass
|
||||
def type_name(self: Pass) -> str: pass
|
||||
def dump(self: Pass, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Break(AST):
|
||||
def __new__(self: Break, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Break, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Break) -> t.CInt: pass
|
||||
def type_name(self: Break) -> str: pass
|
||||
def dump(self: Break, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Continue(AST):
|
||||
def __new__(self: Continue, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Continue, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Continue) -> t.CInt: pass
|
||||
def type_name(self: Continue) -> str: pass
|
||||
def dump(self: Continue, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Import(AST):
|
||||
names: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Import, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Import, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Import) -> t.CInt: pass
|
||||
def type_name(self: Import) -> str: pass
|
||||
def dump(self: Import, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class ImportFrom(AST):
|
||||
module: str
|
||||
names: list[AST | t.CPtr] | t.CPtr
|
||||
level: t.CInt
|
||||
def __new__(self: ImportFrom, pool: memhub.MemManager | t.CPtr, module: str, names: list[AST | t.CPtr] | t.CPtr, level: t.CInt) -> t.CInt: pass
|
||||
def __init__(self: ImportFrom, pool: memhub.MemManager | t.CPtr, module: str, names: list[AST | t.CPtr] | t.CPtr, level: t.CInt) -> t.CInt: pass
|
||||
def kind(self: ImportFrom) -> t.CInt: pass
|
||||
def type_name(self: ImportFrom) -> str: pass
|
||||
def dump(self: ImportFrom, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
class Match(AST):
|
||||
subject: AST | t.CPtr
|
||||
cases: list[AST | t.CPtr] | t.CPtr
|
||||
def __new__(self: Match, pool: memhub.MemManager | t.CPtr, subject: AST | t.CPtr, cases: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def __init__(self: Match, pool: memhub.MemManager | t.CPtr, subject: AST | t.CPtr, cases: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass
|
||||
def kind(self: Match) -> t.CInt: pass
|
||||
def type_name(self: Match) -> str: pass
|
||||
def dump(self: Match, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass
|
||||
@@ -1 +0,0 @@
|
||||
{"IfHandle": "if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针", "IfHandle.Handle": "翻译 if/elif/else 语句"}
|
||||
@@ -1,25 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from lib.core.Handles.HandlesIf.py
|
||||
Module: lib.core.Handles.HandlesIf
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
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.HandlesBody as HandlesBody
|
||||
|
||||
@t.NoVTable
|
||||
class IfHandle(HandlesBase.Mixin):
|
||||
def __init__(self: IfHandle, trans: HT.Translator | t.CPtr) -> t.CInt: pass
|
||||
def Handle(self: IfHandle, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def NewIfHandle(pool: memhub.MemBuddy | t.CPtr, trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr: pass
|
||||
@@ -1,39 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from hashlib.__sha512.py
|
||||
Module: hashlib.__sha512
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
|
||||
SHA512_BLOCK_LEN: t.CDefine = 128
|
||||
SHA512_DIGEST_LEN: t.CDefine = 64
|
||||
|
||||
def sha512_ror(x: t.CUInt64T, n: int) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_shr(x: t.CUInt64T, n: int) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_Ch(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_Maj(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_BigSigma0(x: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_BigSigma1(x: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: pass
|
||||
|
||||
|
||||
sha512_K: t.CExtern | t.CArray[t.CUInt64T, 80]
|
||||
|
||||
@t.Object
|
||||
class sha512:
|
||||
state: t.CArray[t.CUInt64T, 8]
|
||||
count: t.CArray[t.CUInt64T, 2]
|
||||
buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]
|
||||
def __init__(self: sha512) -> t.CInt: pass
|
||||
def transform(self: sha512, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]) -> t.CInt: pass
|
||||
def update(self: sha512, s: str) -> t.CInt: pass
|
||||
def final(self: sha512, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]) -> t.CInt: pass
|
||||
@@ -1,20 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from stdarg.py
|
||||
Module: stdarg
|
||||
"""
|
||||
|
||||
import c
|
||||
|
||||
|
||||
import t
|
||||
|
||||
def va_start(args: t.CPtr, last_arg: t.CPtr) -> t.State: pass
|
||||
|
||||
def va_arg(args: t.CPtr, type: t.CPtr) -> t.CPtr | t.State: pass
|
||||
|
||||
def va_end(args: t.CPtr) -> t.State | t.State: pass
|
||||
|
||||
|
||||
va_list: t.CTypedef = t.CUnsignedChar | t.CPtr
|
||||
|
||||
def arg(type: t.CType) -> t.State: pass
|
||||
@@ -1,91 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from w32.win32memory.py
|
||||
Module: w32.win32memory
|
||||
"""
|
||||
|
||||
import c
|
||||
|
||||
|
||||
import t
|
||||
from stdint import *
|
||||
from w32.win32base import *
|
||||
|
||||
MEM_COMMIT: t.CDefine = 0x00001000
|
||||
MEM_RESERVE: t.CDefine = 0x00002000
|
||||
MEM_DECOMMIT: t.CDefine = 0x00004000
|
||||
MEM_RELEASE: t.CDefine = 0x00008000
|
||||
MEM_FREE: t.CDefine = 0x00010000
|
||||
MEM_RESET: t.CDefine = 0x00080000
|
||||
MEM_TOP_DOWN: t.CDefine = 0x00100000
|
||||
MEM_WRITE_WATCH: t.CDefine = 0x00200000
|
||||
MEM_PHYSICAL: t.CDefine = 0x00400000
|
||||
MEM_LARGE_PAGES: t.CDefine = 0x20000000
|
||||
PAGE_NOACCESS: t.CDefine = 0x01
|
||||
PAGE_READONLY: t.CDefine = 0x02
|
||||
PAGE_READWRITE: t.CDefine = 0x04
|
||||
PAGE_WRITECOPY: t.CDefine = 0x08
|
||||
PAGE_EXECUTE: t.CDefine = 0x10
|
||||
PAGE_EXECUTE_READ: t.CDefine = 0x20
|
||||
PAGE_EXECUTE_READWRITE: t.CDefine = 0x40
|
||||
PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80
|
||||
PAGE_GUARD: t.CDefine = 0x100
|
||||
PAGE_NOCACHE: t.CDefine = 0x200
|
||||
PAGE_WRITECOMBINE: t.CDefine = 0x400
|
||||
HEAP_NO_SERIALIZE: t.CDefine = 0x00000001
|
||||
HEAP_GROWABLE: t.CDefine = 0x00000002
|
||||
HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004
|
||||
HEAP_ZERO_MEMORY: t.CDefine = 0x00000008
|
||||
HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010
|
||||
|
||||
class MEMORY_BASIC_INFORMATION:
|
||||
BaseAddress: VOIDPTR
|
||||
AllocationBase: VOIDPTR
|
||||
AllocationProtect: ULONG
|
||||
RegionSize: t.CSizeT
|
||||
State: ULONG
|
||||
Protect: ULONG
|
||||
Type: ULONG
|
||||
|
||||
def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass
|
||||
|
||||
def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass
|
||||
|
||||
def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass
|
||||
|
||||
def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass
|
||||
|
||||
def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass
|
||||
|
||||
def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass
|
||||
|
||||
def GetProcessHeap() -> HANDLE | t.State: pass
|
||||
|
||||
def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass
|
||||
|
||||
def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass
|
||||
|
||||
def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
|
||||
|
||||
def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
|
||||
|
||||
def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass
|
||||
|
||||
def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass
|
||||
|
||||
def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass
|
||||
|
||||
def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass
|
||||
|
||||
def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
|
||||
|
||||
def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
|
||||
|
||||
def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
|
||||
|
||||
def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass
|
||||
|
||||
def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass
|
||||
|
||||
def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
|
||||
|
||||
def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
|
||||
@@ -1,35 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from lib.core.Handles.HandlesBody.py
|
||||
Module: lib.core.Handles.HandlesBody
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import viperlib
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesExpr as HandlesExpr
|
||||
import lib.core.Handles.HandlesExprCall as HandlesExprCall
|
||||
import lib.core.Handles.HandlesFunctions as HandlesFunctions
|
||||
import lib.core.Handles.HandlesClassDef as HandlesClassDef
|
||||
|
||||
def translate_stmt(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def translate_global(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def translate_nonlocal(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def translate_expr_stmt(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def pre_scan_allocas(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass
|
||||
|
||||
def translate_break(trans: HT.Translator | t.CPtr) -> int: pass
|
||||
|
||||
def translate_continue(trans: HT.Translator | t.CPtr) -> int: pass
|
||||
|
||||
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str: pass
|
||||
@@ -1,13 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from hashlib.__init__.py
|
||||
Module: hashlib.__init__
|
||||
"""
|
||||
|
||||
import t
|
||||
import c
|
||||
|
||||
|
||||
from .__md5 import md5, MD5_DIGEST_LEN
|
||||
from .__sha1 import sha1, SHA1_DIGEST_LEN
|
||||
from .__sha256 import sha256, SHA256_DIGEST_LEN
|
||||
from .__sha512 import sha512, SHA512_DIGEST_LEN
|
||||
@@ -1 +1 @@
|
||||
{"D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Config.py": {"sha1": "c0042adc0b7ec5df", "mtime": 1785332415.2264168, "size": 14060}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Utils.py": {"sha1": "4650533467115342", "mtime": 1785332415.2054548, "size": 4900}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\Converter.py": {"sha1": "3c5f1c61545644a9", "mtime": 1785332415.2120533, "size": 35262}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.py": {"sha1": "6a19179426e9a883", "mtime": 1785332415.1753137, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.py": {"sha1": "e991626c0aee9d7b", "mtime": 1785338517.4840038, "size": 23557}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.py": {"sha1": "15bb32adb7093ed7", "mtime": 1785332415.1796682, "size": 22584}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.py": {"sha1": "2b59175b77f1304e", "mtime": 1785343736.8740923, "size": 24369}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.py": {"sha1": "31e49accebfc8aac", "mtime": 1784751046.0461829, "size": 12874}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBase.py": {"sha1": "63a3d17e96a083ac", "mtime": 1785332415.2080498, "size": 8740}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBody.py": {"sha1": "81eb28ba912467a6", "mtime": 1784566611.8626723, "size": 8538}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.py": {"sha1": "aa45364399b86a03", "mtime": 1785345709.6485052, "size": 142863}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.py": {"sha1": "f05b14a2ad5767a7", "mtime": 1784741624.7278736, "size": 8520}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.py": {"sha1": "68f2617198f5757f", "mtime": 1785352882.3350165, "size": 144462}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.py": {"sha1": "5c482c6aac2ba83b", "mtime": 1785332415.2151341, "size": 250062}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.py": {"sha1": "be8c2d7b882881c8", "mtime": 1784791452.111348, "size": 12796}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFor.py": {"sha1": "456fb516ba3c5002", "mtime": 1785332415.1896677, "size": 17319}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFunctions.py": {"sha1": "1073ffca7e27aae5", "mtime": 1785332415.2064638, "size": 45439}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesIf.py": {"sha1": "66de93aaeebc0601", "mtime": 1784909392.040444, "size": 5211}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesImports.py": {"sha1": "6293eee0a5805aa5", "mtime": 1785332415.2416043, "size": 25274}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMain.py": {"sha1": "4a7b57e6bd18f65e", "mtime": 1785332415.1935978, "size": 21362}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.py": {"sha1": "af9484a65085bf4b", "mtime": 1784540868.0555332, "size": 5336}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.py": {"sha1": "2703a899f26b771d", "mtime": 1785332415.1835012, "size": 5496}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.py": {"sha1": "371fa89e15d8c015", "mtime": 1785352932.9305031, "size": 48672}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.py": {"sha1": "62805d8ad3e9b5ba", "mtime": 1785332415.2370398, "size": 18196}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.py": {"sha1": "af1cc6aaab47a7d1", "mtime": 1785350678.7589717, "size": 60329}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.py": {"sha1": "cb1aa3a78af6f362", "mtime": 1785332415.2565334, "size": 15697}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesWhile.py": {"sha1": "51f0144d6e8188d9", "mtime": 1784566611.8311827, "size": 4787}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\IncludesScanner.py": {"sha1": "6282c9b745a35b8f", "mtime": 1785332415.2009153, "size": 12723}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.py": {"sha1": "2d523679d6b886ad", "mtime": 1785347467.5013578, "size": 51449}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.py": {"sha1": "7ba06a9edf0fa6c7", "mtime": 1785351377.1Line truncated
|
||||
{"D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Config.vp": {"sha1": "c0042adc0b7ec5df", "mtime": 1785332415.2264168, "size": 14060}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Utils.vp": {"sha1": "4650533467115342", "mtime": 1785332415.2054548, "size": 4900}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\Converter.vp": {"sha1": "3c5f1c61545644a9", "mtime": 1785332415.2120533, "size": 35262}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.vp": {"sha1": "6a19179426e9a883", "mtime": 1785332415.1753137, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.vp": {"sha1": "a38b726f4a82545f", "mtime": 1785397411.8500457, "size": 23570}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.vp": {"sha1": "15bb32adb7093ed7", "mtime": 1785332415.1796682, "size": 22584}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.vp": {"sha1": "2b59175b77f1304e", "mtime": 1785343736.8740923, "size": 24369}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.vp": {"sha1": "31e49accebfc8aac", "mtime": 1784751046.0461829, "size": 12874}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBase.vp": {"sha1": "63a3d17e96a083ac", "mtime": 1785332415.2080498, "size": 8740}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBody.vp": {"sha1": "81eb28ba912467a6", "mtime": 1784566611.8626723, "size": 8538}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.vp": {"sha1": "aa45364399b86a03", "mtime": 1785345709.6485052, "size": 142863}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.vp": {"sha1": "f05b14a2ad5767a7", "mtime": 1784741624.7278736, "size": 8520}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.vp": {"sha1": "bde6b4cc0847ee6d", "mtime": 1785398911.198053, "size": 145938}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.vp": {"sha1": "efefa18c5d6c2d81", "mtime": 1785397182.7094119, "size": 261395}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.vp": {"sha1": "be8c2d7b882881c8", "mtime": 1784791452.111348, "size": 12796}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFor.vp": {"sha1": "456fb516ba3c5002", "mtime": 1785332415.1896677, "size": 17319}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFunctions.vp": {"sha1": "1073ffca7e27aae5", "mtime": 1785332415.2064638, "size": 45439}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesIf.vp": {"sha1": "f4cdbca2f8802c12", "mtime": 1785390159.3673935, "size": 5626}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesImports.vp": {"sha1": "6293eee0a5805aa5", "mtime": 1785332415.2416043, "size": 25274}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMain.vp": {"sha1": "4a7b57e6bd18f65e", "mtime": 1785332415.1935978, "size": 21362}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.vp": {"sha1": "af9484a65085bf4b", "mtime": 1784540868.0555332, "size": 5336}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.vp": {"sha1": "4c644ade1f0d6d02", "mtime": 1785394149.332443, "size": 6334}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.vp": {"sha1": "371fa89e15d8c015", "mtime": 1785352932.9305031, "size": 48672}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.vp": {"sha1": "62805d8ad3e9b5ba", "mtime": 1785332415.2370398, "size": 18196}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.vp": {"sha1": "af1cc6aaab47a7d1", "mtime": 1785350678.7589717, "size": 60329}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.vp": {"sha1": "cb1aa3a78af6f362", "mtime": 1785332415.2565334, "size": 15697}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesWhile.vp": {"sha1": "8dc65d4c71e2936a", "mtime": 1785390170.5239043, "size": 5202}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\IncludesScanner.vp": {"sha1": "8d6185cf886c0334", "mtime": 1785398707.0211506, "size": 13021}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.vp": {"sha1": "fc26f66203d7cbb7", "mtime": 1785398809.9049404, "size": 51449}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.vp": {"sha1": "c1bb03b1eae141e0", "mtime": 1785398659.75Line truncated
|
||||
+80
-80
@@ -1,80 +1,80 @@
|
||||
067c78e9f121dce3:includes/w32\win32process.py
|
||||
06f53cc594b4ac6c:includes/w32\win32sync.py
|
||||
0c67644125bea0fd:includes/sys.py
|
||||
0df65b8ed15664b0:includes/hashlib\__sha1.py
|
||||
1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.py
|
||||
15bb32adb7093ed7:lib/core/Handles/HandlesAnnAssign.py
|
||||
19f8024d10c828e8:includes/hashlib\__md5.py
|
||||
1d74d1d3a174c684:includes/llvmlite\__init__.py
|
||||
20cd49775c100a38:includes/json\__writer.py
|
||||
22bc0df83b3f0e62:includes/ast\base.py
|
||||
240a9a4157959a9f:includes/json\__parser.py
|
||||
2703a899f26b771d:lib/core/Handles/HandlesReturn.py
|
||||
271ea3decb810db2:includes/atom.py
|
||||
285b6aa29a34754d:includes/stdio.py
|
||||
28de517e3820658a:includes/posix.py
|
||||
2b59175b77f1304e:lib/core/Handles/HandlesAssign.py
|
||||
2d523679d6b886ad:lib/core/Phase1.py
|
||||
2d8debefda779c40:includes/llvmlite\__types.py
|
||||
2fbec3db55b30ad4:includes/hashtable.py
|
||||
31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.py
|
||||
371fa89e15d8c015:lib/core/Handles/HandlesStruct.py
|
||||
3aa6057398be5673:includes/stdlib.py
|
||||
3c5f1c61545644a9:lib/StubGen/Converter.py
|
||||
4337fb260448bbe2:includes/ast\astaux.py
|
||||
456fb516ba3c5002:lib/core/Handles/HandlesFor.py
|
||||
4650533467115342:lib/Projectrans/Utils.py
|
||||
4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.py
|
||||
4daf5ed3f8e421a1:includes/string.py
|
||||
4dd6b3f1427d1cc5:includes/ast\match.py
|
||||
51f0144d6e8188d9:lib/core/Handles/HandlesWhile.py
|
||||
57288496f7c2d1ad:includes/json\__init__.py
|
||||
5a1d8c48f1243746:includes/llvmlite\__builder.py
|
||||
5c482c6aac2ba83b:lib/core/Handles/HandlesExprCall.py
|
||||
62805d8ad3e9b5ba:lib/core/Handles/HandlesTranslator.py
|
||||
6282c9b745a35b8f:lib/core/IncludesScanner.py
|
||||
6293eee0a5805aa5:lib/core/Handles/HandlesImports.py
|
||||
63a3d17e96a083ac:lib/core/Handles/HandlesBase.py
|
||||
657e182b27c2a022:includes/ast\stmts.py
|
||||
66de93aaeebc0601:lib/core/Handles/HandlesIf.py
|
||||
68f2617198f5757f:lib/core/Handles/HandlesExpr.py
|
||||
692919c5a194ac8d:includes/llvmlite\__module.py
|
||||
6a19179426e9a883:lib/__init__.py
|
||||
6b3bc463fd044545:includes/llvmlite\__verify.py
|
||||
6ff26590374ae6fc:includes/hashlib\__sha512.py
|
||||
71e0a3ffcb3ebfad:includes/stdarg.py
|
||||
72dbbb563aa943b0:includes/w32\fileio.py
|
||||
7ba06a9edf0fa6c7:lib/core/Phase2.py
|
||||
7cadfe07e983fd90:includes/_list.py
|
||||
81eb28ba912467a6:lib/core/Handles/HandlesBody.py
|
||||
874bac141c97bae9:includes/llvmlite\__function.py
|
||||
96837bcc64032444:includes/hashlib\__init__.py
|
||||
a335eb99f2e34479:includes/subprocess.py
|
||||
a5e9a83e9db303ad:includes/linkedlist.py
|
||||
aa45364399b86a03:lib/core/Handles/HandlesClassDef.py
|
||||
af1cc6aaab47a7d1:lib/core/Handles/HandlesType.py
|
||||
af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.py
|
||||
b370d93b74bf55cc:includes/argparse.py
|
||||
b543bc1dfb592119:includes/ast\exprs.py
|
||||
b547ac4f380bddb6:includes/ast\tokens.py
|
||||
b57252077e6b596b:includes/platmacro.py
|
||||
bbdf3bbd4c3bc28c:includes/w32\win32console.py
|
||||
bdf5730851fb95f2:lib/core/VLogger.py
|
||||
be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.py
|
||||
c0042adc0b7ec5df:lib/Projectrans/Config.py
|
||||
c2010cffc6092ea2:main.py
|
||||
c9d54a4158f7f5a8:includes/hashlib\__sha256.py
|
||||
c9f4be41ca1cc2b4:includes/viperio.py
|
||||
ca40915f11b8b6ad:includes/memhub.py
|
||||
cae1b2c5898ed6e5:lib/core/StubMerger.py
|
||||
cb1aa3a78af6f362:lib/core/Handles/HandlesVar.py
|
||||
e217def267d3d4a8:includes/ast\lexer.py
|
||||
e307a2d809cef071:includes/viperlib.py
|
||||
e991626c0aee9d7b:lib/core/BuildPipeline.py
|
||||
f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.py
|
||||
f3444ec56937284f:includes/ast\__init__.py
|
||||
f5522571bcce7bcb:includes/stdint.py
|
||||
f6b51804a0ba8ff0:includes/w32\win32file.py
|
||||
f9e36e2cd6fa659f:includes/llvmlite\__values.py
|
||||
fc980acec33d69a7:includes/w32\win32base.py
|
||||
fde6db0747bdd959:includes/ast\parser.py
|
||||
067c78e9f121dce3:includes/w32\win32process.vp
|
||||
06f53cc594b4ac6c:includes/w32\win32sync.vp
|
||||
0c67644125bea0fd:includes/sys.vp
|
||||
0df65b8ed15664b0:includes/hashlib\__sha1.vp
|
||||
1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.vp
|
||||
15bb32adb7093ed7:lib/core/Handles/HandlesAnnAssign.vp
|
||||
19f8024d10c828e8:includes/hashlib\__md5.vp
|
||||
1d74d1d3a174c684:includes/llvmlite\__init__.vp
|
||||
20cd49775c100a38:includes/json\__writer.vp
|
||||
22bc0df83b3f0e62:includes/ast\base.vp
|
||||
240a9a4157959a9f:includes/json\__parser.vp
|
||||
285b6aa29a34754d:includes/stdio.vp
|
||||
28de517e3820658a:includes/posix.vp
|
||||
2b59175b77f1304e:lib/core/Handles/HandlesAssign.vp
|
||||
2d8debefda779c40:includes/llvmlite\__types.vp
|
||||
2fbec3db55b30ad4:includes/hashtable.vp
|
||||
31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.vp
|
||||
371fa89e15d8c015:lib/core/Handles/HandlesStruct.vp
|
||||
3aa6057398be5673:includes/stdlib.vp
|
||||
3c5f1c61545644a9:lib/StubGen/Converter.vp
|
||||
4337fb260448bbe2:includes/ast\astaux.vp
|
||||
456fb516ba3c5002:lib/core/Handles/HandlesFor.vp
|
||||
4650533467115342:lib/Projectrans/Utils.vp
|
||||
484879ffecdf2b08:main.vp
|
||||
4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.vp
|
||||
4c644ade1f0d6d02:lib/core/Handles/HandlesReturn.vp
|
||||
4daf5ed3f8e421a1:includes/string.vp
|
||||
4dd6b3f1427d1cc5:includes/ast\match.vp
|
||||
57288496f7c2d1ad:includes/json\__init__.vp
|
||||
5a1d8c48f1243746:includes/llvmlite\__builder.vp
|
||||
62805d8ad3e9b5ba:lib/core/Handles/HandlesTranslator.vp
|
||||
6293eee0a5805aa5:lib/core/Handles/HandlesImports.vp
|
||||
63a3d17e96a083ac:lib/core/Handles/HandlesBase.vp
|
||||
657e182b27c2a022:includes/ast\stmts.vp
|
||||
692919c5a194ac8d:includes/llvmlite\__module.vp
|
||||
6a19179426e9a883:lib/__init__.vp
|
||||
6b3bc463fd044545:includes/llvmlite\__verify.vp
|
||||
6ff26590374ae6fc:includes/hashlib\__sha512.vp
|
||||
71e0a3ffcb3ebfad:includes/stdarg.vp
|
||||
72dbbb563aa943b0:includes/w32\fileio.vp
|
||||
7cadfe07e983fd90:includes/_list.vp
|
||||
81eb28ba912467a6:lib/core/Handles/HandlesBody.vp
|
||||
874bac141c97bae9:includes/llvmlite\__function.vp
|
||||
8d6185cf886c0334:lib/core/IncludesScanner.vp
|
||||
8dc65d4c71e2936a:lib/core/Handles/HandlesWhile.vp
|
||||
96837bcc64032444:includes/hashlib\__init__.vp
|
||||
9dbc46e5249ed198:lib/core/StubMerger.vp
|
||||
a335eb99f2e34479:includes/subprocess.vp
|
||||
a38b726f4a82545f:lib/core/BuildPipeline.vp
|
||||
a5e9a83e9db303ad:includes/linkedlist.vp
|
||||
aa246c6e6aa30484:includes/atom.vp
|
||||
aa45364399b86a03:lib/core/Handles/HandlesClassDef.vp
|
||||
af1cc6aaab47a7d1:lib/core/Handles/HandlesType.vp
|
||||
af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.vp
|
||||
b370d93b74bf55cc:includes/argparse.vp
|
||||
b543bc1dfb592119:includes/ast\exprs.vp
|
||||
b547ac4f380bddb6:includes/ast\tokens.vp
|
||||
b57252077e6b596b:includes/platmacro.vp
|
||||
bbdf3bbd4c3bc28c:includes/w32\win32console.vp
|
||||
bde6b4cc0847ee6d:lib/core/Handles/HandlesExpr.vp
|
||||
bdf5730851fb95f2:lib/core/VLogger.vp
|
||||
be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.vp
|
||||
c0042adc0b7ec5df:lib/Projectrans/Config.vp
|
||||
c1bb03b1eae141e0:lib/core/Phase2.vp
|
||||
c9d54a4158f7f5a8:includes/hashlib\__sha256.vp
|
||||
c9f4be41ca1cc2b4:includes/viperio.vp
|
||||
ca40915f11b8b6ad:includes/memhub.vp
|
||||
cb1aa3a78af6f362:lib/core/Handles/HandlesVar.vp
|
||||
e217def267d3d4a8:includes/ast\lexer.vp
|
||||
e307a2d809cef071:includes/viperlib.vp
|
||||
efefa18c5d6c2d81:lib/core/Handles/HandlesExprCall.vp
|
||||
f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.vp
|
||||
f3444ec56937284f:includes/ast\__init__.vp
|
||||
f4cdbca2f8802c12:lib/core/Handles/HandlesIf.vp
|
||||
f5522571bcce7bcb:includes/stdint.vp
|
||||
f6b51804a0ba8ff0:includes/w32\win32file.vp
|
||||
f9e36e2cd6fa659f:includes/llvmlite\__values.vp
|
||||
fc26f66203d7cbb7:lib/core/Phase1.vp
|
||||
fc980acec33d69a7:includes/w32\win32base.vp
|
||||
fde6db0747bdd959:includes/ast\parser.vp
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from lib.core.Handles.HandlesNonlocal.py
|
||||
Module: lib.core.Handles.HandlesNonlocal
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import ast
|
||||
import llvmlite
|
||||
import memhub
|
||||
import string
|
||||
import stdio
|
||||
import lib.core.Handles.HandlesTranslator as HT
|
||||
import lib.core.Handles.HandlesVar as HandlesVar
|
||||
|
||||
def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: pass
|
||||
|
||||
def load_nonlocal_var(trans: HT.Translator | t.CPtr, name: str) -> llvmlite.Value | t.CPtr: pass
|
||||
|
||||
def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr, name: str) -> llvmlite.Value | t.CPtr: pass
|
||||
@@ -1,166 +0,0 @@
|
||||
"""
|
||||
Auto-generated Python stub file from ast.tokens.py
|
||||
Module: ast.tokens
|
||||
"""
|
||||
|
||||
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
|
||||
class TokenType(t.CEnum):
|
||||
EndMarker: t.State
|
||||
NewLine: t.State
|
||||
Indent: t.State
|
||||
Dedent: t.State
|
||||
Name: t.State
|
||||
Number: t.State
|
||||
String: t.State
|
||||
FStringStart: t.State
|
||||
FStringMiddle: t.State
|
||||
FStringEnd: t.State
|
||||
Op: t.State
|
||||
Nl: t.State
|
||||
Comment: t.State
|
||||
Encoding: t.State
|
||||
class Keyword(t.CEnum):
|
||||
NotKeyword: t.State
|
||||
False_: t.State
|
||||
None_: t.State
|
||||
True_: t.State
|
||||
And: t.State
|
||||
As: t.State
|
||||
Assert: t.State
|
||||
Async: t.State
|
||||
Await: t.State
|
||||
Break: t.State
|
||||
Class: t.State
|
||||
Continue: t.State
|
||||
Def: t.State
|
||||
Del: t.State
|
||||
Elif: t.State
|
||||
Else: t.State
|
||||
Except: t.State
|
||||
Finally: t.State
|
||||
For: t.State
|
||||
From: t.State
|
||||
Global: t.State
|
||||
If: t.State
|
||||
Import: t.State
|
||||
In: t.State
|
||||
Is: t.State
|
||||
Lambda: t.State
|
||||
Nonlocal: t.State
|
||||
Not: t.State
|
||||
Or: t.State
|
||||
Pass: t.State
|
||||
Raise: t.State
|
||||
Return: t.State
|
||||
Try: t.State
|
||||
While: t.State
|
||||
With: t.State
|
||||
Yield: t.State
|
||||
Match: t.State
|
||||
Case: t.State
|
||||
Type: t.State
|
||||
class TokOp(t.CEnum):
|
||||
LPar: t.State
|
||||
RPar: t.State
|
||||
Lsqb: t.State
|
||||
Rsqb: t.State
|
||||
LBrace: t.State
|
||||
RBrace: t.State
|
||||
Comma: t.State
|
||||
Colon: t.State
|
||||
Dot: t.State
|
||||
Semi: t.State
|
||||
At: t.State
|
||||
Equal: t.State
|
||||
RArrow: t.State
|
||||
PlusEq: t.State
|
||||
MinusEq: t.State
|
||||
StarEq: t.State
|
||||
SlashEq: t.State
|
||||
DSlashEq: t.State
|
||||
PercentEq: t.State
|
||||
AtEq: t.State
|
||||
AmpEq: t.State
|
||||
VBarEq: t.State
|
||||
CaretEq: t.State
|
||||
GtGtEq: t.State
|
||||
LtLtEq: t.State
|
||||
StarEqEq: t.State
|
||||
DSlash: t.State
|
||||
StarStar: t.State
|
||||
LtLt: t.State
|
||||
GtGt: t.State
|
||||
LessEq: t.State
|
||||
GreaterEq: t.State
|
||||
EqEq: t.State
|
||||
ExclaimEq: t.State
|
||||
Less: t.State
|
||||
Greater: t.State
|
||||
Plus: t.State
|
||||
Minus: t.State
|
||||
Star: t.State
|
||||
Slash: t.State
|
||||
Percent: t.State
|
||||
Amp: t.State
|
||||
VBar: t.State
|
||||
Caret: t.State
|
||||
Tilde: t.State
|
||||
ColonEq: t.State
|
||||
Ellipsis: t.State
|
||||
Bang: t.State
|
||||
class Token:
|
||||
type: t.CInt
|
||||
op_subtype: t.CInt
|
||||
kw_subtype: t.CInt
|
||||
str_val: str
|
||||
int_val: t.CInt64T
|
||||
float_val: t.CDouble
|
||||
is_float: t.CInt
|
||||
is_complex: t.CInt
|
||||
lineno: t.CInt
|
||||
col_offset: t.CInt
|
||||
end_lineno: t.CInt
|
||||
end_col_offset: t.CInt
|
||||
next: Token | t.CPtr
|
||||
def __new__(self: Token, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
class KwEntry:
|
||||
name: str
|
||||
kw_id: t.CInt
|
||||
next: KwEntry | t.CPtr
|
||||
def __new__(self: KwEntry, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
_kw_head: t.CExtern | KwEntry | t.CPtr
|
||||
_kw_pool: t.CExtern | memhub.MemManager | t.CPtr
|
||||
|
||||
def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt) -> t.CInt: pass
|
||||
|
||||
def _kw_lookup(name: str) -> t.CInt: pass
|
||||
|
||||
def _init_keywords(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
|
||||
class OpEntry:
|
||||
name: str
|
||||
op_id: t.CInt
|
||||
length: t.CInt
|
||||
next: OpEntry | t.CPtr
|
||||
def __new__(self: OpEntry, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
_op_head: t.CExtern | OpEntry | t.CPtr
|
||||
|
||||
def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt) -> t.CInt: pass
|
||||
|
||||
def _init_operators(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def _init_tables(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass
|
||||
|
||||
def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt, col_offset: t.CInt) -> Token | t.CPtr: pass
|
||||
|
||||
def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, src: str, start: t.CSizeT, length: t.CSizeT) -> t.CInt: pass
|
||||
|
||||
def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, text: str) -> t.CInt: pass
|
||||
Loaded 100 of 322 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user