将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名

This commit is contained in:
2026-07-30 16:33:56 +08:00
parent f79c8ca643
commit cfc30d735c
322 changed files with 246 additions and 31772 deletions

View File

@@ -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_buildtemp 和 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/../includesOS 解析为 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}/tempOutputDir = {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

View File

@@ -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_sha1hashlib.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

View File

@@ -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',
]

View File

@@ -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

View File

@@ -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_irNone 失败
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 合并到 stdoutresult.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

View File

@@ -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.CPtri8** 语义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.CPtri8** 语义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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
# 方法不在当前模块中时,检查类(含父类)是否有 SHA1stub 可能未注入)
# 优先用类型指针定位 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: Countertranslate_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

View File

@@ -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

View File

@@ -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. 创建 declareIsDeclared=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

View File

@@ -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

View File

@@ -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源模块中的真实函数名
# 无别名时返回 Nonelocal_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 时,
# 记录当前模块(通过 ModuleSha1re-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 Ylevel=1, module="X")在包 pkg 中:
# 解析为 "pkg.X"
# 对于 from . import Ylevel=1, module=None在包 pkg 中:
# 解析为 "pkg"
# 对于 from ..X import Ylevel=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_importsasname: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

View File

@@ -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=2import扫描模式时跳过只处理 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=2import扫描模式时跳过
# _declare_only=1struct注册模式时只处理 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=1struct注册模式时只处理 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

View File

@@ -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)

View File

@@ -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 类型与函数返回类型匹配
# 处理 i1bool 比较结果)→ i8t.CBool等情况
# i1 → 更宽整数用 zextbool 语义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

View File

@@ -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() 创建包装 maintrans 单参)"""
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 池耗尽(每文件 128KB60+ 文件会耗尽 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
# 原地去除 \rCRLF → 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

View File

@@ -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/uniondeclare_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 == 1text.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
# 尝试 BuildCombinedIRstub/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_bufPhase 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_setPhase 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

View File

@@ -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

View File

@@ -1,9 +0,0 @@
import t, c
from stdint import *
# ============================================================
# core 包入口
#
# 子模块通过绝对导入使用import lib.core.X as X
# 此 __init__.py 不做 re-export避免引入未使用的依赖。
# ============================================================

View File

@@ -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:
# 手动复制文件名并追加 .exeviperlib.snprintf 不支持 %.*sstring 无 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -1,6 +0,0 @@
import stdio
def simple_test() -> int:
stdio.printf("hello\n")
return 0

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -1,83 +0,0 @@
import stdio
import t, c
import string
from inherit_test import Animal, Dog
# ============================================================
# 虚分派测试:通过虚表指针验证虚分派机制
#
# 本测试验证:方法调用通过对象的 __vtable__ 字段进行虚分派,
# 而非通过变量声明类型直接调用。
#
# 测试方法:
# 1. 创建 Animal 对象 aAnimal 虚表Speak 返回 0
# 2. 创建 Dog 对象 d
# 3. 用内联汇编将 d 的虚表指针复制到 a
# 4. 调用 a.Speak() — 应返回 1Dog.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 没有覆盖 GetNameDog 虚表中 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
{"WhileHandle": "while 循环语句处理器:继承 Mixin 获得 Trans 回指针", "WhileHandle.Handle": "翻译 while 循环语句"}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
{"IfHandle": "if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针", "IfHandle.Handle": "翻译 if/elif/else 语句"}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -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.

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More