基本稳定

This commit is contained in:
TermiNexus committed 2026-08-05 20:11:38 +08:00
1 parent 0a10b20dde
commit a39b5da0f8
27 files changed
+392 -962

No files matched your search

-1
View File
@@ -1 +0,0 @@
{"D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Config.vp": {"sha1": "c0042adc0b7ec5df", "mtime": 1785332415.2264168, "size": 14060}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Utils.vp": {"sha1": "4650533467115342", "mtime": 1785332415.2054548, "size": 4900}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\Converter.vp": {"sha1": "edfb76eb5b11cb51", "mtime": 1785470008.8908188, "size": 36399}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\VpiReader.vp": {"sha1": "3395dd5ebf7032b7", "mtime": 1785688467.8441546, "size": 21045}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.vp": {"sha1": "c2a4277744568003", "mtime": 1785424554.7031634, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.vp": {"sha1": "0029b86ca4ba3c8a", "mtime": 1785469972.0876107, "size": 25400}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.vp": {"sha1": "b7705a803012e701", "mtime": 1785478290.7112954, "size": 25035}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.vp": {"sha1": "4614c82057c20ce0", "mtime": 1785612002.0288458, "size": 26204}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.vp": {"sha1": "0d60272ffec7421e", "mtime": 1785478333.5054357, "size": 14418}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBase.vp": {"sha1": "63a3d17e96a083ac", "mtime": 1785332415.2080498, "size": 8740}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBody.vp": {"sha1": "144543e5c3a8e884", "mtime": 1785500799.3788817, "size": 10543}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.vp": {"sha1": "22b233500a91b82a", "mtime": 1785688461.7589297, "size": 147577}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.vp": {"sha1": "d8379d695f0ce7ea", "mtime": 1785598131.284988, "size": 8533}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.vp": {"sha1": "ebe9603dbffb6a35", "mtime": 1785478439.6070976, "size": 155333}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.vp": {"sha1": "1d86dddccc01909b", "mtime": 1785688462.1500714, "size": 296707}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.vp": {"sha1": "ede39cea216a347e", "mtime": 1785478524.0725746, "size": 13507}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFor.vp": {"sha1": "456fb516ba3c5002", "mtime": 1785332415.1896677, "size": 17319}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFunctions.vp": {"sha1": "f33eba0679c883b5", "mtime": 1785580039.9426627, "size": 49481}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesIf.vp": {"sha1": "f4cdbca2f8802c12", "mtime": 1785390159.3673935, "size": 5626}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesImports.vp": {"sha1": "c34e22cc668c6a6e", "mtime": 1785424554.7057025, "size": 25292}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMain.vp": {"sha1": "4a7b57e6bd18f65e", "mtime": 1785332415.1935978, "size": 21362}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMatch.vp": {"sha1": "4eb645a9b00ea530", "mtime": 1785688462.3238158, "size": 39328}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.vp": {"sha1": "3e7835a9deb60427", "mtime": 1785485362.3779018, "size": 7459}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.vp": {"sha1": "9224f6a9c894a6cf", "mtime": 1785478537.512802, "size": 6346}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.vp": {"sha1": "d539c830f47d8334", "mtime": 1785688462.3561263, "size": 48050}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.vp": {"sha1": "d064df0bb07fe1ff", "mtime": 1785688462.4070482, "size": 24182}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.vp": {"sha1": "6a25d9b413498b72", "mtime": 1785608629.9467041, "size": 80761}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.vp": {"sha1": "ea374464a0b93230", "mtime": 1785474869.3558953, "size": 16575}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesWhile.vp": {"sha1": "8dc65d4c71e2936a", "mtime": 1785390170.5239043, "size": 5202}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\IncludesScanner.vp": {"sha1": "55be14b41dd7ca15",Line truncated
-82
View File
@@ -1,82 +0,0 @@
0029b86ca4ba3c8a:lib/core/BuildPipeline.vp
067c78e9f121dce3:includes/w32\win32process.vp
06f53cc594b4ac6c:includes/w32\win32sync.vp
0bae3da2213d51e9:lib/core/StubMerger.vp
0c67644125bea0fd:includes/sys.vp
0d60272ffec7421e:lib/core/Handles/HandlesAugAssign.vp
0df65b8ed15664b0:includes/hashlib\__sha1.vp
144543e5c3a8e884:lib/core/Handles/HandlesBody.vp
19f8024d10c828e8:includes/hashlib\__md5.vp
1d86dddccc01909b:lib/core/Handles/HandlesExprCall.vp
20cd49775c100a38:includes/json\__writer.vp
22b233500a91b82a:lib/core/Handles/HandlesClassDef.vp
22bc0df83b3f0e62:includes/ast\base.vp
240a9a4157959a9f:includes/json\__parser.vp
285b6aa29a34754d:includes/stdio.vp
28de517e3820658a:includes/posix.vp
295b7ed2c244f309:includes/llvmlite\__types.vp
2b77d783c41d21d1:includes/hashtable.vp
3395dd5ebf7032b7:lib/StubGen/VpiReader.vp
33d64eeb99369a85:includes/llvmlite\__init__.vp
3aa6057398be5673:includes/stdlib.vp
3e7835a9deb60427:lib/core/Handles/HandlesNonlocal.vp
4337fb260448bbe2:includes/ast\astaux.vp
456fb516ba3c5002:lib/core/Handles/HandlesFor.vp
4614c82057c20ce0:lib/core/Handles/HandlesAssign.vp
4650533467115342:lib/Projectrans/Utils.vp
4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.vp
4dd6b3f1427d1cc5:includes/ast\match.vp
4eb645a9b00ea530:lib/core/Handles/HandlesMatch.vp
55be14b41dd7ca15:lib/core/IncludesScanner.vp
63a3d17e96a083ac:lib/core/Handles/HandlesBase.vp
657e182b27c2a022:includes/ast\stmts.vp
692919c5a194ac8d:includes/llvmlite\__module.vp
6a25d9b413498b72:lib/core/Handles/HandlesType.vp
6b3bc463fd044545:includes/llvmlite\__verify.vp
6ddf430432a0e373:includes/json\__init__.vp
6ff26590374ae6fc:includes/hashlib\__sha512.vp
71e0a3ffcb3ebfad:includes/stdarg.vp
72dbbb563aa943b0:includes/w32\fileio.vp
7cadfe07e983fd90:includes/_list.vp
874bac141c97bae9:includes/llvmlite\__function.vp
8a526c65749808c5:lib/core/Phase1.vp
8dc65d4c71e2936a:lib/core/Handles/HandlesWhile.vp
9224f6a9c894a6cf:lib/core/Handles/HandlesReturn.vp
96837bcc64032444:includes/hashlib\__init__.vp
a335eb99f2e34479:includes/subprocess.vp
a5e9a83e9db303ad:includes/linkedlist.vp
a6c58174a4b03877:main.vp
a7748ef067f79205:includes/llvmlite\__builder.vp
aa246c6e6aa30484:includes/atom.vp
b370d93b74bf55cc:includes/argparse.vp
b543bc1dfb592119:includes/ast\exprs.vp
b547ac4f380bddb6:includes/ast\tokens.vp
b57252077e6b596b:includes/platmacro.vp
b7705a803012e701:lib/core/Handles/HandlesAnnAssign.vp
bbdf3bbd4c3bc28c:includes/w32\win32console.vp
bdf5730851fb95f2:lib/core/VLogger.vp
c0042adc0b7ec5df:lib/Projectrans/Config.vp
c2a4277744568003:lib/__init__.vp
c2d8b39bbdb8380a:includes/memhub.vp
c34e22cc668c6a6e:lib/core/Handles/HandlesImports.vp
c9d54a4158f7f5a8:includes/hashlib\__sha256.vp
c9f4be41ca1cc2b4:includes/viperio.vp
d064df0bb07fe1ff:lib/core/Handles/HandlesTranslator.vp
d539c830f47d8334:lib/core/Handles/HandlesStruct.vp
d8379d695f0ce7ea:lib/core/Handles/HandlesEnum.vp
e217def267d3d4a8:includes/ast\lexer.vp
ea374464a0b93230:lib/core/Handles/HandlesVar.vp
ebe9603dbffb6a35:lib/core/Handles/HandlesExpr.vp
ede39cea216a347e:lib/core/Handles/HandlesExprOps.vp
edfb76eb5b11cb51:lib/StubGen/Converter.vp
f33eba0679c883b5:lib/core/Handles/HandlesFunctions.vp
f34071b7cf6c8158:lib/core/Phase2.vp
f3444ec56937284f:includes/ast\__init__.vp
f4cdbca2f8802c12:lib/core/Handles/HandlesIf.vp
f5522571bcce7bcb:includes/stdint.vp
f6ab8989f3545e83:includes/viperlib.vp
f6b51804a0ba8ff0:includes/w32\win32file.vp
f9e36e2cd6fa659f:includes/llvmlite\__values.vp
fc980acec33d69a7:includes/w32\win32base.vp
fde6db0747bdd959:includes/ast\parser.vp
ffaf70367668b227:includes/string.vp
Binary file not shown.
-84
View File
@@ -1,84 +0,0 @@
# -*- coding: utf-8 -*-
import pathlib
# 1. VpiReader.vp
p = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\StubGen\VpiReader.vp')
c = p.read_text(encoding='utf-8')
lines = c.split('\n')
new_lines = []
skip = False
for i, line in enumerate(lines):
if 'DEBUG: sha1_buf length mismatch' in line:
skip = True
# also skip preceding lines
while new_lines and ('_buflen' in new_lines[-1] or 'sha1_buf' in new_lines[-1] or len(new_lines[-1].strip()) == 0 or new_lines[-1].strip().startswith('#')):
new_lines.pop()
continue
if skip:
if 'sys.exit(1)' in line:
skip = False
continue
if 'stdio.' in line or '_buflen' in line:
continue
if line.strip() == '' or line.strip().startswith('if _buflen'):
continue
skip = False
new_lines.append(line)
p.write_text('\n'.join(new_lines), encoding='utf-8')
print('VpiReader.vp done')
# 2. HandlesFunctions.vp
p2 = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\core\Handles\HandlesFunctions.vp')
c2 = p2.read_text(encoding='utf-8')
lines2 = c2.split('\n')
new_lines2 = []
skip2 = False
for line in lines2:
if 'DEBUG: double-dot in _mangle_name' in line:
skip2 = True
while new_lines2 and ('_mi' in new_lines2[-1] or 'mangled[_mi' in new_lines2[-1] or 'stdio.' in new_lines2[-1] or 'sys.exit' in new_lines2[-1] or new_lines2[-1].strip().startswith('#')):
new_lines2.pop()
continue
if skip2:
if 'sys.exit(1)' in line:
skip2 = False
continue
if 'stdio.' in line or '_mi' in line or 'mangled[_mi' in line or line.strip().startswith('if mangled'):
continue
if line.strip() == '' or line.strip() == 'return mangled':
if line.strip() == 'return mangled':
new_lines2.append(line)
skip2 = False
continue
skip2 = False
new_lines2.append(line)
p2.write_text('\n'.join(new_lines2), encoding='utf-8')
print('HandlesFunctions.vp done')
# 3. HandlesExprCall.vp
p3 = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\core\Handles\HandlesExprCall.vp')
c3 = p3.read_text(encoding='utf-8')
lines3 = c3.split('\n')
new_lines3 = []
skip3 = False
for line in lines3:
if 'DEBUG: double-dot in call_name' in line:
skip3 = True
while new_lines3 and ('_cni' in new_lines3[-1] or 'call_name[_cni' in new_lines3[-1] or 'stdio.' in new_lines3[-1] or 'sys.exit' in new_lines3[-1] or new_lines3[-1].strip().startswith('#')):
new_lines3.pop()
continue
if skip3:
if 'sys.exit(1)' in line:
skip3 = False
continue
if 'stdio.' in line or '_cni' in line or 'call_name[_cni' in line or line.strip().startswith('if call_name'):
continue
if line.strip() == '' or line.strip().startswith('#'):
if line.strip().startswith('#'):
new_lines3.append(line)
skip3 = False
continue
skip3 = False
new_lines3.append(line)
p3.write_text('\n'.join(new_lines3), encoding='utf-8')
print('HandlesExprCall.vp done')
-197
View File
@@ -1,197 +0,0 @@
import tkinter as tk
from tkinter import scrolledtext
import subprocess
import threading
import sys
import os
import queue
import time
class ConsoleApp:
def __init__(self, root, args):
self.root = root
self.args = args
self.proc = None
self.output_queue = queue.Queue()
# 获取系统当前编码,尽量保证原样输出
self.encoding = sys.stdout.encoding or 'utf-8'
# 记录最后一次收到输出的时间
self.last_output_time = time.time()
root.title("AI 交互终端")
root.geometry("900x600")
# GUI 布局
# 输出区域
self.text_area = scrolledtext.ScrolledText(root, wrap=tk.WORD, font=("Consolas", 10))
self.text_area.pack(expand=True, fill='both', padx=5, pady=5)
# 输入区域
input_frame = tk.Frame(root)
input_frame.pack(fill='x', padx=5, pady=5)
self.entry = tk.Entry(input_frame, font=("Consolas", 10))
self.entry.pack(side=tk.LEFT, expand=True, fill='x')
self.entry.bind('<Return>', self.send_input)
# 说话模式复选框
self.speak_mode = tk.BooleanVar(value=False)
self.speak_check = tk.Checkbutton(input_frame, text="提示AI(说话)", variable=self.speak_mode, font=("Consolas", 9))
self.speak_check.pack(side=tk.RIGHT, padx=5)
self.kill_btn = tk.Button(input_frame, text="强制终止进程", command=self.force_terminate, bg="red", fg="white")
self.kill_btn.pack(side=tk.RIGHT, padx=5)
# 状态栏 (用于显示无输出时长)
status_frame = tk.Frame(root)
status_frame.pack(fill='x', padx=5, pady=(0, 5))
self.time_label = tk.Label(status_frame, text="无输出时长: 00:00", font=("Consolas", 10), fg="gray")
self.time_label.pack(side=tk.RIGHT)
# 启动子进程 (合并 stderr 到 stdout)
try:
self.proc = subprocess.Popen(
self.args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=0 # 无缓冲,确保实时性
)
except Exception as e:
print(f"启动进程失败: {e}")
sys.exit(1)
# 启动读取子进程输出的线程
self.output_thread = threading.Thread(target=self.read_output, daemon=True)
self.output_thread.start()
# 启动读取当前脚本控制台输入的线程 (允许直接在终端输入)
self.stdin_thread = threading.Thread(target=self.read_stdin, daemon=True)
self.stdin_thread.start()
# 窗口关闭事件
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
# 开始轮询队列更新GUI
self.update_gui()
def read_output(self):
"""后台线程:实时读取子进程的输出"""
fd = self.proc.stdout.fileno()
while True:
try:
byte_data = os.read(fd, 1024)
if not byte_data:
break # 进程结束
# 只要收到数据,就更新最后输出时间
self.last_output_time = time.time()
# 1. 实时输出到当前脚本的 stdout (不加任何前缀)
sys.stdout.buffer.write(byte_data)
sys.stdout.buffer.flush()
# 2. 放入队列供 GUI 使用
try:
text = byte_data.decode(self.encoding, errors='replace')
except:
text = byte_data.decode('utf-8', errors='replace')
self.output_queue.put(text)
except OSError:
break # 管道已关闭
def read_stdin(self):
"""后台线程:实时读取宿主控制台的 stdin 并转发给子进程"""
while True:
line = sys.stdin.readline()
if not line:
break
try:
self.proc.stdin.write(line.encode(self.encoding, errors='replace'))
self.proc.stdin.flush()
except:
break
def send_input(self, event):
"""GUI 输入框回车事件"""
text = self.entry.get()
self.entry.delete(0, tk.END)
if not text:
return
# 如果勾选了"提示AI",则直接输出到当前脚本的 stdout,不发给子进程
if self.speak_mode.get():
speak_text = text + '\n'
# 输出到当前脚本控制台,供 AI 捕获
sys.stdout.buffer.write(speak_text.encode(self.encoding, errors='replace'))
sys.stdout.buffer.flush()
# 在 GUI 中回显,让用户知道说了什么(使用不同颜色区分)
self.text_area.insert(tk.END, speak_text, 'speak_tag')
self.text_area.tag_config('speak_tag', foreground="blue")
self.text_area.see(tk.END)
else:
# 正常模式:发给子进程
text += '\n'
try:
self.proc.stdin.write(text.encode(self.encoding, errors='replace'))
self.proc.stdin.flush()
except Exception as e:
self.output_queue.put(f"\n[输入发送失败: {e}]\n")
def force_terminate(self):
"""强制终止子进程"""
if self.proc and self.proc.poll() is None:
print("用户终止了应用程序") # 输出到控制台 stdout
self.output_queue.put("\n[用户终止了应用程序]\n")
self.proc.kill()
def on_closing(self):
"""关闭窗口时终止子进程"""
if self.proc and self.proc.poll() is None:
self.proc.kill()
self.root.destroy()
def update_gui(self):
"""主线程:从队列获取数据并更新GUI"""
try:
while True:
text = self.output_queue.get_nowait()
self.text_area.insert(tk.END, text)
self.text_area.see(tk.END)
except queue.Empty:
pass
# 计算并更新无输出时长
if self.proc and self.proc.poll() is None:
idle_seconds = int(time.time() - self.last_output_time)
mins = idle_seconds // 60
secs = idle_seconds % 60
self.time_label.config(text=f"无输出时长: {mins:02d}:{secs:02d}")
else:
self.time_label.config(text="进程已结束")
# 检查进程是否已结束
if self.proc and self.proc.poll() is not None:
if self.output_queue.empty():
self.kill_btn.config(state=tk.DISABLED, bg="grey", text="进程已结束")
# 进程结束且输出已读取完毕,自动关闭程序
self.root.destroy()
return # 停止轮询
# 每 200ms 轮询一次 (减少CPU占用,时间显示不需要50ms那么频繁)
self.root.after(200, self.update_gui)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("用法: python ai_console.py <command> [args...]")
print("示例: python ai_console.py cmd")
sys.exit(1)
root = tk.Tk()
app = ConsoleApp(root, sys.argv[1:])
root.mainloop()
+1 -1
View File
@@ -17,7 +17,7 @@ from .base import (
_init_ast, _copy_str, _set_pos, _inherit_pos, _set_parent_list,
_binop_from_op, _augop_from_op, _cmpop_from_op,
_emit, _emit_str, _emit_int, _dump_list,
dump,
dump, _op_name,
)
# 语句节点
from .stmts import (
+8
View File
@@ -553,6 +553,14 @@ def _read_string(lx: Lexer | t.CPtr):
conv_buf[wpos] = '\t'
elif next_ch == 'r':
conv_buf[wpos] = '\r'
elif next_ch == 'f':
conv_buf[wpos] = '\f'
elif next_ch == 'v':
conv_buf[wpos] = '\v'
elif next_ch == 'a':
conv_buf[wpos] = '\a'
elif next_ch == 'b':
conv_buf[wpos] = '\b'
elif next_ch == '\\':
conv_buf[wpos] = '\\'
elif next_ch == '\'':
+1 -1
View File
@@ -154,7 +154,7 @@ def a2b_hex(hexstr: str, length: t.CInt) -> str:
out[oi] = '\0'
return out
def unhexlify(data: str, length: t.CInt):
def unhexlify(data: str, length: t.CInt) -> bytes:
return a2b_hex(data, length)
def b2a_base64(data: str, length: t.CInt) -> str:
+4 -4
View File
@@ -504,10 +504,10 @@ def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, "global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
TypePrint(ty_buf, 512, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
# 初始化值
@@ -541,10 +541,10 @@ def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, " = external global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
TypePrint(ty_buf, 512, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
+179 -8
View File
@@ -4,6 +4,7 @@ import viperlib
import string
import memhub
import stdio
import stdlib
from linkedlist import GSListNode
@@ -383,8 +384,23 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
pool 用于递归打印子类型时分配临时缓冲区。
"""
_TypePrintDepth(buf, size, ty, pool, 0)
# 递归深度上限:悬空/自引用的 LLVMType 树(1b reset 后内存被复用)会导致
# Ptr(pointee)/Struct(fields)/Func(params) 无限递归,每次递归分配临时缓冲
# 造成 OOM(单文件暴涨 900MB 根因)。超过 100 层即停止打印。
TYPEPRINT_MAX_DEPTH: t.CDefine = 100
def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt):
"""带递归深度上限的 TypePrint 内部实现"""
if ty is None or buf is None or size == 0:
return
if depth >= TYPEPRINT_MAX_DEPTH:
viperlib.snprintf(buf, size, "...")
return
buf[0] = '\0'
match ty:
case LLVMType.Int(bits):
@@ -400,7 +416,10 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
match pointee:
case LLVMType.Struct(sfields, sfcount, sname):
if sname is not None:
viperlib.snprintf(buf, size, "%%\"%s\"*", sname)
# 悬空防护:sname 可能指向被 reset 回收/部分复用的 pool 内存,
# 用受限打印避免读越界崩溃;完整名在 vtable 生成后由
# TypeStr 兜底(stdlib 深拷贝,跨 reset 存活)
viperlib.snprintf(buf, size, "%%\"%.40s\"*", sname)
return
case LLVMType.Void():
# Ptr(Void) → i8*(LLVM IR void* 非法)
@@ -419,7 +438,7 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
string.strcpy(buf, "i8*")
return
# 通用路径: 递归打印 pointee 后追加 '*'
TypePrint(buf, size, pointee, pool)
_TypePrintDepth(buf, size, pointee, pool, depth + 1)
pos: t.CSizeT = string.strlen(buf)
if pos + 1 < size:
buf[pos] = '*'
@@ -431,7 +450,7 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 嵌套指针/数组更易超过 128,使用 512 字节避免截断
tmp: t.CChar | t.CPtr = pool.alloc(512)
if tmp is not None:
TypePrint(tmp, 512, elem_ty, pool)
_TypePrintDepth(tmp, 512, elem_ty, pool, depth + 1)
_strappend(buf, size, tmp)
_strappend(buf, size, "]")
case LLVMType.Struct(fields, fcount, name):
@@ -440,20 +459,26 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
viperlib.snprintf(buf, size, "%%\"%s\"", name)
else:
# 匿名结构体: {ty1, ty2, ...}
_print_struct_body(buf, size, fields, pool)
_print_struct_body(buf, size, fields, pool, depth)
case LLVMType.Func(ret, params, count):
# ret (ty1, ty2, ...)
TypePrint(buf, size, ret, pool)
_TypePrintDepth(buf, size, ret, pool, depth + 1)
_strappend(buf, size, " (")
cur2: ParamNode | t.CPtr = params
first2: t.CInt = 1
_pc2: t.CInt = 0
# 函数参数类型可能为 SHA1 限定命名结构体指针,512 字节避免截断
tmp3: t.CChar | t.CPtr = pool.alloc(512)
while cur2 is not None:
# 悬空保护:参数链若被 reset 回收后内容复用,可能成环无限循环
_pc2 += 1
if _pc2 > 200:
_strappend(buf, size, "...)")
break
if first2 == 0:
_strappend(buf, size, ", ")
if tmp3 is not None:
TypePrint(tmp3, 512, cur2.Ty, pool)
_TypePrintDepth(tmp3, 512, cur2.Ty, pool, depth + 1)
_strappend(buf, size, tmp3)
cur2 = cur2.Next
first2 = 0
@@ -502,7 +527,8 @@ def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr)
# 供 TypePrint(匿名结构体)和 PrintStructDefinition(命名结构体定义行)复用
# ============================================================
def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt = 0):
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)
直接在 buf 当前末尾写入字段类型,避免 pool.alloc 返回与 buf 重叠的内存
@@ -515,13 +541,18 @@ def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
first: t.CInt = 1
fidx: t.CInt = 0
while cur is not None:
# 悬空保护:ParamNode 链若被 reset 回收后内容复用,Next 指针可能成环或
# 指向垃圾,无限循环。最多打印 200 个字段即停止,防止 OOM。
if fidx >= 200:
_strappend(buf, size, "...}")
return
if first == 0:
_strappend(buf, size, ", ")
# 直接在 buf 当前末尾位置写入字段类型
# TypePrint 首字节置 '\0' 是无害的(pos 处本来就是 '\0')
pos: t.CSizeT = string.strlen(buf)
if pos + 2 < size:
TypePrint(buf + pos, size - pos, cur.Ty, pool)
_TypePrintDepth(buf + pos, size - pos, cur.Ty, pool, depth + 1)
cur = cur.Next
first = 0
fidx += 1
@@ -574,4 +605,144 @@ def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
return None
def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
"""获取结构体的字段链表(供跨模块重建 Struct 类型用)"""
if ty is None:
return None
match ty:
case LLVMType.Struct(fields, fcount, name):
return fields
case _:
return None
def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
"""获取结构体的字段数量(供跨模块重建 Struct 类型用)"""
if ty is None:
return 0
match ty:
case LLVMType.Struct(fields, fcount, name):
return fcount
case _:
return 0
# ============================================================
# DeepCopyType - 深拷贝 LLVMType 到 stdlib 区(跨文件 reset 存活)
#
# 背景: 1b 阶段(mark1 之后)新注册的结构体(泛型特化类等),其
# struct_ty 是 pool 分配的 LLVMType,所在文件翻译完 reset_to(mark1)
# 后指针悬空。_struct_table 中的 entry.Ty 指向它,后续文件遍历
# _struct_table(find_struct_by_type/lookup_field 等)时解引用悬空
# 指针导致崩溃(0xC0000005)。
#
# 本函数递归拷贝整棵 LLVMType 树到 stdlib(含 ParamNode 字段链和
# 字符串名),保证 entry.Ty 跨文件永久存活。
#
# 注意: 自引用类型(如 Value 含 Ptr(Value) 字段)会导致无限递归,
# 用深度上限防护(超过即返回浅拷贝副本,后续不再递归)。
# ============================================================
DEEPCOPY_MAX_DEPTH: t.CDefine = 64
def DeepCopyType(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
"""深拷贝 LLVMType 到 stdlib 区(深度限制防自引用递归),失败返回 None"""
return _DeepCopyDepth(pool, ty, 0)
def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr, depth: t.CInt) -> LLVMType | t.CPtr:
"""带深度上限的深拷贝实现"""
if ty is None:
return None
new_ty: LLVMType | t.CPtr = (LLVMType | t.CPtr)(stdlib.malloc(LLVMType.__sizeof__()))
if new_ty is None:
return None
string.memset(new_ty, 0, LLVMType.__sizeof__())
if depth >= DEEPCOPY_MAX_DEPTH:
# 深度超限:浅拷贝 tag 后停止递归(复制当前变体但不深拷子类型)
match ty:
case LLVMType.Int(bits):
c.DerefAs(new_ty, LLVMType.Int(bits))
case LLVMType.Float(bits):
c.DerefAs(new_ty, LLVMType.Float(bits))
case LLVMType.Void():
c.DerefAs(new_ty, LLVMType.Void())
case LLVMType.Label():
c.DerefAs(new_ty, LLVMType.Label())
case LLVMType.Metadata():
c.DerefAs(new_ty, LLVMType.Metadata())
case _:
c.DerefAs(new_ty, LLVMType.Void())
return new_ty
match ty:
case LLVMType.Int(bits):
c.DerefAs(new_ty, LLVMType.Int(bits))
case LLVMType.Float(bits):
c.DerefAs(new_ty, LLVMType.Float(bits))
case LLVMType.Void():
c.DerefAs(new_ty, LLVMType.Void())
case LLVMType.Label():
c.DerefAs(new_ty, LLVMType.Label())
case LLVMType.Metadata():
c.DerefAs(new_ty, LLVMType.Metadata())
case LLVMType.Ptr(pointee):
c.DerefAs(new_ty, LLVMType.Ptr(_DeepCopyDepth(pool, pointee, depth + 1)))
case LLVMType.Array(elem_ty, count):
c.DerefAs(new_ty, LLVMType.Array(_DeepCopyDepth(pool, elem_ty, depth + 1), count))
case LLVMType.Func(ret, params, pcount):
c.DerefAs(new_ty, LLVMType.Func(
_DeepCopyDepth(pool, ret, depth + 1),
_DeepCopyParamChain(pool, params, depth + 1), pcount))
case LLVMType.Struct(fields, fcount, name):
c.DerefAs(new_ty, LLVMType.Struct(
_DeepCopyParamChain(pool, fields, depth + 1),
fcount, _DeepCopyStr(pool, name)))
case _:
stdlib.free(new_ty)
return None
return new_ty
def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
head: ParamNode | t.CPtr, depth: t.CInt) -> ParamNode | t.CPtr:
"""深拷贝 ParamNode 链表到 stdlib"""
if head is None:
return None
first: ParamNode | t.CPtr = None
prev: ParamNode | t.CPtr = None
cur: ParamNode | t.CPtr = head
guard: t.CInt = 0
while cur is not None:
guard += 1
if guard > 512:
break
node: ParamNode | t.CPtr = (ParamNode | t.CPtr)(stdlib.malloc(PNODE_SIZE))
if node is None:
break
string.memset(node, 0, PNODE_SIZE)
node.Ty = _DeepCopyDepth(pool, paramnode_get_ty(cur), depth + 1)
node.Next = None
if first is None:
first = node
if prev is not None:
prev.Next = node
prev = node
cur = paramnode_get_next(cur)
return first
def _DeepCopyStr(pool: memhub.MemBuddy | t.CPtr, s: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
"""深拷贝字符串到 stdlib"""
if s is None:
return None
slen: t.CSizeT = string.strlen(s)
copy: t.CChar | t.CPtr = stdlib.malloc(slen + 1)
if copy is None:
return None
string.strcpy(copy, s)
return copy
+116 -6
View File
@@ -4,7 +4,7 @@ import string
import atom
import viperio
import stdio
import sys
import stdlib
# ============================================================
# memhub - Unified memory management library
@@ -26,7 +26,6 @@ MEMBUDDY_MIN_BLOCK: t.CDefine = 32
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
MEMBUDDY_HEADER_SIZE: t.CDefine = 8
def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT:
if align == 0: return val
return (val + align - 1) & ~(align - 1)
@@ -134,7 +133,13 @@ class MemPool(MemManager):
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
if size == 0: return None
aligned: t.CSizeT = _align_up(size, MEMHUB_ALIGN)
if self.offset + aligned > self.size: return None
if self.offset + aligned > self.size:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败\n", size)
stdio.printf("[OOM] MemPool: total=%zu used=%zu (bump allocator, 无释放)\n",
self.size, self.offset)
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
stdlib.exit(1)
ptr: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(self.base) + self.offset, t.CPtr)
self.offset += aligned
if self.offset > self.high_water:
@@ -211,8 +216,18 @@ class MemSlab(MemManager):
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
# Slab mode: allocate one block only if requested size <= block_size
if self.free_list is None: return None
if size > self.block_size: return None
if self.free_list is None:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败(free_list 已空)\n", size)
stdio.printf("[OOM] MemSlab: block_size=%zu block_count=%zu used=%zu\n",
self.block_size, self.block_count, self.used_count)
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
stdlib.exit(1)
if size > self.block_size:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败(超过 block_size=%zu)\n", size, self.block_size)
stdio.printf("[OOM] 说明: 请求大小超过 MemSlab 块大小,应改用 MemBuddy/MemPool。\n")
stdlib.exit(1)
block: t.CVoid | t.CPtr = self.free_list
self.free_list = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
self.used_count += 1
@@ -254,6 +269,11 @@ class MemSlab(MemManager):
# MemBuddy - Buddy system allocator
# Free list head array stored at arena start; subsequent memory managed in power-of-two sized blocks
# Thread-safe (spinlock enabled), supports block coalescing
#
# Checkpoint 支持(供编译器等长任务回收阶段性分配):
# mark() → 返回当前分配水位(不分配内存)
# reset_to(m) → 释放水位 m 之后分配的所有块(回收到 free list)
# 记录栈从 usable 顶部预留 _CHK_RESERVE 字节,不参与 buddy 分配。
# ============================================================
class MemBuddy(MemManager):
# Override parent __provides__: MemBuddy provides both __mbuddy__ and __memmgr__.
@@ -265,6 +285,10 @@ class MemBuddy(MemManager):
lock_val: t.CVolatile | t.CInt # Spinlock
usable: t.CVoid | t.CPtr # Start of usable memory region (skips free_lists)
usable_size: t.CSizeT # Size of usable memory (power of two)
chk_stack: t.CUInt64T | t.CPtr # Checkpoint 分配记录栈(存 block 地址)
chk_cap: t.CSizeT # 记录栈容量(条目数)
chk_depth: t.CSizeT # 当前记录深度
chk_base: t.CVoid | t.CPtr # 记录栈起始地址(由 stdlib.malloc 分配,独立于 buddy 区)
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
self.base = base
@@ -274,6 +298,10 @@ class MemBuddy(MemManager):
self.lock_val = 0
self.usable = None
self.usable_size = 0
self.chk_stack = None
self.chk_cap = 0
self.chk_depth = 0
self.chk_base = None
self.lock_val = 0
fl_bytes: t.CSizeT = (MEMBUDDY_MAX_ORDERS + 1) * 8
@@ -291,6 +319,12 @@ class MemBuddy(MemManager):
return
remaining: t.CSizeT = size - fl_bytes
# 注意:不能在 __init__ 里预留 checkpoint 记录栈!
# buddy 区必须从 fl_bytes 后开始、大小必须是 2 的幂。
# 若预留 512KB,remaining = 2^30 - 512KB 不是 2 的幂,
# _largest_pow2_le 会取到 2^29 = 512MB,1GB 池直接砍半。
# 记录栈改为 mark() 时从 buddy 池懒分配(见 mark())。
usable: t.CSizeT = _largest_pow2_le(remaining)
if usable < MEMBUDDY_MIN_BLOCK:
@@ -312,6 +346,60 @@ class MemBuddy(MemManager):
# Entire usable memory region as a max_order free block
self._fl_push(self.max_order, self.usable)
# === Checkpoint support ===
def mark(self) -> t.CSizeT:
"""返回当前分配水位(checkpoint)
记录栈用 stdlib.malloc 分配(64K 条目 × 8B = 512KB,独立于 buddy 区),
首次调用时懒分配。这样不占用 buddy 池、不会把 1GB 池砍半、
reset_to 也不会误释放栈自身。
"""
if self.chk_stack is None:
# 记录栈用 stdlib.malloc 分配(独立于 buddy 区,避免占用 buddy 池、
# 避免 reset_to 误释放栈自身,也避免栈内存与 buddy 块重叠)。
cap: t.CSizeT = 64 * 1024
base: t.CVoid | t.CPtr = t.CVoid(stdlib.malloc(cap * 8), t.CPtr)
if base is None:
return 0
self.chk_base = base
self.chk_stack = (t.CUInt64T | t.CPtr)(t.CVoid(base, t.CPtr))
self.chk_cap = cap
self.chk_depth = 0
return self.chk_depth
def reset_to(self, mark: t.CSizeT):
"""释放水位 mark 之后分配的所有块,回收到 free list
栈中每个 block:若 header 仍标记为已分配(奇数),_coalesce 归还;
若已被单独 free(header==0),跳过避免重复归还。
"""
if self.chk_stack is None:
return
if mark >= self.chk_depth:
return
self._lock()
while self.chk_depth > mark:
self.chk_depth -= 1
block: t.CVoid | t.CPtr = t.CVoid(self.chk_stack[self.chk_depth], t.CPtr)
if block is None:
continue
stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
stored_val: t.CUInt64T = t.CUInt64T(stored)
if (stored_val & 1) == 0:
continue # 已被单独 free,跳过
order: t.CInt = t.CInt(stored_val >> 1)
if order < 0 or order > self.max_order:
continue
self._coalesce(block, order)
self._unlock()
def reset_all(self):
"""回收全部已分配块(等价 reset_to(0))"""
if self.chk_stack is None:
return
self.reset_to(0)
# === Free list operations ===
def _fl_push(self, order: t.CInt, block: t.CVoid | t.CPtr):
@@ -405,6 +493,24 @@ class MemBuddy(MemManager):
order: t.CInt = t.CInt(stored_val >> 1)
if order < 0: return 0
if order > self.max_order: return 0
# 记录栈一致性校验:分配时(alloc)每个 block 地址都会压入 chk_stack。
# reset_to(mark) 会把 [mark, chk_depth) 的块弹栈并归还 free list,
# 之后这些地址会被重新分配。若一个 header 恰好是合法奇数(假阳性),
# 但地址不在当前 chk_stack[0..chk_depth) 存活区间内,说明已被回收,
# 不能当作有效指针(否则 _format_func_type_str/TypePrint 会沿垃圾链
# 无限分配导致 OOM)。
# 注意:chk_stack 容量满(64K)后 alloc 不再记录新块(chk_depth==chk_cap),
# 此时无法区分,跳过校验(退化到仅 header 校验,避免误判正常 free)。
if self.chk_stack is not None and self.chk_depth < self.chk_cap:
alive: t.CInt = 0
ci: t.CSizeT = 0
while ci < self.chk_depth:
if self.chk_stack[ci] == t.CUInt64T(block):
alive = 1
break
ci += 1
if alive == 0:
return 0
return 1
# === Spinlock ===
@@ -430,6 +536,10 @@ class MemBuddy(MemManager):
if block is not None:
c.DerefAs(block, t.CVoid(t.CUInt64T((order << 1) | 1), t.CPtr))
result = t.CVoid(t.CUInt64T(block) + MEMBUDDY_HEADER_SIZE, t.CPtr)
# 记录到 checkpoint 栈(供 reset_to 回收)
if self.chk_stack is not None and self.chk_depth < self.chk_cap:
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
self.chk_depth += 1
if result is None:
# Allocation failure: print memory usage statistics and exit with OOM
fb: t.CSizeT = self.free_bytes()
@@ -439,7 +549,7 @@ class MemBuddy(MemManager):
stdio.printf("[OOM] 内存池: total=%zu used=%zu free=%zu free_blocks=%zu\n",
self.usable_size, ub, fb, self.free_count())
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
sys.exit(1)
stdlib.exit(1)
self._unlock()
return result
+21 -20
View File
@@ -7,106 +7,107 @@ import os._win32
import os._posix
# os 包入口
# 根据 platmacro.IS_WINDOWS 分派到 _win32 或 _posix 后端
# os.path 为跨平台纯字符串操作,直接可用
# os package entry point
# Dispatches to _win32 or _posix backend based on platmacro.IS_WINDOWS
# os.path is for cross-platform pure string operations, can be used directly
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
# Module-level global MBuddy pointer (initialized by the user in main)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# File/Directory Attribute Query
# =============================================================================
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
"""Check if the file/directory exists"""
if platmacro.IS_WINDOWS:
return os._win32.exists(path)
return os._posix.exists(path)
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
"""Check if the path is a directory"""
if platmacro.IS_WINDOWS:
return os._win32.isdir(path)
return os._posix.isdir(path)
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
"""Check if the path is a regular file"""
if platmacro.IS_WINDOWS:
return os._win32.isfile(path)
return os._posix.isfile(path)
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
"""Returns the file size (in bytes). Returns -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.getsize(path)
return os._posix.getsize(path)
# =============================================================================
# 工作目录
# Working Directory
# =============================================================================
def getcwd() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
"""Return the current working directory (memory allocated via _mbuddy)"""
if platmacro.IS_WINDOWS:
return os._win32.getcwd()
return os._posix.getcwd_impl()
def chdir(path: str) -> int:
"""切换当前工作目录。成功返回 0,失败返回 -1。"""
"""Switch the current working directory. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.chdir(path)
return os._posix.chdir_impl(path)
# =============================================================================
# 文件/目录操作
# File/Directory Operations
# =============================================================================
def mkdir(path: str) -> int:
"""创建目录。成功返回 0,失败返回 -1。"""
"""Create a directory. Returns 0 on success, -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.mkdir(path)
return os._posix.mkdir_impl(path)
def remove(path: str) -> int:
"""删除文件。成功返回 0,失败返回 -1。"""
"""Delete the file. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.remove(path)
return os._posix.remove(path)
def rmdir(path: str) -> int:
"""删除空目录。成功返回 0,失败返回 -1。"""
"""Delete empty directories. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.rmdir(path)
return os._posix.rmdir_impl(path)
def rename(old_path: str, new_path: str) -> int:
"""重命名/移动文件或目录。成功返回 0,失败返回 -1。"""
"""Rename/move a file or directory. Returns 0 on success, -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.rename(old_path, new_path)
return os._posix.rename_impl(old_path, new_path)
def chmod(path: str, mode: int) -> int:
"""修改文件权限。成功返回 0,失败返回 -1。
Windows 上只处理只读位(S_IWUSR);POSIX 上使用完整权限位。"""
"""Modify file permissions. Returns 0 on success, -1 on failure.
On Windows, only the read-only bit (S_IWUSR) is handled;
On POSIX, full permission bits are used."""
if platmacro.IS_WINDOWS:
return os._win32.chmod(path, mode)
return os._posix.chmod_impl(path, mode)
# =============================================================================
# 目录列举
# Table of Contents Listing
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
+1 -1
View File
@@ -193,7 +193,7 @@ def _rmtree_posix(path: str) -> int:
path_len: t.CSizeT = len(path)
result: int = 0
entry: posix.Dirent = posix.readdir(dirp)
entry: posix.Dirent | t.CPtr = posix.readdir(dirp)
while entry != None:
name: str = entry.d_name
# Skip . and ..
+2 -1
View File
@@ -6,4 +6,5 @@ def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def free(p: t.CVoid | t.CPtr) -> t.State: pass
def system(cmd: t.CConst | t.CChar | t.CPtr) -> INT | t.State: pass
def system(cmd: t.CConst | t.CChar | t.CPtr) -> INT | t.State: pass
def exit(status: int) -> t.State: pass
+1 -1
View File
@@ -385,5 +385,5 @@ class FileW:
def open(filename: str, mode: ULONG, share: ULONG = SHARE_READ) -> File | t.CPtr:
return File(filename, mode, share)
def openw(filename: LPCWSTR, mode: ULONG, share: ULONG = SHARE_READ) -> FileW | t.CPtr:
def openw(filename: w32.win32base.LPCWSTR, mode: ULONG, share: ULONG = SHARE_READ) -> FileW | t.CPtr:
return FileW(filename, mode, share)
+2
View File
@@ -1,3 +1,5 @@
# from string import memset, memcpy
# from stdio import malloc, free, calloc, realloc
from stdint import *
import zlib.zdeflate as zdeflate
import zlib.zinflate as zinflate
-1
View File
@@ -1,5 +1,4 @@
from stdint import *
import stddef
import string
import stdlib
import memhub
+1 -2
View File
@@ -3,10 +3,9 @@ import lib._bootstrap # noqa: F401 设置 sys.path(项目根 + lib/includes
from lib.core.VLogger import Logger, LogLevel, set_logger
# 创建全局日志实例
# 创建全局日志实例(仅控制台输出,不落盘,避免生成 build.log)
logger = Logger(
name="TransPyC",
log_file="build.log",
level=LogLevel.INFO,
use_colors=True
)
+5
View File
@@ -1442,6 +1442,11 @@ class AssignHandle(BaseHandle):
VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo)
if isinstance(VarType, ir.VoidType):
VarType = ir.IntType(32)
# 记录模块级注解类型:供函数内 global 变量的 += (HandlesAugAssign)参考,
# 避免用 RHS 字面量类型(i32)误建 i32 全局导致 i64/i32 类型不匹配。
if not hasattr(Gen, '_module_ann_types'):
Gen._module_ann_types = {}
Gen._module_ann_types[VarName] = VarType
if VarName in Gen.variables or VarName in Gen.module.globals:
# 时序修复:第一遍创建全局时类未处理(SymbolTable 无枚举成员),
# initializer 回退为 0。第二遍类已处理,尝试用解析出的枚举值更新 initializer。
+21 -2
View File
@@ -19,8 +19,27 @@ class AugAssignHandle(BaseHandle):
ast.Div: '__truediv__', ast.FloorDiv: '__floordiv__', ast.Mod: '__mod__', ast.Pow: '__pow__',
}
def _resolve_global_var_type(self, Gen: "Translator.LlvmGen", VarName: str, fallback: ir.Type) -> ir.Type:
"""解析 global 变量的 LLVM 类型:优先用模块级 AnnAssign 的注解类型。
问题场景:函数内 `_g_alloc_count += 1`(global 声明),模块级注解为
`_g_alloc_count: t.CSizeT`(i64)。若不查模块级注解类型,此处会用 RHS 字面量
类型(i32)自动建 i32 全局,与模块内其他读取/写入(i64)类型不匹配,
产生 "Operands must be the same type, got (i64, i32)" 类错误。
模块级 AnnAssign 已通过 _EmitGlobalAnnAssignLlvm 创建 LLVM 全局,
但注解无初始值(如 `_g_alloc_max: t.CSizeT = 0`)时 initializer 为空、
Gen.module.globals 中无该符号,故需在此兜底解析注解类型。
"""
module_ann: dict = getattr(Gen, '_module_ann_types', None)
if module_ann and VarName in module_ann:
ann_type: ir.Type = module_ann[VarName]
if ann_type is not None:
return ann_type
if isinstance(fallback, ir.IntType):
return fallback
return ir.IntType(64)
def _is_aug_unsigned(self, Node: ast.AugAssign, OldVal: ir.Value | None, Value: ir.Value) -> bool:
"""判断增量赋值操作是否应使用无符号指令"""
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
if isinstance(Node.target, ast.Name):
if Gen._check_node_unsigned(Node.target):
@@ -92,7 +111,7 @@ class AugAssignHandle(BaseHandle):
# (注解无初始值的全局变量),此处自动创建零初始化全局变量
GVar: ir.GlobalVariable
if VarName not in Gen.module.globals:
_gv_type: ir.Type = Value.type if isinstance(Value.type, ir.IntType) else ir.IntType(64)
_gv_type: ir.Type = self._resolve_global_var_type(Gen, VarName, Value.type)
GVar = ir.GlobalVariable(Gen.module, _gv_type, name=VarName)
GVar.initializer = ir.Constant(_gv_type, 0)
else:
+5 -1
View File
@@ -631,8 +631,12 @@ class ClassHandle(BaseHandle):
child_method: str = f"{ClassName}.{method_name}"
new_methods.append(child_method)
Gen.register_method(ClassName, child_method)
covered_names.add(method_name)
# 添加子类新增方法(不在父类中的)
for m in Gen.class_methods[ClassName]:
# 用快照遍历:register_method 会原地修改 class_methods,
# 若遍历活列表会把父类独有方法(已由 register_method 追加)再次追加,
# 导致 vtable 槽数与跨模块调用方推断不一致(如 MemBuddy 36 槽 vs 28 槽)。
for m in list(Gen.class_methods[ClassName]):
method_name: str = m.split('.')[-1] if '.' in m else m
if method_name not in covered_names:
new_methods.append(m)
-66
View File
@@ -7,16 +7,8 @@ from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta
import ast
import llvmlite.ir as ir
# [CDF-LOAD] 模块加载标记:用于确认修复后的代码被实际加载
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write('[CDF-LOAD] HandlesExprAttr.py loaded (with CDefine fix)\n')
except Exception:
pass
class ExprAttrHandle(BaseHandle):
# ========== 辅助方法 ==========
def _apply_bswap_on_Load(self, val: ir.Value, ClassName: str, AttrName: str) -> ir.Value:
@@ -205,20 +197,6 @@ class ExprAttrHandle(BaseHandle):
for key in (f"{VarName}.{AttrName}", AttrName):
if key in define_constants:
return self._make_define_constant(Gen, define_constants[key])
# [CDF-DBG] CDefine 查找失败时的诊断输出
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
_dbg_keys: list[str] = []
for _k in PossibleKeys:
_si: Any = self.Trans.SymbolTable.lookup(_k)
_dbg_keys.append(f"{_k}=>si={_si is not None},isdef={getattr(_si, 'IsDefine', None)},dv={getattr(_si, 'DefineValue', None)}")
_dc_keys: list[str] = [f"{k}=>{define_constants.get(k, '<miss>')}" for k in (f"{VarName}.{AttrName}", AttrName)]
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[CDF-DBG] miss VarName={VarName} AttrName={AttrName} imported_modules={imported_modules}\n")
_f.write(f"[CDF-DBG] sym_keys={_dbg_keys}\n")
_f.write(f"[CDF-DBG] dc_keys={_dc_keys}\n")
except Exception:
pass
return None
def _lookup_module_global(self, Gen: LlvmCodeGenerator, VarName: str, AttrName: str) -> ir.Value | None:
@@ -420,18 +398,6 @@ class ExprAttrHandle(BaseHandle):
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
AttrName: str = Node.attr
# [HAN-DBG] 入口诊断:标记 CONST_* 属性访问
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
_in_globals: bool = AttrName in Gen.module.globals
_gv_type: Any = None
if _in_globals:
_gv_type = str(Gen.module.globals[AttrName].type)
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[HAN-DBG] enter VarName={VarName} AttrName={AttrName} in_globals={_in_globals} gv_type={_gv_type}\n")
except Exception:
pass
# __doc__ 魔法字符串:函数/结构体的 docstring
if AttrName == '__doc__':
doc_ptr: ir.Value | None = Gen._get_doc_ptr(VarName)
@@ -462,12 +428,6 @@ class ExprAttrHandle(BaseHandle):
# 尝试 import 模块全局变量
result = self._lookup_module_global(Gen, VarName, AttrName)
if result is not None:
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[HAN-DBG] module_global HIT VarName={VarName} AttrName={AttrName} result_type={result.type}\n")
except Exception:
pass
return result
# FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储)
@@ -488,12 +448,6 @@ class ExprAttrHandle(BaseHandle):
# 尝试 attr 直接作为全局变量(仅当 VarName 不是结构体变量时)
if not ClassName and AttrName in Gen.module.globals:
gv: Any = Gen.module.globals[AttrName]
if AttrName in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[HAN-DBG] FALLBACK_TO_GLOBAL VarName={VarName} AttrName={AttrName} gv_type={gv.type}\n")
except Exception:
pass
if AttrName in Gen.variables and Gen.variables[AttrName] is None:
str_gv_name: str = AttrName + '_str'
if str_gv_name in Gen.module.globals:
@@ -899,20 +853,6 @@ class ExprAttrHandle(BaseHandle):
def _HandleAttributeLlvm(self, Node: ast.Attribute) -> ir.Value | None:
Gen: LlvmCodeGenerator = self.Trans.LlvmGen
# [ATTR-DBG] 入口诊断:标记 CONST_* 属性访问的派发路径
if Node.attr in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
_val_kind: str = type(Node.value).__name__
_val_id: str = ''
if isinstance(Node.value, ast.Name):
_val_id = Node.value.id
elif isinstance(Node.value, ast.Attribute):
_val_id = f"<Attribute attr={Node.value.attr}>"
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[ATTR-DBG] dispatch Node.attr={Node.attr} value_kind={_val_kind} value_id={_val_id}\n")
except Exception:
pass
if isinstance(Node.value, ast.Name):
VarName: str = Node.value.id
# 处理 t/c import 的别名重定向
@@ -921,12 +861,6 @@ class ExprAttrHandle(BaseHandle):
src_module: str
src_name: str
src_module, src_name = t_c_imported[VarName]
if Node.attr in ('CONST_INT', 'CONST_FLOAT', 'CONST_STR', 'CONST_BOOL', 'CONST_NONE'):
try:
with open('d:/Users/TermiNexus/Desktop/TransPyC/_attr_debug.log', 'a', encoding='utf-8') as _f:
_f.write(f"[ATTR-DBG] REDIRECT VarName={VarName} -> src_module={src_module} src_name={src_name}\n")
except Exception:
pass
virtual_attr: ast.Attribute = ast.Attribute(
value=ast.Name(id=src_module, ctx=ast.Load()),
attr=src_name, ctx=ast.Load()
+6 -4
View File
@@ -1726,14 +1726,16 @@ class FunctionHandle(BaseHandle):
triple = getattr(Gen, 'module_triple', '') or getattr(Gen.module, 'triple', '')
is_windows = 'windows' in triple if triple else False
ptr_size = getattr(Gen, 'ptr_size', 8)
# va_list 大小取决于 ABI:Windows x64 = 1个指针,Linux x64 = __va_list_tag[1](24字节)
# 32位平台:Windows = 4字节指针,Linux = 12字节
# va_list 大小取决于 ABI:Windows x64 = __va_list_tag(24字节),Linux x64 = __va_list_tag[1](24字节)
# 注意:x86_64-pc-windows-gnu 的 llvm.va_start 写的是 24 字节的 struct __va_list_tag
# ({i32 gp_offset, i32 fp_offset, i8* overflow_arg_area, i8* reg_save_area}),
# 若只分配 8 字节会向调用者栈帧越界写 16 字节,导致随机栈破坏(历史崩溃根因)。
if ptr_size == 4:
va_list_size = 4 if is_windows else 12
va_list_align = 4
else:
va_list_size = 8 if is_windows else 24
va_list_align = 8 if is_windows else 16
va_list_size = 24
va_list_align = 16
va_list_type = ir.ArrayType(ir.IntType(8), va_list_size)
va_list_alloc = Gen._allocaEntry(va_list_type, name=f"{vararg_name}_va_list", align=va_list_align)
va_list_ptr = Gen.builder.bitcast(va_list_alloc, ir.IntType(8).as_pointer(), name=f"{vararg_name}_va_list_i8ptr")
+18
View File
@@ -155,6 +155,24 @@ class ExprGenMixin:
'|': self.builder.or_,
'^': self.builder.xor,
}
# 整数操作数宽度对齐:两个操作数都是整数但位宽不同时,
# 统一扩展到较大位宽(低位宽操作数 zext/sext)。
# 触发场景:`_g_alloc_count: t.CSizeT = 0`(i64 全局)在函数内
# `_g_alloc_count += 1`,RHS 整数字面量是 i32,不扩展会报
# "Operands must be the same type, got (i64, i32)"。
if (op in ops or op in shift_ops or op in bit_ops or op in cmp_ops):
if (isinstance(left.type, ir.IntType) and isinstance(right.type, ir.IntType)
and left.type != right.type and left.type.width != 1 and right.type.width != 1):
if left.type.width > right.type.width:
if is_unsigned:
right = self.builder.zext(right, left.type, name="zext_rhs_op")
else:
right = self.builder.sext(right, left.type, name="sext_rhs_op")
elif right.type.width > left.type.width:
if is_unsigned:
left = self.builder.zext(left, right.type, name="zext_lhs_op")
else:
left = self.builder.sext(left, right.type, name="sext_lhs_op")
if op == '**' or op == 'Pow':
if isinstance(left, ir.Constant) and isinstance(right, ir.Constant):
try:
View File
Whitespace-only changes.
-478
View File
@@ -1,478 +0,0 @@
===== TransPyV Test Suite =====
asm: nop ok
asm: nop2 ok
asm: multi-clobber ok
asm: input ok val=42
asm: output result=123
asm: in+out result2=11 (expect 11)
=== attr_test: c.Attribute 装饰器测试 ===
--- Test 1: c.Attribute(always_inline) ---
AlwaysInlineFunc(21)=42 (expect 42)
AlwaysInlineFunc OK
--- Test 2: c.Attribute(noinline) ---
NoInlineFunc(5)=105 (expect 105)
NoInlineFunc OK
--- Test 3: c.Attribute(noreturn) ---
NoReturnFunc declared with noreturn attr
NoReturnFunc OK (not called to avoid UB)
--- Test 4: normal function (no attr) ---
NormalFunc(7)=21 (expect 21)
NormalFunc OK
--- Test 5: c.Attribute(always_inline, pure) ---
MultiAttrFunc(10)=11 (expect 11)
MultiAttrFunc OK
--- Test 6: c.Attribute(packed) ---
PackedAttrFunc(10)=9 (expect 9)
PackedAttrFunc OK
--- Test 7: c.Attribute(llvm.nounwind) ---
NoUnwindFunc(10)=11 (expect 11)
NoUnwindFunc OK
--- Test 8: c.Attribute(llvm.noredzone) ---
NoRedZoneFunc(10)=12 (expect 12)
NoRedZoneFunc OK
--- Test 9: c.Attribute(llvm.willreturn) ---
WillReturnFunc(10)=13 (expect 13)
WillReturnFunc OK
--- Test 10: c.Attribute(llvm.mustprogress) ---
MustProgressFunc(10)=14 (expect 14)
MustProgressFunc OK
--- Test 11: c.Attribute(const) ---
ConstFunc(99)=42 (expect 42)
ConstFunc OK
--- Test 12: c.Attribute(always_inline, nounwind, noredzone) ---
TripleAttrFunc(10)=15 (expect 15)
TripleAttrFunc OK
=== attr_test 完成 ===
local +=: 15
local -=: 12
local *=: 24
local /=: 6
local %=: 6
global +=: 1
global +=: 11
global -=: 8
bit &=: 15
bit |=: 63
bit ^=: 192
bit <<=: 16
bit >>=: 4
global: 9
global: 10
global: 11
closure: 1
closure: 1
closure: 1
=== deco_test: t/c 装饰器测试 ===
--- Test 1: t.CDefine ---
MAX_VALUE=256 (expect 256)
PI_APPROX=314 (expect 314)
MAX_VALUE OK
PI_APPROX OK
--- Test 2: t.CExport ---
ExportedAdd(3,4)=7 (expect 7)
ExportedAdd OK
--- Test 3: t.CInline ---
InlineSquare(5)=25 (expect 25)
InlineSquare OK
--- Test 4: normal function ---
NormalSub(10,3)=7 (expect 7)
NormalSub OK
--- Test 5: t.CExport | t.CInline ---
ExportedInlineCube(3)=27 (expect 27)
ExportedInlineCube OK
--- Test 6: t.CExport return ptr ---
ExportedFindChar found, char=108 (expect 108)
ExportedFindChar OK
--- Test 7: t.CExtern | t.CExport ---
ExternalDecl declared (not called)
ExternalDecl OK
--- Test 8: t.State ---
StateDecl declared (not called)
StateDecl OK
--- Test 9: t.State (void) ---
StateVoidDecl declared (not called)
StateVoidDecl OK
--- Test 10: t.CArray[elem, CDefine] ---
ARR_SIZE=8 (expect 8)
arr sum=280 (expect 280)
arr[0]=0 (expect 0)
arr[7]=70 (expect 70)
CArray CDefine count OK
=== deco_test 完成 ===
deref: 104
ptr: len(hello)=5
=== eq_test: ==、!=、is、None 比较测试 ===
--- Test 1: int == / != ---
int == int (same) OK
int != int (diff) OK
not (int == diff) OK
--- Test 2: int < > <= >= ---
int < OK
int > OK
int <= OK
int >= OK
--- Test 3: ptr is None / is not None ---
strchr found, is not None OK
strchr not found, is None OK
--- Test 4: assign None and compare ---
None assign, is None OK
None assign, is not None OK
--- Test 5: ptr == None / != None ---
strstr found, != None OK
strstr not found, == None OK
--- Test 6: bool and/or ---
1 and 0 = false OK
1 or 0 = true OK
not 0 = true OK
=== eq_test 完成 ===
float: f=3.140000
double: d=3.141593
float: f=2.500000
union: u.f=3.140000
union: u.i=42 (after f overwritten)
union: float overwrites int verified
arith: 1.50 + 2.50 = 4.00
arith: 1.50 - 2.50 = -1.00
arith: 1.50 * 2.50 = 3.75
arith: 1.50 / 2.50 = 0.60
arith: 10.0000 + 3.0000 = 13.0000
arith: 10.0000 - 3.0000 = 7.0000
arith: 10.0000 * 3.0000 = 30.0000
arith: 10.0000 / 3.0000 = 3.3333
arith: 10.0 % 3.0 = 1.0000
arith: 3 + 1.50 = 4.50
while: total=10 i=5
break: k=0
break: k=1
break: k=2
continue: m=0
continue: m=1
continue: m=3
continue: m=4
for: j=0
for: j=1
for: j=2
for: j=3
for: j=4
add(3,4)=7
mul(5,6)=30
square(7)=49
factorial(5)=120
add(b=4,a=3)=7
sub(b=3,a=10)=7
Hello, World!
Hello, World!
greet mixed: returned=2
Hi, TransPyC!
greet kwargs: returned=1
=== llvmir_test: c.LLVMIR 内联 LLVM IR 测试 ===
--- Test 1: LLVMIR add ---
add(10, 20)=30 (expect 30)
LLVMIR add OK
--- Test 2: LLVMIR sub ---
sub(50, 20)=30 (expect 30)
LLVMIR sub OK
--- Test 3: LLVMIR mul ---
mul(6, 7)=42 (expect 42)
LLVMIR mul OK
--- Test 4: LLVMIR sdiv ---
sdiv(100, 4)=25 (expect 25)
LLVMIR sdiv OK
--- Test 5: LLVMIR and ---
and(255, 15)=15 (expect 15)
LLVMIR and OK
--- Test 6: LLVMIR or ---
or(240, 15)=255 (expect 255)
LLVMIR or OK
--- Test 7: LLVMIR xor ---
xor(255, 15)=240 (expect 240)
LLVMIR xor OK
--- Test 8: LLVMIR shl ---
shl(1, 4)=16 (expect 16)
LLVMIR shl OK
--- Test 9: LLVMIR LOut ---
LOut add(10, 20)=30 (expect 30)
LLVMIR LOut OK
--- Test 10: LLVMIR icmp eq ---
icmp eq(5, 5)=-1 (expect nonzero)
LLVMIR icmp eq OK
--- Test 11: LLVMIR icmp ne ---
icmp ne(5, 3)=-1 (expect nonzero)
LLVMIR icmp ne OK
--- Test 12: LLVMIR icmp slt ---
icmp slt(3, 5)=-1 (expect nonzero)
LLVMIR icmp slt OK
--- Test 13: LLVMIR srem ---
srem(17, 5)=2 (expect 2)
LLVMIR srem OK
--- Test 14: LLVMIR lshr ---
lshr(256, 2)=64 (expect 64)
LLVMIR lshr OK
--- Test 15: LLVMIR nested in expression ---
(LLVMIR add(10,20)) + 10 = 40 (expect 40)
LLVMIR nested OK
=== llvmir_test 完成 ===
oop: === Test 1: Basic Methods ===
oop: p.x=10 p.y=20
oop: after move p.x=100 p.y=200
oop: === Test 2: Defaults + Methods ===
oop: initial count=0 step=1
oop: after 3 increments: 1 2 3
oop: after reset+increment: 1
oop: === Test 3: __init__ ===
oop: rect 3x4 area=12
oop: === All OOP Tests Passed ===
ptr: len(hello)=5
ptr: after DerefAs x=88
ptr: sum(A,B,C)=198
if: x is truthy
if: 1==1 is truthy
while: total=10 i=5
for: j=0
for: j=1
for: j=2
for: j=3
for: j=4
break: k=0
break: k=1
break: k=2
continue: m=0
continue: m=1
continue: m=3
continue: m=4
bool: x>5 and x<100 is true
bool: x>100 or x>5 is true
ptr: len(hello)=5
ptr: after DerefAs v=88
ptr: sum(A,B,C)=198
ptr: c.Load v2=42 (expected 42)
ptr: c.Load overwrite v3=200 (expected 200)
ptr: c.Load src unchanged v5=999 v6=999 (expected 999, 999)
hello
strlen(Hello)=5
=== string_test: string.py 库函数测试 ===
--- Test 1: strlen ---
strlen(Hello)=5 (expect 5)
strlen()=0 (expect 0)
strlen(Hello, World!)=13 (expect 13)
--- Test 2: strcmp ---
strcmp(abc,abc)=0 (expect 0)
strcmp(abc,abd)=-1 (expect <0)
strcmp(abd,abc)=1 (expect >0)
--- Test 3: strncmp ---
strncmp(abcdef,abcXYZ,3)=0 (expect 0)
strncmp(abcdef,abcXYZ,4)=12 (expect <0)
--- Test 4: atoi ---
atoi(123)=123 (expect 123)
atoi(-456)=-456 (expect -456)
atoi( 789)=789 (expect 789)
--- Test 5: strchr ---
strchr(Hello,'l') found, char=108 (expect 108)
strchr(Hello,'z') not found OK
--- Test 6: strstr ---
strstr(Hello,World) found OK
strstr(Hello,xyz) not found OK
=== string_test 完成 ===
struct: p.x=10 p.y=20
struct: modified p.x=100 p.y=200
struct: sum=300
struct: volume=60
array: total=1500
array: arr[2]=999
ptr: len(hello)=5
ptr: sum(A,B,C)=198
ctor: z.x=0 z.y=0
ctor: p3.x=7 p3.y=8
ctor: bx.w=10 bx.h=20 bx.d=30
kw: p4.x=10 p4.y=20
kw: p5.x=5 p5.y=15
kw: bx2.w=10 bx2.h=20 bx2.d=30
def: sz.w=100 sz.h=200
def: sz2.w=5 sz2.h=6
def: sz3.w=888 sz3.h=999
def: sz4.w=7 sz4.h=200
enum: Idle=0 Run=1 Stop=2
enum: Red=10 Green=11 Blue=20 Yellow=21
enum: Small=0 Big=1 Medium=2
enum: sum(Idle,Run,Stop)=3
enum: Idle==0 true
enum: Red==10 true
enum: Run!=Stop true
union: u.i=42
union: u.l=20015998343868
union: shared memory verified
type: CInt=100 CInt32T=200 CUInt32T=300
type: CLong=1000 CLongLong=2000 CInt64T=3000 CSizeT=4000
bit: 240&15=0
bit: 240|15=255
bit: 240^15=255
bit: 240<<2=960
bit: 240>>2=60
bit: 17%5=2
vtable: === Test Start ===
vtable: a.GetName()=42 (expected 42)
vtable: a.Speak()=0 (expected 0)
vtable: s.SetSides(4)=0 (expected 0)
vtable: s.GetSides()=4 (expected 4)
vtable: === All Tests Passed ===
inherit: === Test 1: Base Class ===
inherit: a.GetName()=42 (expected 42)
inherit: a.Speak()=0 (expected 0)
inherit: === Test 2: Dog (override Speak) ===
inherit: d.GetName()=100 (expected 100)
inherit: d.Speak()=1 (expected 1)
inherit: d.GetBreed()=7 (expected 7)
inherit: === Test 3: Cat (inherit Speak) ===
inherit: ct.GetName()=200 (expected 200)
inherit: ct.Speak()=0 (expected 0)
inherit: ct.GetColor()=3 (expected 3)
inherit: === All Tests Passed ===
funcvt: === Test Start ===
funcvt: A.VirtualMethod()=15 (expected 15)
funcvt: A.NormalMethod()=25 (expected 25)
funcvt: B.KeptMethod()=37 (expected 37)
funcvt: B.ExcludedMethod()=47 (expected 47)
funcvt: C.VirtualMethod()=59 (expected 59)
funcvt: C.NormalMethod()=69 (expected 69)
funcvt: === All Tests Passed ===
vdispatch: === Test Start ===
vdispatch: === Test 1: Direct Dispatch ===
vdispatch: a.Speak()=0 (expected 0)
vdispatch: d.Speak()=1 (expected 1)
vdispatch: === Test 2: Virtual Dispatch ===
vdispatch: a.Speak()=1 (expected 1 after vtable copy)
vdispatch: === Test 3: GetName After VTable Copy ===
vdispatch: a.GetName()=42 (expected 42)
vdispatch: === All Tests Passed ===
new: === Test Start ===
new: === Test 1: __new__ returns self ===
new: WithNew.__new__ called
new: WithNew.__init__ called
new: w.GetValue()=42 (expected 42)
new: === Test 2: __new__ no extra args ===
new: WithNewNoArgs.__new__ called
new: n.GetValue()=99 (expected 99)
new: === Test 3: __new__ + vtable ===
new: WithNewVTable.__new__ called
new: vt.GetValue()=10 (expected 10)
new: vt.Speak()=11 (expected 11)
new: === All Tests Passed ===
nsisol: === Test Start ===
nsisol: === Test 1: from-import bare constructor ===
nsisol: w.GetId()=42 (expected 42)
nsisol: w.Render()=100 (expected 100)
nsisol: g.Render()=200 (expected 200)
nsisol: g.GetExtra()=9 (expected 9)
nsisol: === Test 2: module-qualified constructor ===
nsisol: ps.Sum()=30 (expected 30)
nsisol: ps2.Sum()=11 (expected 11)
nsisol: === Test 3: type annotation with imported class ===
nsisol: annot_w.GetId()=99 (expected 99)
nsisol: === Test 4: cross-module inheritance vtable ===
nsisol: base.Render()=100 (expected 100)
nsisol: derived.Render()=200 (expected 200)
nsisol: derived.GetId()=2 (expected 2)
nsisol: === All Tests Passed ===
=== testcheck_test ===
--- Arithmetic ---
PASS: 3+4=7
PASS: 10-3=7
PASS: 6*7=42
--- String ---
PASS: strlen(hello)=5
PASS: strcmp(abc,abc)=0
--- Module Import ---
testcheck module imported and called successfully
PASS: import testcheck works
--- Summary ---
PASS: 6, FAIL: 0
=== Operator Overload Tests ===
--- Counter __add__ ---
PASS: cnt(10)+5=15
--- Counter __sub__/__mul__/__div__/__mod__ ---
PASS: cnt-3=7
PASS: cnt*3=30
PASS: cnt/3=3
PASS: cnt%3=1
--- Counter compare overloads ---
PASS: cnt==10:1
PASS: cnt!=10:0
PASS: cnt<20:1
PASS: cnt<=10:1
PASS: cnt>5:1
PASS: cnt>=10:1
--- BitBox bitwise overloads ---
PASS: bb&0x0F=15
PASS: bb|0x100=511
PASS: bb^0x55=170
PASS: bb<<4=4080
PASS: bb>>4=15
--- Native int binop ---
PASS: 7+8=15
PASS: 10-3=7
PASS: 4*5=20
--- Native int compare ---
PASS: 3<5
PASS: 10==10
--- Vec2 struct overloads ---
PASS: a+b x=4
PASS: a+b y=6
PASS: a-b x=2
PASS: a-b y=2
--- Vec2 compare overloads ---
PASS: (5,5)==(5,5):1
PASS: (5,5)!=(5,5):0
--- Summary ---
PASS: 27, FAIL: 0
circ: === Test Start ===
circ: === Test 1: A.MakeB() ===
circ: a.GetValue()=10 (expected 10)
circ: b.GetValue()=10 (expected 10)
circ: === Test 2: B.MakeA() ===
circ: a2.GetValue()=10 (expected 10)
circ: === Test 3: value chain A(20)->B->A ===
circ: final=20 (expected 20)
circ: === All Tests Passed ===
=== nested_match_test: 嵌套 match REnum 检测测试 ===
[DBG] _init_mbuddy: start
[DBG] _init_mbuddy: malloc arena=0
[DBG] _init_mbuddy: malloc mb=0
[DBG] _init_mbuddy: before_init
[DBG] _init_mbuddy: init
[DBG] _init_mbuddy: store
[DBG] _init_mbuddy: done
--- Test 1: 单层 match LLVMType ---
[DBG] Int32 done: 0
Int(-693633024) OK
bits==-693633024 FAIL
--- Test 2: 嵌套 match(case 块内 match 另一值)---
outer Int(-688782832), inner Int(0) OK
values FAIL
--- Test 3: 嵌套 match pointee ---
--- Test 4: 3 层嵌套 match ---
--- Test 5: if 块内嵌套 match ---
Float(-688782320) + Double(0) OK
float values FAIL
--- Test 6: 嵌套 match 不同变体(default 分支)---
outer Int(-688782192), inner Float(0) OK
mismatch values FAIL
=== nested_match_test: SOME FAIL ===
===== Test Suite Complete =====
-1
View File
@@ -1 +0,0 @@
===== Test Suite Complete =====