chore(test): 初始化回归测试仓(新增 .gitignore,TestsOverview.md 改为 README.md)

把 Test/ 纳入 https://git.gvsds.com/GVSDS/Viper_RegressionTesting 。

1) 新增 .gitignore —— 只保留测试源码,剔除全部构建产物:
   目录   **/output*/(output / output_opt / output_orig / output_verify / output_dbg)、
          **/temp*/(temp / temp_opt)、**/.tpv_build/
   二进制 *.exe *.obj *.o *.out *.a *.lib *.dll
   中间物 *.ll *.vpi *.pyi *.deps.txt *.deps.json *.doc.json *_sha1_map.txt
          _pyi_cache_v1.pkl _pyi_cache_v1.sig.json _shared_sym.json _phase1_manifest.json
   其它   build_all.txt(构建日志)、*.log、__pycache__/、*.bak、IDE 目录
   保留   App/*.vp、project.json / project_opt.json / project.vpj、README.md、两个 .py
   实测 `git add -A --dry-run`:196 个文件,无任何构建产物混入。

2) TestsOverview.md → README.md(作为仓库首页文档)。

3) SequentialRegressionTest.py:7 处 TestsOverview.md 引用同步改为 README.md
   (文档串、OVERVIEW 路径、read_test_order 文档与报错文案、argparse description、
   启动横幅);同时修正入口路径 PROJECTRANS —— 旧值 <root>/Projectrans.py 已不存在,
   改为 <root>/TransPyC/Projectrans.py(与 regression_test.py:45-48 记录一致),
   否则本脚本会以 "can't open file" 全量失败。
   regression_test.py 无需改动:它按目录扫描 project.json 找项目,不引用该文档。
This commit is contained in:
TermiNexus committed 2026-09-29 15:14:59 +08:00
commit 3c6fb1d246
196 files changed
+24775

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
# ============================================================
# Viper 回归测试仓(Test/)
# 仅提交测试源码:App/*.vp、project*.json、README.md、两个 .py 脚本
# ============================================================
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
# 构建产物目录
# output/ 及其变体(output_opt / output_orig / output_verify / output_dbg)、
# temp/ 与 temp_opt/、TransPyV 的 .tpv_build/
**/output*/
**/temp*/
**/.tpv_build/
# 可执行文件与目标文件
*.exe
*.obj
*.o
*.out
*.a
*.lib
*.dll
# 编译器中间产物(LLVM IR / 存根 / 依赖记录 / 符号表 / 缓存)
*.ll
*.vpi
*.pyi
*.deps.txt
*.deps.json
*.doc.json
*_sha1_map.txt
_pyi_cache_v1.pkl
_pyi_cache_v1.sig.json
_shared_sym.json
_phase1_manifest.json
# 构建日志
build_all.txt
*.log
# 备份
*.bak
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
.trae/
+204
View File
@@ -0,0 +1,204 @@
import t, c
from stdint import *
import stdio
import stdlib
import string
import memhub
import argparse
import testcheck
# 全局 MBuddy 指针
_mbuddy: memhub.MemBuddy | t.CPtr
@t.CExport
def main() -> int:
global _mbuddy
testcheck.begin("ArgparseTest: 命令行参数解析")
# 初始化内存管理器
arena: bytes = stdlib.malloc(16 * 1024 * 1024)
if arena is None:
testcheck.fail("malloc arena failed")
return 1
_mbuddy = memhub.MemBuddy(arena, 16 * 1024 * 1024)
argparse._mbuddy = _mbuddy
# 构造模拟 argv: myprog --input test.txt -c 42 --verbose output.dat
argv_buf: bytes = _mbuddy.alloc(8 * 7) # 7 个指针
argv: str | t.CPtr = (str | t.CPtr)(argv_buf)
# argv[0] = "myprog"
s0: bytes = _mbuddy.alloc(16)
string.strcpy(s0, "myprog")
argv0: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv))
argv0[0] = s0
# argv[1] = "--input"
s1: bytes = _mbuddy.alloc(16)
string.strcpy(s1, "--input")
argv1: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 8)
argv1[0] = s1
# argv[2] = "test.txt"
s2: bytes = _mbuddy.alloc(16)
string.strcpy(s2, "test.txt")
argv2: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 16)
argv2[0] = s2
# argv[3] = "-c"
s3: bytes = _mbuddy.alloc(8)
string.strcpy(s3, "-c")
argv3: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 24)
argv3[0] = s3
# argv[4] = "42"
s4: bytes = _mbuddy.alloc(8)
string.strcpy(s4, "42")
argv4: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 32)
argv4[0] = s4
# argv[5] = "--verbose"
s5: bytes = _mbuddy.alloc(16)
string.strcpy(s5, "--verbose")
argv5: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 40)
argv5[0] = s5
# argv[6] = "output.dat"
s6: bytes = _mbuddy.alloc(16)
string.strcpy(s6, "output.dat")
argv6: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv) + 48)
argv6[0] = s6
argc: INT = 7
# ============================================================
# Test 1: 基本解析 (--input, -c, --verbose, output)
# ============================================================
testcheck.section("Test 1: 基本解析")
parser = argparse.ArgumentParser("myprog", "A test program for argparse", pool=_mbuddy)
parser.add_argument("--input", "-i", argparse.STRING, 0, None, True, argparse.STORE, "input file path")
parser.add_argument("--count", "-c", argparse.INT, 1, None, False, argparse.STORE, "repeat count")
parser.add_argument("--verbose", "-v", argparse.BOOL, 0, None, False, argparse.STORE_TRUE, "enable verbose output")
parser.add_argument("output", None, argparse.STRING, 0, None, False, argparse.STORE, "output file path")
args = parser.parse_args(argc, argv)
if args is not None:
testcheck.ok("parse_args returned non-NULL")
inp: str = args.get_str("input")
cnt: INT = args.get_int("count")
verb: INT = args.get_bool("verbose")
out: str = args.get_str("output")
testcheck.check(string.strcmp(inp, "test.txt") == 0, "input = test.txt", "input mismatch")
testcheck.check(cnt == 42, "count = 42", "count mismatch")
testcheck.check(verb == True, "verbose = True", "verbose mismatch")
testcheck.check(string.strcmp(out, "output.dat") == 0, "output = output.dat", "output mismatch")
argparse.release(args)
else:
testcheck.fail("parse_args returned NULL")
# ============================================================
# Test 2: --name=value 语法
# ============================================================
testcheck.section("Test 2: --name=value 语法")
argv2_buf: bytes = _mbuddy.alloc(8 * 3)
argv2: str | t.CPtr = (str | t.CPtr)(argv2_buf)
a0: bytes = _mbuddy.alloc(16)
string.strcpy(a0, "myprog")
a0_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv2))
a0_ptr[0] = a0
a1: bytes = _mbuddy.alloc(32)
string.strcpy(a1, "--input=hello.txt")
a1_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv2) + 8)
a1_ptr[0] = a1
a2: bytes = _mbuddy.alloc(16)
string.strcpy(a2, "output2.dat")
a2_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv2) + 16)
a2_ptr[0] = a2
args2 = parser.parse_args(3, argv2)
if args2 is not None:
testcheck.ok("parse_args returned non-NULL")
inp2: str = args2.get_str("input")
cnt2: INT = args2.get_int("count")
out2: str = args2.get_str("output")
testcheck.check(string.strcmp(inp2, "hello.txt") == 0, "input = hello.txt", "input mismatch")
testcheck.check(cnt2 == 1, "count = 1 (default)", "count mismatch")
testcheck.check(string.strcmp(out2, "output2.dat") == 0, "output = output2.dat", "output mismatch")
argparse.release(args2)
else:
testcheck.fail("parse_args returned NULL")
# ============================================================
# Test 3: -v COUNT 计数动作
# ============================================================
testcheck.section("Test 3: COUNT 计数动作")
argv3_buf: bytes = _mbuddy.alloc(8 * 4)
argv3_arr: str | t.CPtr = (str | t.CPtr)(argv3_buf)
b0: bytes = _mbuddy.alloc(8)
string.strcpy(b0, "myprog")
b0_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv3_arr))
b0_ptr[0] = b0
b1: bytes = _mbuddy.alloc(8)
string.strcpy(b1, "-v")
b1_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv3_arr) + 8)
b1_ptr[0] = b1
b2: bytes = _mbuddy.alloc(8)
string.strcpy(b2, "-v")
b2_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv3_arr) + 16)
b2_ptr[0] = b2
b3: bytes = _mbuddy.alloc(16)
string.strcpy(b3, "output3.dat")
b3_ptr: str | t.CPtr = (str | t.CPtr)(t.CUInt64T(argv3_arr) + 24)
b3_ptr[0] = b3
parser2 = argparse.ArgumentParser("myprog", "Count test", pool=_mbuddy)
parser2.add_argument("--verbose", "-v", argparse.BOOL, 0, None, False, argparse.COUNT, "verbosity level")
parser2.add_argument("output", None, argparse.STRING, 0, None, False, argparse.STORE, "output file")
args3 = parser2.parse_args(4, argv3_arr)
if args3 is not None:
testcheck.ok("parse_args returned non-NULL")
verb3: INT = args3.get_int("verbose")
out3: str = args3.get_str("output")
testcheck.check(verb3 == 2, "verbose = 2 (counted)", "verbose count mismatch")
testcheck.check(string.strcmp(out3, "output3.dat") == 0, "output = output3.dat", "output mismatch")
argparse.release(args3)
else:
testcheck.fail("parse_args returned NULL")
# ============================================================
# Test 4: 关键字参数调用 add_argument
# ============================================================
testcheck.section("Test 4: 关键字参数")
parser3 = argparse.ArgumentParser("myprog", "Keyword arg test", pool=_mbuddy)
parser3.add_argument("--input", short="-i", arg_type=argparse.STRING, default=0, default_str=None, required=False, action=argparse.STORE, help="input file")
parser3.add_argument("--count", short="-c", arg_type=argparse.INT, default=1, required=False, action=argparse.STORE, help="count")
parser3.add_argument("--verbose", short="-v", arg_type=argparse.BOOL, default=0, required=False, action=argparse.STORE_TRUE, help="verbose")
parser3.add_argument("output", arg_type=argparse.STRING, default=0, required=False, action=argparse.STORE, help="output file")
args4 = parser3.parse_args(argc, argv)
if args4 is not None:
testcheck.ok("parse_args returned non-NULL")
inp4: str = args4.get_str("input")
cnt4: INT = args4.get_int("count")
out4: str = args4.get_str("output")
testcheck.check(string.strcmp(inp4, "test.txt") == 0, "input = test.txt", "input mismatch")
testcheck.check(cnt4 == 42, "count = 42", "count mismatch")
testcheck.check(string.strcmp(out4, "output.dat") == 0, "output = output.dat", "output mismatch")
argparse.release(args4)
else:
testcheck.fail("parse_args returned NULL")
return testcheck.end()
+30
View File
@@ -0,0 +1,30 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ArgparseTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"],
"output": "ArgparseTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true,
"startup": false
}
}
+256
View File
@@ -0,0 +1,256 @@
from stdint import *
import t, c
from t import CInt, CExport
from stdio import printf
import memhub
import stdlib
import sys
import string
import ast
import w32.win32console
# MBuddy arena 大小:1MB
ARENA_SIZE: t.CDefine = 1048576
# mpool 内存大小:512KB
POOL_SIZE: t.CDefine = 524288
# dump 缓冲区大小:256KB
DUMP_SIZE: t.CDefine = 262144
def classify_list(lst: list[ast.AST | t.CPtr] | t.CPtr, depth: t.CInt):
"""递归遍历 list[AST | t.CPtr] 容器,逐元素分类(orelse/args/comparators 等)"""
if lst is None:
return
n: t.CSizeT = lst.__len__()
i: t.CSizeT = 0
while i < n:
classify_print(lst.get(i), depth + 1)
i += 1
def classify_print(node: ast.AST | t.CPtr, depth: t.CInt):
"""递归遍历 parse 树,用 isinstance 运行时判定每个节点的类别并打印。
依赖 TPV isinstance 的 vtable 子类集合比较:
- isinstance(node, ast.Stmt) → 语句节点(Assign/If/For/While/...)
- isinstance(node, ast.ExprNode) → 表达式节点(Name/Constant/BinOp/...)
- 两者皆非 → 其他(Module/Expression/...)
验证运行时(非编译期静态)正确区分 Stmt 与 ExprNode。
"""
if node is None:
return
sp: t.CInt = 0
while sp < depth:
printf(" ")
sp += 1
if isinstance(node, ast.Stmt) != 0:
printf("STMT %s\n", node.type_name())
elif isinstance(node, ast.ExprNode) != 0:
printf("EXPR %s\n", node.type_name())
else:
printf("OTHER %s\n", node.type_name())
# 按 kind 遍历语句持有的表达式字段(语句 body 块均在 children)。
# 属性访问前先 cast 成具体节点类:node 静态类型是 ast.AST,
# 直接访问 node.value 会在 AST 基类字段表 fast-fail(按需过滤原则)。
k: t.CInt = node.kind()
if k == ast.ASTKind.Assign:
asg: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node)
classify_print(asg.value, depth + 1)
elif k == ast.ASTKind.If:
ifn: ast.If | t.CPtr = (ast.If | t.CPtr)(node)
classify_print(ifn.test, depth + 1)
classify_list(ifn.orelse, depth + 1)
elif k == ast.ASTKind.While:
whl: ast.While | t.CPtr = (ast.While | t.CPtr)(node)
classify_print(whl.test, depth + 1)
classify_list(whl.orelse, depth + 1)
elif k == ast.ASTKind.For:
for_nd: ast.For | t.CPtr = (ast.For | t.CPtr)(node)
classify_print(for_nd.iter, depth + 1)
classify_print(for_nd.target, depth + 1)
classify_list(for_nd.orelse, depth + 1)
elif k == ast.ASTKind.Return:
ret_nd: ast.Return | t.CPtr = (ast.Return | t.CPtr)(node)
classify_print(ret_nd.value, depth + 1)
elif k == ast.ASTKind.Expr:
expr_nd: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
classify_print(expr_nd.value, depth + 1)
elif k == ast.ASTKind.BinOp:
bin_nd: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node)
classify_print(bin_nd.left, depth + 1)
classify_print(bin_nd.right, depth + 1)
elif k == ast.ASTKind.UnaryOp:
una_nd: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node)
classify_print(una_nd.operand, depth + 1)
elif k == ast.ASTKind.Compare:
cmp_nd: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node)
classify_print(cmp_nd.left, depth + 1)
classify_list(cmp_nd.comparators, depth + 1)
elif k == ast.ASTKind.BoolOp:
bool_nd: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node)
classify_list(bool_nd.values, depth + 1)
elif k == ast.ASTKind.Call:
call_nd: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node)
classify_print(call_nd.func, depth + 1)
classify_list(call_nd.args, depth + 1)
else:
pass
# children(语句 body 块)
if node.children is not None:
n: t.CSizeT = node.children.__len__()
i: t.CSizeT = 0
while i < n:
classify_print(node.children.get(i), depth + 1)
i += 1
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
printf("AST Comprehensive Test Start\n")
# 初始化全局 MBuddy 内存分配器
arena: bytes = stdlib.malloc(ARENA_SIZE)
if arena == None:
printf("FAIL: arena alloc failed\n")
return 1
mbuddy_obj: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, ARENA_SIZE)
if mbuddy_obj == None:
printf("FAIL: mbuddy init failed\n")
return 1
sys._mbuddy = mbuddy_obj
ast._mbuddy = mbuddy_obj
# 为 ast 解析器创建 mpool
pool_mem: bytes = stdlib.malloc(POOL_SIZE)
if pool_mem == None:
printf("FAIL: malloc for pool failed\n")
return 1
pool: memhub.MemPool | t.CPtr = memhub.MemPool(pool_mem, POOL_SIZE)
if pool == None:
printf("FAIL: memhub.MemPool init failed\n")
return 1
# dump 缓冲区(独立分配)
dump_mem: bytes = stdlib.malloc(DUMP_SIZE)
if dump_mem == None:
printf("FAIL: malloc for dump failed\n")
return 1
dump_buf: t.CChar | t.CPtr = t.CChar(dump_mem, t.CPtr)
# 综合测试源码:覆盖 CPython 主要语法
src: str = """x = 1
y = 2
z = x + y
a = x - y
b = x * y
c = x / y
d = x == y
e = x < y
f = x > y
g = x and y
h = x or y
i = not x
def foo(a, b):
return a + b
result = foo(x, y)
if x > 0:
print(x)
else:
print(y)
for i in range(10):
print(i)
while x > 0:
x = x - 1
class Point:
pass
"""
printf("Parsing comprehensive source...\n")
# 解析
ast._init_tables(pool)
lx_dbg: t.CPtr = ast.new_lexer(pool)
if lx_dbg == None:
printf("FAIL: new_lexer returned None\n")
stdlib.free(pool_mem)
stdlib.free(dump_mem)
return 1
ast._lexer_init(lx_dbg, src, pool)
tokens_dbg: t.CPtr = ast.tokenize(lx_dbg)
if tokens_dbg == None:
printf("FAIL: tokenize returned None\n")
stdlib.free(pool_mem)
stdlib.free(dump_mem)
return 1
tree: ast.AST | t.CPtr = ast.parse_tokens(pool, tokens_dbg)
if tree == None:
printf("FAIL: parse returned None\n")
stdlib.free(pool_mem)
stdlib.free(dump_mem)
return 1
printf("PASS: parse succeeded\n")
# dump AST
printf("Calling ast.dump...\n")
ast.dump(tree, dump_buf, DUMP_SIZE)
printf("ast.dump returned, now printing buffer...\n")
printf("=== AST DUMP ===\n%s\n=== END ===\n", dump_buf)
# ============================================================
# Stmt/Expr 运行时区分测试(isinstance vtable 子类集合比较)
# ============================================================
printf("=== STMT/EXPR RUNTIME DISTINGUISH TEST ===\n")
classify_print(tree, 0)
# 断言 1: Module 既非 Stmt 亦非 ExprNode(顶层容器)
if isinstance(tree, ast.Stmt) != 0 or isinstance(tree, ast.ExprNode) != 0:
printf("FAIL: Module misclassified as Stmt/ExprNode\n")
else:
printf("PASS: Module is neither Stmt nor ExprNode\n")
# 断言 2: 顶层 body 每条语句均为 Stmt
top_ok: t.CInt = 1
top_n: t.CSizeT = tree.children.__len__()
i2: t.CSizeT = 0
while i2 < top_n:
top_node: ast.AST | t.CPtr = tree.children.get(i2)
if isinstance(top_node, ast.Stmt) == 0:
top_ok = 0
printf("FAIL: top-level node not Stmt: %s\n", top_node.type_name())
i2 += 1
if top_ok != 0:
printf("PASS: all %lld top-level nodes are Stmt\n", top_n)
# 断言 3: Assign 是 Stmt 且不是 ExprNode
first_assign: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(tree.children.get(0))
if isinstance(first_assign, ast.Stmt) != 0 and isinstance(first_assign, ast.ExprNode) == 0:
printf("PASS: Assign is Stmt, not ExprNode\n")
else:
printf("FAIL: Assign classification wrong\n")
# 断言 4: Assign.value(表达式)是 ExprNode 且不是 Stmt
if isinstance(first_assign.value, ast.ExprNode) != 0 \
and isinstance(first_assign.value, ast.Stmt) == 0:
printf("PASS: Assign.value is ExprNode (%s)\n", first_assign.value.type_name())
else:
printf("FAIL: Assign.value not ExprNode\n")
# 断言 5: 表达式语句 Expr(如 print(x))属于 Stmt(Statement 语义)
if top_n >= 15:
if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(tree.children.get(14))
if if_node.children is not None and if_node.children.__len__() > 0:
expr_stmt: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(if_node.children.get(0))
if isinstance(expr_stmt, ast.Stmt) != 0 and isinstance(expr_stmt, ast.ExprNode) == 0:
printf("PASS: Expr(stmt) is Stmt, not ExprNode (%s)\n", expr_stmt.type_name())
else:
printf("FAIL: Expr(stmt) classification wrong\n")
printf("=== END RUNTIME TEST ===\n")
stdlib.free(pool_mem)
stdlib.free(dump_mem)
return 0
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "AstTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "AstTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+18
View File
@@ -0,0 +1,18 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CExport
import memhub
import mbuddytest
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
# memhub 的 [MEMDBG] 悬空/重复 free 检测默认开启(_memdbg_enable=1)。
# BuddyTest 含"故意双重 free,期望静默拒绝且状态不损坏"的负向用例,
# 若保持开启会在第二次 free 处终止进程 → 在此关闭 debug 模式。
memhub._memdbg_enable = 0
return mbuddytest.mbuddy_main()
+545
View File
@@ -0,0 +1,545 @@
import t, c
from t import CInt, CPtr, CChar, CUInt8T, CUInt32T, CUInt64T, CSizeT
import viperlib
import viperio
import stdlib
import memhub
import string
import testcheck
import w32.win32process
import w32.win32sync
import w32.win32base
# 线程函数: 在共享 MBuddy 上执行 alloc/free (测试 spinlock 线程安全)
def _thread_alloc_free(param: t.CPtr) -> t.CUInt32T:
bd: memhub.MemBuddy | t.CPtr = (memhub.MemBuddy | t.CPtr)(param)
i: CInt
for i in range(100):
p: bytes = bd.alloc(32)
if p != None:
p_c: CUInt8T | CPtr = CPtr(p)
p_c[0] = CUInt8T(i & 0xFF)
bd.free(p)
return 0
def mbuddy_main() -> CInt:
buf: bytes = stdlib.malloc(256)
testcheck.begin("BuddyTest: 伙伴系统内存分配器测试")
# === 基础 alloc/free 测试 ===
testcheck.section("基础 alloc/free")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena, 65536)
viperlib.snprintf(buf, 256, "stats=%lu, free_count=%lu", bd.stats(), bd.free_count())
testcheck.info(buf)
p1: bytes = bd.alloc(16)
p2: bytes = bd.alloc(64)
p3: bytes = bd.alloc(256)
testcheck.check(p1 != None and p2 != None and p3 != None,
"3 allocs OK", "alloc FAILED")
# 写入数据验证指针可用
p_c: CUInt8T | CPtr = CPtr(p1)
p_c[0] = CUInt8T(0xAB)
p_c[1] = CUInt8T(0xCD)
viperlib.snprintf(buf, 256, "p1[0]=0x%x p1[1]=0x%x", p_c[0], p_c[1])
testcheck.info(buf)
testcheck.check(p_c[0] == CUInt8T(0xAB) and p_c[1] == CUInt8T(0xCD),
"write/read OK", "write/read FAILED")
bd.free(p1)
bd.free(p2)
bd.free(p3)
testcheck.ok("3 frees OK")
# 释放后验证合并: free_count 应回到初始分解块数 (10)
# 4096-264 内非 2 的幂: 65536-264=65272 二进制分解为 10 个 2 的幂块
testcheck.check(bd.free_count() == 10,
"coalesce: free_count=10 OK", "coalesce: free_count != 10")
# 合并后应能分配大块
big: bytes = bd.alloc(16000)
testcheck.check(big != None, "big alloc OK", "big alloc FAILED")
bd.free(big)
stdlib.free(arena)
# === calloc 测试 (验证清零) ===
testcheck.section("calloc 清零")
arena2: bytes = stdlib.malloc(4096)
viperlib.snprintf(buf, 256, "arena2 = %p", arena2)
testcheck.info(buf)
bd2: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena2, 4096)
dirty: bytes = bd2.alloc(64)
viperlib.snprintf(buf, 256, "dirty = %p", dirty)
testcheck.info(buf)
d_c: CUInt8T | CPtr = CPtr(dirty)
i: CInt
for i in range(64):
d_c[i] = CUInt8T(0xFF)
bd2.free(dirty)
cl: bytes = bd2.calloc(8, 8)
viperlib.snprintf(buf, 256, "cl = %p (arena2=%p, dirty was=%p)", cl, arena2, dirty)
testcheck.info(buf)
if cl != None:
cl_c: CUInt8T | CPtr = CPtr(cl)
all_zero: CInt = 1
j: CInt
for j in range(64):
if cl_c[j] != 0:
all_zero = 0
break
testcheck.check(all_zero == 1, "calloc zeroed OK", "calloc NOT zeroed")
bd2.free(cl)
else:
testcheck.fail("calloc FAILED")
stdlib.free(arena2)
# === realloc 扩展测试 ===
testcheck.section("realloc 扩展")
arena3: bytes = stdlib.malloc(4096)
bd3: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena3, 4096)
rp: bytes = bd3.alloc(32)
rp_c: CUInt8T | CPtr = CPtr(rp)
k: CInt
for k in range(32):
rp_c[k] = CUInt8T(k + 1)
rp2: bytes = bd3.realloc(rp, 128)
if rp2 != None:
rp2_c: CUInt8T | CPtr = CPtr(rp2)
ok: CInt = 1
m: CInt
for m in range(32):
if rp2_c[m] != CUInt8T(m + 1):
ok = 0
break
testcheck.check(ok == 1, "realloc grow data preserved OK", "realloc grow data LOST")
bd3.free(rp2)
else:
testcheck.fail("realloc grow FAILED")
stdlib.free(arena3)
# === 原地收缩测试 (验证无泄漏) ===
testcheck.section("原地收缩 (realloc shrink)")
arena_shrink: bytes = stdlib.malloc(4096)
bds: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_shrink, 4096)
sp: bytes = bds.alloc(256)
testcheck.check(sp != None, "alloc 256 OK", "alloc 256 FAILED")
fc_before: CSizeT = bds.free_count()
# realloc 到更小尺寸: 256+8=264 -> order 4 (512); 32+8=40 -> order 1 (64)
# new_order(1) <= old_order(4), 应原地返回同一指针
sp2: bytes = bds.realloc(sp, 32)
fc_after: CSizeT = bds.free_count()
testcheck.check(sp2 == sp, "shrink same ptr OK", "shrink ptr changed")
testcheck.check(fc_after == fc_before, "shrink no leak OK", "shrink LEAKED blocks")
# 验证数据仍可读写
sp_c: CUInt8T | CPtr = CPtr(sp2)
sp_c[0] = CUInt8T(0x42)
testcheck.check(sp_c[0] == CUInt8T(0x42), "shrink data OK", "shrink data FAILED")
bds.free(sp2)
testcheck.check(bds.free_count() == 6, "shrink+free coalesce OK", "shrink+free coalesce FAILED")
stdlib.free(arena_shrink)
# === 边界情况测试 ===
testcheck.section("边界情况")
arena4: bytes = stdlib.malloc(4096)
bd4: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena4, 4096)
# alloc(0) 应返回 None
z: bytes = bd4.alloc(0)
testcheck.check(z == None, "alloc(0)=None OK", "alloc(0) should be None")
# free(None) 应安全
bd4.free(None)
testcheck.ok("free(None) safe")
# realloc(None, size) 等价于 alloc
rn: bytes = bd4.realloc(None, 32)
testcheck.check(rn != None, "realloc(None)=alloc OK", "realloc(None) FAILED")
bd4.free(rn)
# realloc(ptr, 0) 等价于 free
rz: bytes = bd4.alloc(32)
rz2: bytes = bd4.realloc(rz, 0)
testcheck.check(rz2 == None, "realloc(ptr,0)=free OK", "realloc(ptr,0) should be None")
stdlib.free(arena4)
# === 非法指针防护测试 ===
testcheck.section("非法指针防护")
arena5: bytes = stdlib.malloc(4096)
bd5: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena5, 4096)
valid: bytes = bd5.alloc(32)
testcheck.check(valid != None, "alloc for illegal test OK", "alloc FAILED")
# 1. free 随机地址 (地址 1)
bd5.free(t.CPtr(t.CUInt64T(1)))
testcheck.ok("free(addr=1) ignored")
# 2. free NULL
bd5.free(None)
testcheck.ok("free(NULL) ignored")
# 3. free 越界指针 (arena 之前)
bd5.free(t.CPtr(t.CUInt64T(arena5)))
testcheck.ok("free(before arena) ignored")
# 4. free 越界指针 (arena 之后)
bd5.free(t.CPtr(t.CUInt64T(arena5) + 99999))
testcheck.ok("free(after arena) ignored")
# 5. free 未对齐指针 (arena + 1, 在 mem 区域内但不对齐)
bd5.free(t.CPtr(t.CUInt64T(bd5.base) + 1))
testcheck.ok("free(misaligned) ignored")
# 6. 验证合法 free 仍正常工作 (释放后应能再次分配)
bd5.free(valid)
retry5: bytes = bd5.alloc(32)
testcheck.check(retry5 != None, "valid free still works OK", "valid free BROKEN")
if retry5 != None:
bd5.free(retry5)
# 7. realloc 非法指针应返回 None
r_illegal: bytes = bd5.realloc(t.CPtr(1), 64)
testcheck.check(r_illegal == None, "realloc(illegal)=None OK", "realloc(illegal) should be None")
stdlib.free(arena5)
# === OOM 内存耗尽测试 ===
testcheck.section("OOM 内存耗尽")
arena6: bytes = stdlib.malloc(4096)
bd6: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena6, 4096)
# 持续分配直到失败
alloc_count: CInt = 0
ptrs_arr: bytes = stdlib.malloc(8 * 256) # 存储指针的数组
ptrs: CUInt64T | CPtr = CPtr(ptrs_arr)
while alloc_count < 256:
p: bytes = bd6.alloc(32)
if p == None:
break
ptrs[alloc_count] = t.CUInt64T(p)
alloc_count += 1
viperlib.snprintf(buf, 256, "allocated %d blocks before OOM", alloc_count)
testcheck.info(buf)
testcheck.check(alloc_count > 0, "OOM: got some allocs OK", "OOM: no allocs at all")
# 尝试再分配应失败
oom_p: bytes = bd6.alloc(32)
testcheck.check(oom_p == None, "OOM: alloc fails OK", "OOM: alloc should fail")
# 释放一个块后应能再次分配
if alloc_count > 0:
first_ptr: bytes = t.CPtr(ptrs[0])
bd6.free(first_ptr)
retry: bytes = bd6.alloc(32)
testcheck.check(retry != None, "OOM: free+alloc OK", "OOM: free+alloc FAILED")
if retry != None:
bd6.free(retry)
# 释放所有块
idx: CInt = 1
while idx < alloc_count:
cur_p: bytes = t.CPtr(ptrs[idx])
bd6.free(cur_p)
idx += 1
# 全部释放后应能合并回初始分解块数 (6)
testcheck.check(bd6.free_count() == 6,
"OOM: full coalesce OK", "OOM: free_count != 6 after full free")
stdlib.free(ptrs_arr)
stdlib.free(arena6)
# === 空闲链表状态测试 ===
testcheck.section("空闲链表状态")
arena7: bytes = stdlib.malloc(4096)
bd7: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena7, 4096)
# 初始: 非 2 的幂 arena (4096-264=3832) 二进制分解为 6 个块
testcheck.check(bd7.free_count() == 6, "init: 6 free blocks OK", "init: free_count != 6")
# 分配后: 空闲块数应增加 (分裂产生多个小块)
a1: bytes = bd7.alloc(32)
fc1: CSizeT = bd7.free_count()
viperlib.snprintf(buf, 256, "after alloc(32): free_count=%lu", fc1)
testcheck.info(buf)
testcheck.check(fc1 > 1, "after alloc: split OK", "after alloc: no split")
# 再分配
a2: bytes = bd7.alloc(32)
fc2: CSizeT = bd7.free_count()
testcheck.check(fc2 >= 1, "after 2nd alloc: free >= 1 OK", "after 2nd alloc: free < 1")
# 释放 a1: 空闲块数应增加
bd7.free(a1)
fc3: CSizeT = bd7.free_count()
testcheck.check(fc3 > fc2, "after free a1: free increased OK", "after free a1: free not increased")
# 释放 a2: 应合并, 空闲块数回到初始 6 块
bd7.free(a2)
testcheck.check(bd7.free_count() == 6,
"after free all: coalesced to 6 OK", "after free all: free_count != 6")
stdlib.free(arena7)
# === with 上下文管理器测试 ===
testcheck.section("with 上下文管理器")
arena8: bytes = stdlib.malloc(4096)
with memhub.MemBuddy(arena8, 4096) as wbd:
wp1: bytes = wbd.alloc(32)
wp2: bytes = wbd.alloc(64)
testcheck.check(wp1 != None and wp2 != None,
"with: allocs OK", "with: allocs FAILED")
# 退出 with 块时 __exit__ 自动 reset
# 退出后重新进入,验证 reset 生效
with memhub.MemBuddy(arena8, 4096) as wbd2:
wp3: bytes = wbd2.alloc(1024)
testcheck.check(wp3 != None, "with: reset+realloc OK", "with: reset+realloc FAILED")
stdlib.free(arena8)
# === 双重 free 检测测试 ===
testcheck.section("双重 free 检测")
arena_df: bytes = stdlib.malloc(4096)
bd_df: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_df, 4096)
df: bytes = bd_df.alloc(64)
testcheck.check(df != None, "df: alloc OK", "df: alloc FAILED")
# 第一次 free
bd_df.free(df)
fc_df1: CSizeT = bd_df.free_count()
testcheck.ok("first free OK")
# 第二次 free (双重 free) — 应被静默拒绝
bd_df.free(df)
fc_df2: CSizeT = bd_df.free_count()
testcheck.check(fc_df2 == fc_df1, "double free rejected OK", "double free CORRUPTED state")
# 验证分配器仍正常工作
df2: bytes = bd_df.alloc(64)
testcheck.check(df2 != None, "df: alloc after double-free OK", "df: alloc after double-free FAILED")
if df2 != None:
bd_df.free(df2)
stdlib.free(arena_df)
# === 自检功能测试 ===
testcheck.section("自检功能")
arena_sc: bytes = stdlib.malloc(4096)
bd_sc: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_sc, 4096)
# 初始状态自检
testcheck.check(bd_sc.self_check() == 0, "self_check init OK", "self_check init FAILED")
# 分配后自检
sc_p1: bytes = bd_sc.alloc(32)
sc_p2: bytes = bd_sc.alloc(128)
testcheck.check(bd_sc.self_check() == 0, "self_check after alloc OK", "self_check after alloc FAILED")
# 部分释放后自检
bd_sc.free(sc_p1)
testcheck.check(bd_sc.self_check() == 0, "self_check after partial free OK", "self_check after partial free FAILED")
# 全部释放后自检 (应合并回单个大块)
bd_sc.free(sc_p2)
testcheck.check(bd_sc.self_check() == 0, "self_check after full free OK", "self_check after full free FAILED")
# 双重 free 后自检 (验证状态未损坏)
sc_p3: bytes = bd_sc.alloc(64)
bd_sc.free(sc_p3)
bd_sc.free(sc_p3) # 双重 free,应被拒绝
testcheck.check(bd_sc.self_check() == 0, "self_check after double-free OK", "self_check after double-free CORRUPTED")
stdlib.free(arena_sc)
# === 并发多线程测试 (spinlock) ===
testcheck.section("并发多线程 (spinlock)")
arena_mt: bytes = stdlib.malloc(65536)
bd_mt: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_mt, 65536)
NUM_THREADS: CInt = 4
handles_arr: bytes = stdlib.malloc(8 * 4)
handles: CUInt64T | CPtr = CPtr(handles_arr)
tid: CUInt32T = 0
# 创建 4 个线程并发 alloc/free
t_idx: CInt
for t_idx in range(NUM_THREADS):
h: bytes = w32.win32process.CreateThread(None, 0, _thread_alloc_free, t.CPtr(bd_mt), 0, c.Addr(tid))
handles[t_idx] = CUInt64T(h)
# 等待所有线程完成
for t_idx in range(NUM_THREADS):
h: bytes = t.CPtr(handles[t_idx])
w32.win32sync.WaitForSingleObject(h, w32.win32base.INFINITE)
w32.win32base.CloseHandle(h)
# 验证分配器状态: 自检通过,所有块已合并
testcheck.check(bd_mt.self_check() == 0, "mt: self_check OK", "mt: self_check FAILED")
testcheck.check(bd_mt.free_count() == 10, "mt: free_count=10 OK", "mt: free_count != 10 (leaked)")
viperlib.snprintf(buf, 256, "mt: free_count=%lu", bd_mt.free_count())
testcheck.info(buf)
stdlib.free(handles_arr)
stdlib.free(arena_mt)
# === 极端边界测试 ===
testcheck.section("极端边界")
# 1. 分配尺寸恰巧是块边界
arena_ex: bytes = stdlib.malloc(4096)
bd_ex: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_ex, 4096)
# 24 + 16 = 40 > 32(8 头 + 8 哨兵),需要 order 1 (64 字节)
exact_fit: bytes = bd_ex.alloc(24)
testcheck.check(exact_fit != None, "exact fit order 0 OK", "exact fit order 0 FAILED")
# 25 + 16 = 41 > 32, 需要 order 1 (64 字节)
over_fit: bytes = bd_ex.alloc(25)
testcheck.check(over_fit != None, "over by 1 byte OK", "over by 1 byte FAILED")
bd_ex.free(exact_fit)
bd_ex.free(over_fit)
testcheck.check(bd_ex.free_count() == 6, "boundary: coalesce OK", "boundary: coalesce FAILED")
# 2. 单次分配接近最大块上限(order6=2048,非 2 的幂 arena 的最大分解块)
# 可用数据区 = 2048 - 8(头) - 8(哨兵),alloc(max_usable) 的 needed 恰好
# = 2048,正好填满 order6 最大块
max_usable: CSizeT = 2048 - 16
viperlib.snprintf(buf, 256, "mem_size=%lu, max_block=2048, max_usable=%lu", bd_ex.mem_size, max_usable)
testcheck.info(buf)
# 恰好用完 order6 块(其余 5 个分解块空闲)
exact_max: bytes = bd_ex.alloc(max_usable)
testcheck.check(exact_max != None, "exact max alloc OK", "exact max alloc FAILED")
testcheck.check(bd_ex.free_count() == 5, "max alloc: 5 free blocks left OK", "max alloc: free_count != 5")
bd_ex.free(exact_max)
testcheck.check(bd_ex.free_count() == 6, "max free: coalesce OK", "max free: coalesce FAILED")
# 再次分配同样大小 — 验证合并后可再次使用
exact_max2: bytes = bd_ex.alloc(max_usable)
testcheck.check(exact_max2 != None, "exact max re-alloc OK", "exact max re-alloc FAILED")
bd_ex.free(exact_max2)
# 3. 分配超过 arena 上限 — 应失败
over_max: bytes = bd_ex.alloc(bd_ex.mem_size)
testcheck.check(over_max == None, "over max: fails OK", "over max: should fail")
over_max2: bytes = bd_ex.alloc(max_usable + 1)
testcheck.check(over_max2 == None, "max+1: fails OK", "max+1: should fail")
stdlib.free(arena_ex)
# 4. Arena 太小 (仅够 free_lists 开销, 264 字节)
arena_tiny: bytes = stdlib.malloc(264)
bd_tiny: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_tiny, 264)
testcheck.check(bd_tiny.stats() == 0, "tiny arena: stats=0 OK", "tiny arena: stats != 0")
tiny_p: bytes = bd_tiny.alloc(32)
testcheck.check(tiny_p == None, "tiny arena: alloc fails OK", "tiny arena: should fail")
stdlib.free(arena_tiny)
# 5. Arena 刚好够一个最小块 (264 + 32 = 296)
arena_one: bytes = stdlib.malloc(296)
bd_one: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_one, 296)
testcheck.check(bd_one.stats() == 32, "one block: stats=32 OK", "one block: stats != 32")
# 最小块 32 字节 = 数据 16 + 头 8 + 哨兵 8,alloc(16) 恰好填满
one_p: bytes = bd_one.alloc(16)
testcheck.check(one_p != None, "one block: alloc OK", "one block: alloc FAILED")
one_p2: bytes = bd_one.alloc(16)
testcheck.check(one_p2 == None, "one block: OOM OK", "one block: should be OOM")
bd_one.free(one_p)
testcheck.check(bd_one.free_count() == 1, "one block: free OK", "one block: free FAILED")
stdlib.free(arena_one)
# 6. 2 的幂 arena vs 非 2 的幂 arena
arena_pow2: bytes = stdlib.malloc(512)
bd_pow2: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_pow2, 512)
# 512 - 264 = 248, 二进制分解 = 128+64+32 = 224 (尾 24 字节碎片不入池)
testcheck.check(bd_pow2.stats() == 224, "pow2 arena: stats=224 OK", "pow2 arena: stats != 224")
stdlib.free(arena_pow2)
arena_non2: bytes = stdlib.malloc(500)
bd_non2: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_non2, 500)
# 500 - 264 = 236, 二进制分解 = 128+64+32 = 224 (尾 12 字节碎片不入池)
testcheck.check(bd_non2.stats() == 224, "non-pow2 arena: stats=224 OK", "non-pow2 arena: stats != 224")
stdlib.free(arena_non2)
# 7. 压力测试: 反复 alloc/free 同一尺寸 1000 次
arena_stress: bytes = stdlib.malloc(4096)
bd_stress: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_stress, 4096)
s: CInt
for s in range(1000):
sp: bytes = bd_stress.alloc(64)
if sp != None:
sp_c: CUInt8T | CPtr = CPtr(sp)
sp_c[0] = CUInt8T(s & 0xFF)
bd_stress.free(sp)
testcheck.check(bd_stress.self_check() == 0, "stress: self_check OK", "stress: self_check FAILED")
testcheck.check(bd_stress.free_count() == 6, "stress: free_count=6 OK", "stress: leaked")
stdlib.free(arena_stress)
# 8. 分配全部最小块然后全部释放
arena_fill: bytes = stdlib.malloc(4096)
bd_fill: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_fill, 4096)
fill_count: CInt = 0
fill_ptrs_arr: bytes = stdlib.malloc(8 * 256)
fill_ptrs: CUInt64T | CPtr = CPtr(fill_ptrs_arr)
fc: CInt
for fc in range(256):
fp: bytes = bd_fill.alloc(24)
if fp == None:
break
fill_ptrs[fill_count] = t.CUInt64T(fp)
fill_count += 1
viperlib.snprintf(buf, 256, "fill: %d min blocks allocated", fill_count)
testcheck.info(buf)
testcheck.check(fill_count > 0, "fill: got blocks OK", "fill: no blocks")
testcheck.check(bd_fill.self_check() == 0, "fill: self_check OK", "fill: self_check FAILED")
# 全部释放
fi: CInt
for fi in range(fill_count):
fp2: bytes = t.CPtr(fill_ptrs[fi])
bd_fill.free(fp2)
testcheck.check(bd_fill.free_count() == 6, "fill: all freed OK", "fill: leaked after free all")
testcheck.check(bd_fill.self_check() == 0, "fill: self_check after free OK", "fill: self_check FAILED")
stdlib.free(fill_ptrs_arr)
stdlib.free(arena_fill)
stdlib.free(buf)
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "BuddyTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "BuddyTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+268
View File
@@ -0,0 +1,268 @@
import t
from stdint import *
from stdio import printf
from stdlib import malloc
import testcheck
# ============================================================
# 测试 1:@property getter
# ============================================================
class Rect:
width: t.CInt
height: t.CInt
def __new__(self, w: t.CInt, h: t.CInt) -> 'Rect' | t.CPtr:
return t.CPtr(malloc(Rect.__sizeof__()))
def __init__(self, w: t.CInt, h: t.CInt):
self.width = w
self.height = h
@property
def area(self) -> t.CInt:
return self.width * self.height
@property
def is_square(self) -> bool:
return self.width == self.height
def test_property_getter():
testcheck.section("@property getter")
r1: Rect = Rect(3, 4)
testcheck.check(r1.area == 12, "area == 12", "area expect 12")
testcheck.check(not r1.is_square, "not square", "should not be square")
r2: Rect = Rect(5, 5)
testcheck.check(r2.area == 25, "square area == 25", "square area expect 25")
testcheck.check(r2.is_square, "is_square", "should be square")
# ============================================================
# 测试 2:@property.setter
# ============================================================
class Temperature:
_celsius: t.CDouble
def __new__(self, celsius_val: t.CDouble) -> 'Temperature' | t.CPtr:
return t.CPtr(malloc(Temperature.__sizeof__()))
def __init__(self, celsius_val: t.CDouble):
self._celsius = celsius_val
@property
def celsius(self) -> t.CDouble:
return self._celsius
@celsius.setter
def celsius(self, val: t.CDouble):
self._celsius = val
@property
def fahrenheit(self) -> t.CDouble:
return self._celsius * 1.8 + 32.0
def test_property_setter():
testcheck.section("@property.setter")
tmp1: Temperature = Temperature(0.0)
testcheck.check(tmp1.fahrenheit > 31.9 and tmp1.fahrenheit < 32.1, "0C == 32F", "0C expect 32F")
tmp1.celsius = 100.0
testcheck.check(tmp1.fahrenheit > 211.9 and tmp1.fahrenheit < 212.1, "100C == 212F", "100C expect 212F")
testcheck.check(tmp1.celsius > 99.9 and tmp1.celsius < 100.1, "celsius == 100", "celsius expect 100")
# ============================================================
# 测试 3:@property.getter(重新定义 getter)
# ============================================================
class Counter:
_count: t.CInt
def __new__(self) -> 'Counter' | t.CPtr:
return t.CPtr(malloc(Counter.__sizeof__()))
def __init__(self):
self._count = 0
@property
def value(self) -> t.CInt:
return self._count
@value.setter
def value(self, v: t.CInt):
self._count = v
def test_property_getter_redef():
testcheck.section("@property.getter redef")
cnt: Counter = Counter()
testcheck.check(cnt.value == 0, "init == 0", "init expect 0")
cnt.value = 42
testcheck.check(cnt.value == 42, "set == 42", "set expect 42")
# ============================================================
# 测试 4:@property.deleter
# ============================================================
class Config:
_value: t.CInt
_deleted: t.CInt
def __new__(self, v: t.CInt) -> 'Config' | t.CPtr:
return t.CPtr(malloc(Config.__sizeof__()))
def __init__(self, v: t.CInt):
self._value = v
self._deleted = 0
@property
def value(self) -> t.CInt:
return self._value
@value.setter
def value(self, v: t.CInt):
self._value = v
@value.deleter
def value(self):
self._value = 0
self._deleted = 1
def is_deleted(self) -> bool:
return self._deleted != 0
def test_property_deleter():
testcheck.section("@property.deleter")
cfg: Config = Config(99)
testcheck.check(cfg.value == 99, "init == 99", "init expect 99")
testcheck.check(not cfg.is_deleted(), "not deleted", "should not be deleted")
del cfg.value
testcheck.check(cfg.value == 0, "after del == 0", "after del expect 0")
testcheck.check(cfg.is_deleted(), "is_deleted", "should be deleted")
# ============================================================
# 测试 5:@staticmethod
# ============================================================
class MathUtils:
@staticmethod
def add(a: t.CInt, b: t.CInt) -> t.CInt:
return a + b
@staticmethod
def max_val(a: t.CInt, b: t.CInt) -> t.CInt:
return a if a > b else b
def test_staticmethod():
testcheck.section("@staticmethod")
# 通过类名调用
testcheck.check(MathUtils.add(3, 4) == 7, "MathUtils.add(3,4)==7", "MathUtils.add(3,4) expect 7")
testcheck.check(MathUtils.max_val(5, 10) == 10, "MathUtils.max(5,10)==10", "MathUtils.max(5,10) expect 10")
# ============================================================
# 测试 6:@classmethod
# ============================================================
class Point:
x: t.CDouble
y: t.CDouble
def __new__(self, x: t.CDouble, y: t.CDouble) -> 'Point' | t.CPtr:
return t.CPtr(malloc(Point.__sizeof__()))
def __init__(self, x: t.CDouble, y: t.CDouble):
self.x = x
self.y = y
@classmethod
def origin(cls: Point) -> Point:
return Point(0.0, 0.0)
@classmethod
def from_int(cls: Point, x: t.CInt, y: t.CInt) -> Point:
return Point(x * 1.0, y * 1.0)
def dist_sq(self) -> t.CDouble:
return self.x * self.x + self.y * self.y
def test_classmethod():
testcheck.section("@classmethod")
# 通过类名调用
p1: Point = Point.origin()
testcheck.check(p1.x > -0.01 and p1.x < 0.01, "origin.x ~= 0", "origin.x expect ~0")
testcheck.check(p1.y > -0.01 and p1.y < 0.01, "origin.y ~= 0", "origin.y expect ~0")
testcheck.check(p1.dist_sq() < 0.01, "origin.dist ~= 0", "origin.dist expect ~0")
p2: Point = Point.from_int(3, 4)
testcheck.check(p2.x > 2.99 and p2.x < 3.01, "from_int(3,4).x ~= 3", "from_int(3,4).x expect ~3")
testcheck.check(p2.y > 3.99 and p2.y < 4.01, "from_int(3,4).y ~= 4", "from_int(3,4).y expect ~4")
testcheck.check(p2.dist_sq() > 24.99 and p2.dist_sq() < 25.01, "dist_sq ~= 25", "dist_sq expect ~25")
# ============================================================
# 测试 7:综合测试 — @property + @staticmethod + @classmethod
# ============================================================
class Circle:
_radius: t.CDouble
def __new__(self, r: t.CDouble) -> 'Circle' | t.CPtr:
return t.CPtr(malloc(Circle.__sizeof__()))
def __init__(self, r: t.CDouble):
self._radius = r
@property
def radius(self) -> t.CDouble:
return self._radius
@radius.setter
def radius(self, val: t.CDouble):
self._radius = val
@property
def area(self) -> t.CDouble:
return 3.14159265 * self._radius * self._radius
@staticmethod
def is_unit(r: t.CDouble) -> bool:
return r > 0.99 and r < 1.01
@classmethod
def unit(cls: Circle) -> Circle:
return Circle(1.0)
def test_combined():
testcheck.section("Combined @property + @staticmethod + @classmethod")
# 先测试直接构造
cr0: Circle = Circle(1.0)
testcheck.check(cr0.radius > 0.99 and cr0.radius < 1.01, "direct radius ~= 1", "direct radius expect ~1")
testcheck.check(cr0.area > 3.14 and cr0.area < 3.15, "direct area ~= pi", "direct area expect ~pi")
cr0.radius = 2.0
testcheck.check(cr0.radius > 1.99 and cr0.radius < 2.01, "direct radius 2.0", "direct radius expect 2.0")
testcheck.check(cr0.area > 12.56 and cr0.area < 12.58, "direct area ~= 4pi", "direct area expect ~4pi")
# 测试 classmethod
cr1: Circle = Circle.unit()
testcheck.check(cr1.radius > 0.99 and cr1.radius < 1.01, "unit radius ~= 1", "unit radius expect ~1")
testcheck.check(Circle.is_unit(1.0), "is_unit(1.0)", "is_unit(1.0) should be true")
testcheck.check(not Circle.is_unit(2.0), "not is_unit(2.0)", "is_unit(2.0) should be false")
# ============================================================
# 主函数
# ============================================================
def main() -> t.CInt | t.CExport:
testcheck.begin("Builtin Decorator Test")
test_property_getter()
test_property_setter()
test_property_getter_redef()
test_property_deleter()
test_staticmethod()
test_classmethod()
test_combined()
return testcheck.end()
+39
View File
@@ -0,0 +1,39 @@
{
"name": "BuiltinDecoratorTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "BuiltinDecoratorTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+777
View File
@@ -0,0 +1,777 @@
import t, c
# ============================================================
# PyObject — 所有 Python 对象的基类
# ============================================================
class PyObject:
ob_refcnt: t.CLong
ob_type: t.CPtr
# ============================================================
# 引用计数
# ============================================================
extern def Py_INCREF(op: PyObject | t.CPtr)
extern def Py_DECREF(op: PyObject | t.CPtr)
extern def Py_XINCREF(op: PyObject | t.CPtr)
extern def Py_XDECREF(op: PyObject | t.CPtr)
extern def Py_DecRef(op: PyObject | t.CPtr)
# ============================================================
# 解释器初始化/终止
# ============================================================
extern def Py_Initialize()
extern def Py_Finalize()
extern def Py_InitializeEx(initsigs: t.CInt)
extern def Py_FinalizeEx() -> t.CInt
extern def Py_IsInitialized() -> t.CInt
# ============================================================
# PyConfig
# ============================================================
class PySTATUS:
func: t.CConst | str
err_msg: t.CConst | str
exitcode: t.CInt
class PyPreConfig:
_config_version: t.CInt
_config_init: t.CInt
parse_argv: t.CInt
isolated: t.CInt
use_environment: t.CInt
utf8_mode: t.CInt
coerce_c_locale: t.CInt
C_locale_warnings: t.CInt
allocator: t.CInt
dev_mode: t.CInt
class PyWideStringList:
length: t.CSizeT
items: t.CPtr
class PyConfig:
_config_version: t.CInt
_config_init: t.CInt
isolated: t.CInt
use_environment: t.CInt
dev_mode: t.CInt
install_signal_handlers: t.CInt
use_hash_seed: t.CInt
hash_seed: t.CUnsignedLong
faulthandler: t.CInt
tracemalloc: t.CInt
import_time: t.CInt
show_ref_count: t.CInt
dump_refs: t.CInt
dump_refs_file: t.CConst | str
malloc_stats: t.CInt
filesystem_errors: t.CInt
pycache_prefix: t.CConst | str
parse_argv: t.CInt
argv: PyWideStringList
program_name: t.CConst | str
xoptions: PyWideStringList
warnoptions: PyWideStringList
site_import: t.CInt
bytes_warning: t.CInt
warn_default_encoding: t.CInt
inspect: t.CInt
interactive: t.CInt
optimization_level: t.CInt
parser_debug: t.CInt
verbose: t.CInt
quiet: t.CInt
home: t.CConst | str
pythonpath_env: t.CConst | str
module_search_paths: PyWideStringList
module_search_paths_set: t.CInt
executable: t.CConst | str
base_executable: t.CConst | str
prefix: t.CConst | str
base_prefix: t.CConst | str
exec_prefix: t.CConst | str
base_exec_prefix: t.CConst | str
platlibdir: t.CConst | str
stdio_filename: t.CConst | str
extern def PyConfig_InitPythonConfig(config: PyConfig | t.CPtr)
extern def PyConfig_InitIsolatedConfig(config: PyConfig | t.CPtr)
extern def PyConfig_Clear(config: PyConfig | t.CPtr)
extern def PyConfig_Read(config: PyConfig | t.CPtr) -> PySTATUS
extern def Py_InitializeFromConfig(config: PyConfig | t.CPtr) -> PySTATUS
extern def Py_DecodeLocale(s: t.CConst | str) -> str
extern def PyStatus_Exception(status: PySTATUS) -> t.CInt
# ============================================================
# 整数操作 (PyLong)
# ============================================================
extern def PyLong_FromLong(v: t.CInt) -> PyObject | t.CPtr
extern def PyLong_FromUnsignedLong(v: t.CUnsignedLong) -> PyObject | t.CPtr
extern def PyLong_FromLongLong(v: t.CLong) -> PyObject | t.CPtr
extern def PyLong_FromUnsignedLongLong(v: t.CUnsignedLong) -> PyObject | t.CPtr
extern def PyLong_FromSsize_t(v: t.CPtrDiffT) -> PyObject | t.CPtr
extern def PyLong_FromSize_t(v: t.CSizeT) -> PyObject | t.CPtr
extern def PyLong_FromDouble(v: t.CDouble) -> PyObject | t.CPtr
extern def PyLong_AsLong(obj: PyObject | t.CPtr) -> t.CInt
extern def PyLong_AsUnsignedLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong
extern def PyLong_AsLongLong(obj: PyObject | t.CPtr) -> t.CLong
extern def PyLong_AsUnsignedLongLong(obj: PyObject | t.CPtr) -> t.CUnsignedLong
extern def PyLong_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble
extern def PyLong_AsSsize_t(obj: PyObject | t.CPtr) -> t.CPtrDiffT
extern def PyLong_AsSize_t(obj: PyObject | t.CPtr) -> t.CSizeT
# ============================================================
# 浮点数操作 (PyFloat)
# ============================================================
extern def PyFloat_FromDouble(v: t.CDouble) -> PyObject | t.CPtr
extern def PyFloat_AsDouble(obj: PyObject | t.CPtr) -> t.CDouble
extern def PyFloat_FromString(s: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 字符串操作 (PyUnicode / PyBytes)
# ============================================================
extern def PyUnicode_FromString(u: t.CConst | str) -> PyObject | t.CPtr
extern def PyUnicode_FromStringAndSize(u: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr
extern def PyUnicode_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr
extern def PyUnicode_AsUTF8(obj: PyObject | t.CPtr) -> str
extern def PyUnicode_AsUTF8AndSize(obj: PyObject | t.CPtr, size: t.CPtrDiffT | t.CPtr) -> str
extern def PyUnicode_AsWideChar(obj: PyObject | t.CPtr, wbuf: t.CPtr, bufsize: t.CSizeT) -> t.CSizeT
extern def PyUnicode_GetLength(obj: PyObject | t.CPtr) -> t.CPtrDiffT
extern def PyUnicode_ReadChar(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CUInt32T
extern def PyUnicode_WriteChar(obj: PyObject | t.CPtr, idx: t.CSizeT, ch: t.CUInt32T) -> t.CInt
extern def PyUnicode_Compare(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> t.CInt
extern def PyUnicode_Concat(l: PyObject | t.CPtr, r: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyUnicode_Contains(container: PyObject | t.CPtr, element: PyObject | t.CPtr) -> t.CInt
extern def PyUnicode_Format(fmt: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyUnicode_InternInPlace(s: PyObject | t.CPtr | t.CPtr): pass
extern def PyUnicode_InternFromString(u: t.CConst | str) -> PyObject | t.CPtr
extern def PyBytes_FromString(v: t.CConst | str) -> PyObject | t.CPtr
extern def PyBytes_FromStringAndSize(v: t.CConst | str, size: t.CSizeT) -> PyObject | t.CPtr
extern def PyBytes_AsString(obj: PyObject | t.CPtr) -> str
extern def PyBytes_Size(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PyBytes_FromObject(o: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyBytes_FromFormat(fmt: t.CConst | str) -> PyObject | t.CPtr
# ============================================================
# 布尔 / None
# ============================================================
extern def PyBool_FromLong(v: t.CLong) -> PyObject | t.CPtr
Py_True: PyObject | t.CPtr | t.State
Py_False: PyObject | t.CPtr | t.State
Py_None: PyObject | t.CPtr | t.State
# ============================================================
# 列表操作 (PyList)
# ============================================================
extern def PyList_New(len: t.CSizeT) -> PyObject | t.CPtr
extern def PyList_Size(lst: PyObject | t.CPtr) -> t.CSizeT
extern def PyList_GetItem(lst: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr
extern def PyList_SetItem(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt
extern def PyList_Insert(lst: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt
extern def PyList_Append(lst: PyObject | t.CPtr, item: PyObject | t.CPtr) -> t.CInt
extern def PyList_GetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr
extern def PyList_SetSlice(lst: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT, items: PyObject | t.CPtr) -> t.CInt
extern def PyList_Sort(lst: PyObject | t.CPtr) -> t.CInt
extern def PyList_Reverse(lst: PyObject | t.CPtr) -> t.CInt
extern def PyList_AsTuple(lst: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 元组操作 (PyTuple)
# ============================================================
extern def PyTuple_New(len: t.CSizeT) -> PyObject | t.CPtr
extern def PyTuple_Size(tup: PyObject | t.CPtr) -> t.CSizeT
extern def PyTuple_GetItem(tup: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr
extern def PyTuple_SetItem(tup: PyObject | t.CPtr, idx: t.CSizeT, item: PyObject | t.CPtr) -> t.CInt
extern def PyTuple_GetSlice(tup: PyObject | t.CPtr, lo: t.CSizeT, hi: t.CSizeT) -> PyObject | t.CPtr
extern def PyTuple_Pack(n: t.CSizeT) -> PyObject | t.CPtr
# ============================================================
# 字典操作 (PyDict)
# ============================================================
extern def PyDict_New() -> PyObject | t.CPtr
extern def PyDict_GetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyDict_GetItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr
extern def PyDict_SetItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt
extern def PyDict_SetItemString(d: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PyDict_DelItem(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PyDict_DelItemString(d: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt
extern def PyDict_Size(d: PyObject | t.CPtr) -> t.CSizeT
extern def PyDict_Keys(d: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyDict_Values(d: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyDict_Items(d: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyDict_Copy(d: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyDict_Clear(d: PyObject | t.CPtr): pass
extern def PyDict_Contains(d: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PyDict_Next(d: PyObject | t.CPtr, pos: t.CPtrDiffT | t.CPtr, key: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr) -> t.CInt
extern def PyDict_Merge(d: PyObject | t.CPtr, other: PyObject | t.CPtr, override: t.CInt) -> t.CInt
extern def PyDict_Update(d: PyObject | t.CPtr, other: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 对象通用操作
# ============================================================
extern def PyObject_Str(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_Repr(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_Type(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_IsInstance(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt
extern def PyObject_IsSubclass(obj: PyObject | t.CPtr, cls: PyObject | t.CPtr) -> t.CInt
extern def PyObject_HasAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt
extern def PyObject_HasAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt
extern def PyObject_GetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_GetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> PyObject | t.CPtr
extern def PyObject_SetAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt
extern def PyObject_SetAttrString(obj: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PyObject_DelAttr(obj: PyObject | t.CPtr, name: PyObject | t.CPtr) -> t.CInt
extern def PyObject_DelAttrString(obj: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt
extern def PyObject_Call(callable: PyObject | t.CPtr, args: PyObject | t.CPtr, kwargs: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_CallNoArgs(callable: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_CallOneArg(callable: PyObject | t.CPtr, arg: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_IsTrue(obj: PyObject | t.CPtr) -> t.CInt
extern def PyObject_Not(obj: PyObject | t.CPtr) -> t.CInt
extern def PyObject_RichCompare(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> PyObject | t.CPtr
extern def PyObject_RichCompareBool(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, opid: t.CInt) -> t.CInt
extern def PyObject_Hash(obj: PyObject | t.CPtr) -> t.CLong
extern def PyObject_Length(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PyObject_GetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_SetItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt
extern def PyObject_DelItem(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PyObject_Dir(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyObject_GetIter(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyIter_Next(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 比较常量
# ============================================================
Py_LT: t.CInt | t.State
Py_LE: t.CInt | t.State
Py_EQ: t.CInt | t.State
Py_NE: t.CInt | t.State
Py_GT: t.CInt | t.State
Py_GE: t.CInt | t.State
# ============================================================
# 模块操作
# ============================================================
extern def PyImport_ImportModule(name: t.CConst | str) -> PyObject | t.CPtr
extern def PyImport_Import(name: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyImport_ImportModuleLevelObject(name: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr, level: t.CInt) -> PyObject | t.CPtr
extern def PyImport_ReloadModule(mod: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyImport_AddModule(name: t.CConst | str) -> PyObject | t.CPtr
extern def PyImport_GetModuleDict() -> PyObject | t.CPtr
extern def PyImport_ImportModuleEx(name: t.CConst | str, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, fromlist: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 模块创建
# ============================================================
class PyMethodDef:
ml_name: t.CConst | str
ml_meth: t.CPtr
ml_flags: t.CInt
ml_doc: t.CConst | str
class PyModuleDef_Base:
ob_base: PyObject
m_init: t.CPtr
m_index: t.CSizeT
m_copy: PyObject | t.CPtr
class PyModuleDef:
m_base: PyModuleDef_Base
m_name: t.CConst | str
m_doc: t.CConst | str
m_size: t.CPtrDiffT
m_methods: PyMethodDef | t.CPtr
m_slots: t.CPtr
m_traverse: t.CPtr
m_clear: t.CPtr
m_free: t.CPtr
extern def PyModule_Create(mod: PyModuleDef | t.CPtr) -> PyObject | t.CPtr
extern def PyModule_Create2(mod: PyModuleDef | t.CPtr, ver: t.CInt) -> PyObject | t.CPtr
extern def PyModule_GetName(mod: PyObject | t.CPtr) -> str
extern def PyModule_GetDict(mod: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyModule_GetFilenameObject(mod: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyModule_AddObject(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PyModule_AddObjectRef(mod: PyObject | t.CPtr, name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PyModule_AddIntConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CLong) -> t.CInt
extern def PyModule_AddStringConstant(mod: PyObject | t.CPtr, name: t.CConst | str, val: t.CConst | str) -> t.CInt
# ============================================================
# GIL 管理
# ============================================================
extern def PyGILState_Ensure() -> t.CInt
extern def PyGILState_Release(state: t.CInt): pass
extern def PyEval_SaveThread() -> t.CPtr
extern def PyEval_RestoreThread(tstate: t.CPtr): pass
extern def PyEval_AcquireThread(tstate: t.CPtr): pass
extern def PyEval_ReleaseThread(tstate: t.CPtr): pass
extern def PyEval_AcquireLock(): pass
extern def PyEval_ReleaseLock(): pass
extern def PyEval_ThreadsInitialized() -> t.CInt
extern def PyEval_InitThreads(): pass
# ============================================================
# 错误处理
# ============================================================
extern def PyErr_Occurred() -> PyObject | t.CPtr
extern def PyErr_Clear(): pass
extern def PyErr_Fetch(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr): pass
extern def PyErr_Restore(tp: PyObject | t.CPtr, val: PyObject | t.CPtr, tb: PyObject | t.CPtr): pass
extern def PyErr_NormalizeException(tp: PyObject | t.CPtr | t.CPtr, val: PyObject | t.CPtr | t.CPtr, tb: PyObject | t.CPtr | t.CPtr): pass
extern def PyErr_SetString(tp: PyObject | t.CPtr, msg: t.CConst | str): pass
extern def PyErr_SetObject(tp: PyObject | t.CPtr, val: PyObject | t.CPtr): pass
extern def PyErr_BadArgument() -> t.CPtr | t.State: pass
extern def PyErr_NoMemory() -> t.CPtr | t.State: pass
extern def PyErr_Print(): pass
extern def PyErr_ExceptionMatches(exc: PyObject | t.CPtr) -> t.CInt | t.State: pass
extern def PyErr_GivenExceptionMatches(given: PyObject | t.CPtr, exc: PyObject | t.CPtr) -> t.CInt | t.State: pass
# ============================================================
# 内置异常类型
# ============================================================
PyExc_BaseException: PyObject | t.CPtr | t.State
PyExc_Exception: PyObject | t.CPtr | t.State
PyExc_TypeError: PyObject | t.CPtr | t.State
PyExc_ValueError: PyObject | t.CPtr | t.State
PyExc_RuntimeError: PyObject | t.CPtr | t.State
PyExc_KeyError: PyObject | t.CPtr | t.State
PyExc_IndexError: PyObject | t.CPtr | t.State
PyExc_AttributeError: PyObject | t.CPtr | t.State
PyExc_ImportError: PyObject | t.CPtr | t.State
PyExc_OSError: PyObject | t.CPtr | t.State
PyExc_IOError: PyObject | t.CPtr | t.State
PyExc_ZeroDivisionError: PyObject | t.CPtr | t.State
PyExc_OverflowError: PyObject | t.CPtr | t.State
PyExc_MemoryError: PyObject | t.CPtr | t.State
PyExc_NameError: PyObject | t.CPtr | t.State
PyExc_StopIteration: PyObject | t.CPtr | t.State
PyExc_NotImplementedError: PyObject | t.CPtr | t.State
PyExc_SyntaxError: PyObject | t.CPtr | t.State
PyExc_FileNotFoundError: PyObject | t.CPtr | t.State
PyExc_PermissionError: PyObject | t.CPtr | t.State
PyExc_IsADirectoryError: PyObject | t.CPtr | t.State
PyExc_NotADirectoryError: PyObject | t.CPtr | t.State
# ============================================================
# 内置函数
# ============================================================
extern def Py_BuildValue(fmt: t.CConst | str) -> PyObject | t.CPtr
extern def Py_VaBuildValue(fmt: t.CConst | str, va: t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 类型检查
# ============================================================
extern def PyLong_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyFloat_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyUnicode_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyBytes_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyList_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyTuple_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyDict_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyBool_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyNone_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 内存管理
# ============================================================
extern def PyMem_Malloc(size: t.CSizeT) -> t.CPtr
extern def PyMem_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr
extern def PyMem_Free(ptr: t.CPtr)
extern def PyMem_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr
extern def PyObject_Malloc(size: t.CSizeT) -> t.CPtr
extern def PyObject_Realloc(ptr: t.CPtr, size: t.CSizeT) -> t.CPtr
extern def PyObject_Free(ptr: t.CPtr)
extern def PyObject_Calloc(nelem: t.CSizeT, elsize: t.CSizeT) -> t.CPtr
extern def PyObject_Init(obj: PyObject | t.CPtr, tp: t.CPtr) -> PyObject | t.CPtr
extern def PyObject_InitVar(obj: PyObject | t.CPtr, tp: t.CPtr, size: t.CSizeT) -> PyObject | t.CPtr
# ============================================================
# 文件操作
# ============================================================
extern def PyFile_FromString(filename: t.CConst | str, mode: t.CConst | str) -> PyObject | t.CPtr
extern def PyFile_AsFile(file: PyObject | t.CPtr) -> t.CPtr
extern def PyFile_WriteObject(obj: PyObject | t.CPtr, file: PyObject | t.CPtr, flags: t.CInt) -> t.CInt
extern def PyFile_WriteString(s: t.CConst | str, file: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 编译/执行
# ============================================================
extern def Py_CompileString(s: t.CConst | str, filename: t.CConst | str, start: t.CInt) -> PyObject | t.CPtr
extern def PyEval_EvalCode(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyEval_EvalCodeEx(code: PyObject | t.CPtr, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr, args: PyObject | t.CPtr | t.CPtr, argc: t.CInt, kws: PyObject | t.CPtr | t.CPtr, kwc: t.CInt, defs: PyObject | t.CPtr | t.CPtr, defc: t.CInt, kwdefs: PyObject | t.CPtr, closure: PyObject | t.CPtr) -> PyObject | t.CPtr: pass
extern def PyEval_EvalFrame(frame: t.CPtr) -> PyObject | t.CPtr: pass
extern def PyEval_CallObject(callable: PyObject | t.CPtr, args: PyObject | t.CPtr) -> PyObject | t.CPtr: pass
extern def PyEval_CallFunction(callable: PyObject | t.CPtr, fmt: t.CConst | str) -> PyObject | t.CPtr: pass
extern def PyEval_CallMethod(obj: PyObject | t.CPtr, method: t.CConst | str, fmt: t.CConst | str) -> PyObject | t.CPtr: pass
# ============================================================
# PyRun
# ============================================================
extern def PyRun_SimpleString(cmd: t.CConst | str) -> t.CInt
extern def PyRun_SimpleFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt
extern def PyRun_AnyFile(fp: t.CPtr, filename: t.CConst | str) -> t.CInt
extern def PyRun_String(s: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyRun_File(fp: t.CPtr, filename: t.CConst | str, start: t.CInt, globs: PyObject | t.CPtr, locs: PyObject | t.CPtr) -> PyObject | t.CPtr
Py_single_input: t.CInt | t.State
Py_file_input: t.CInt | t.State
Py_eval_input: t.CInt | t.State
# ============================================================
# Capsule
# ============================================================
extern def PyCapsule_New(ptr: t.CPtr, name: t.CConst | str, dtor: t.CPtr) -> PyObject | t.CPtr
extern def PyCapsule_GetPointer(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CPtr
extern def PyCapsule_GetName(cap: PyObject | t.CPtr) -> str
extern def PyCapsule_IsValid(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt
extern def PyCapsule_SetPointer(cap: PyObject | t.CPtr, ptr: t.CPtr) -> t.CInt
extern def PyCapsule_SetName(cap: PyObject | t.CPtr, name: t.CConst | str) -> t.CInt
extern def PyCapsule_SetDestructor(cap: PyObject | t.CPtr, dtor: t.CPtr) -> t.CInt
# ============================================================
# 序列操作
# ============================================================
extern def PySequence_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PySequence_Size(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PySequence_Length(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PySequence_Concat(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PySequence_Repeat(obj: PyObject | t.CPtr, count: t.CSizeT) -> PyObject | t.CPtr
extern def PySequence_GetItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> PyObject | t.CPtr
extern def PySequence_SetItem(obj: PyObject | t.CPtr, idx: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt
extern def PySequence_DelItem(obj: PyObject | t.CPtr, idx: t.CSizeT) -> t.CInt
extern def PySequence_GetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> PyObject | t.CPtr
extern def PySequence_SetSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT, val: PyObject | t.CPtr) -> t.CInt
extern def PySequence_DelSlice(obj: PyObject | t.CPtr, start: t.CSizeT, end: t.CSizeT) -> t.CInt
extern def PySequence_Contains(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CInt
extern def PySequence_Index(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT
extern def PySequence_Count(obj: PyObject | t.CPtr, val: PyObject | t.CPtr) -> t.CSizeT
extern def PySequence_List(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PySequence_Tuple(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 映射操作
# ============================================================
extern def PyMapping_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyMapping_Size(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PyMapping_Length(obj: PyObject | t.CPtr) -> t.CSizeT
extern def PyMapping_HasKey(obj: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PyMapping_HasKeyString(obj: PyObject | t.CPtr, key: t.CConst | str) -> t.CInt
extern def PyMapping_GetItemString(obj: PyObject | t.CPtr, key: t.CConst | str) -> PyObject | t.CPtr
extern def PyMapping_SetItemString(obj: PyObject | t.CPtr, key: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PyMapping_Keys(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyMapping_Values(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyMapping_Items(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
# ============================================================
# 数字操作
# ============================================================
extern def PyNumber_Add(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Subtract(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Multiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_MatrixMultiply(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_FloorDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_TrueDivide(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Modulo(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Power(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr, o3: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Negative(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Positive(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Absolute(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Invert(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Lshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Rshift(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_And(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Xor(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Or(o1: PyObject | t.CPtr, o2: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Index(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Long(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Float(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyNumber_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 弱引用
# ============================================================
extern def PyWeakref_NewRef(obj: PyObject | t.CPtr, cb: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyWeakref_GetObject(ref: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyWeakref_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 属性描述符
# ============================================================
class PyGetSetDef:
name: t.CConst | str
get: t.CPtr
set: t.CPtr
doc: t.CConst | str
closure: t.CPtr
class PyMemberDef:
name: t.CConst | str
type: t.CInt
offset: t.CPtrDiffT
flags: t.CInt
doc: t.CConst | str
# ============================================================
# sys 模块
# ============================================================
extern def PySys_GetObject(name: t.CConst | str) -> PyObject | t.CPtr
extern def PySys_SetObject(name: t.CConst | str, val: PyObject | t.CPtr) -> t.CInt
extern def PySys_ResetWarnOptions(): pass
extern def PySys_AddWarnOption(s: PyObject | t.CPtr): pass
extern def PySYS_AddXOption(s: PyObject | t.CPtr): pass
extern def PySys_WriteStdout(fmt: t.CConst | str): pass
extern def PySys_WriteStderr(fmt: t.CConst | str): pass
extern def PySys_FormatStdout(fmt: t.CConst | str): pass
extern def PySys_FormatStderr(fmt: t.CConst | str): pass
# ============================================================
# 内存视图
# ============================================================
extern def PyMemoryView_FromObject(obj: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyMemoryView_GetContiguous(obj: PyObject | t.CPtr, btype: t.CInt, order: t.CChar) -> PyObject | t.CPtr
extern def PyMemoryView_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# set / frozenset
# ============================================================
extern def PySet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PySet_Add(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PySet_Discard(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PySet_Contains(s: PyObject | t.CPtr, key: PyObject | t.CPtr) -> t.CInt
extern def PySet_Size(s: PyObject | t.CPtr) -> t.CSizeT
extern def PySet_Clear(s: PyObject | t.CPtr): pass
extern def PySet_Check(obj: PyObject | t.CPtr) -> t.CInt
extern def PyFrozenSet_New(iterable: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PyFrozenSet_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# slice
# ============================================================
extern def PySlice_New(start: PyObject | t.CPtr, stop: PyObject | t.CPtr, step: PyObject | t.CPtr) -> PyObject | t.CPtr
extern def PySlice_GetIndicesEx(sl: PyObject | t.CPtr, length: t.CSizeT, start: t.CSizeT | t.CPtr, stop: t.CSizeT | t.CPtr, step: t.CSizeT | t.CPtr, slicelen: t.CSizeT | t.CPtr) -> t.CInt
extern def PySlice_Unpack(sl: PyObject | t.CPtr, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT | t.CPtr): pass
extern def PySlice_AdjustIndices(length: t.CSizeT, start: t.CPtrDiffT | t.CPtr, stop: t.CPtrDiffT | t.CPtr, step: t.CPtrDiffT) -> t.CSizeT
extern def PySlice_Check(obj: PyObject | t.CPtr) -> t.CInt
# ============================================================
# 类型包装类 — 带运算符重载
# ============================================================
# --- PyLongObj: Python 整数包装 ---
class PyLongObj:
ptr: PyObject | t.CPtr
def __new__(self) -> 'PyLongObj' | t.CPtr:
return t.CPtr(malloc(PyLongObj.__sizeof__()))
@staticmethod
def from_long(val: t.CLong) -> 'PyLongObj' | t.CPtr:
obj: PyLongObj | t.CPtr = PyLongObj()
obj.ptr = PyLong_FromLong(val)
return obj
def __add__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr:
res: PyLongObj | t.CPtr = PyLongObj()
res.ptr = PyNumber_Add(self.ptr, other.ptr)
return res
def __sub__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr:
res: PyLongObj | t.CPtr = PyLongObj()
res.ptr = PyNumber_Subtract(self.ptr, other.ptr)
return res
def __mul__(self, other: PyLongObj | t.CPtr) -> 'PyLongObj' | t.CPtr:
res: PyLongObj | t.CPtr = PyLongObj()
res.ptr = PyNumber_Multiply(self.ptr, other.ptr)
return res
def __neg__(self) -> 'PyLongObj' | t.CPtr:
res: PyLongObj | t.CPtr = PyLongObj()
res.ptr = PyNumber_Negative(self.ptr)
return res
def to_long(self) -> t.CLong:
return PyLong_AsLong(self.ptr)
def __str__(self) -> PyObject | t.CPtr:
return PyObject_Str(self.ptr)
def dec_ref(self):
Py_DecRef(self.ptr)
# --- PyFloatObj: Python 浮点数包装 ---
class PyFloatObj:
ptr: PyObject | t.CPtr
def __new__(self) -> 'PyFloatObj' | t.CPtr:
return t.CPtr(malloc(PyFloatObj.__sizeof__()))
@staticmethod
def from_double(val: t.CDouble) -> 'PyFloatObj' | t.CPtr:
obj: PyFloatObj | t.CPtr = PyFloatObj()
obj.ptr = PyFloat_FromDouble(val)
return obj
def __add__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr:
res: PyFloatObj | t.CPtr = PyFloatObj()
res.ptr = PyNumber_Add(self.ptr, other.ptr)
return res
def __sub__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr:
res: PyFloatObj | t.CPtr = PyFloatObj()
res.ptr = PyNumber_Subtract(self.ptr, other.ptr)
return res
def __mul__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr:
res: PyFloatObj | t.CPtr = PyFloatObj()
res.ptr = PyNumber_Multiply(self.ptr, other.ptr)
return res
def __truediv__(self, other: PyFloatObj | t.CPtr) -> 'PyFloatObj' | t.CPtr:
res: PyFloatObj | t.CPtr = PyFloatObj()
res.ptr = PyNumber_TrueDivide(self.ptr, other.ptr)
return res
def __neg__(self) -> 'PyFloatObj' | t.CPtr:
res: PyFloatObj | t.CPtr = PyFloatObj()
res.ptr = PyNumber_Negative(self.ptr)
return res
def to_double(self) -> t.CDouble:
return PyFloat_AsDouble(self.ptr)
def __str__(self) -> PyObject | t.CPtr:
return PyObject_Str(self.ptr)
def dec_ref(self):
Py_DecRef(self.ptr)
# --- PyUnicodeObj: Python 字符串包装 ---
class PyUnicodeObj:
ptr: PyObject | t.CPtr
def __new__(self) -> 'PyUnicodeObj' | t.CPtr:
return t.CPtr(malloc(PyUnicodeObj.__sizeof__()))
@staticmethod
def from_string(s: t.CChar | t.CPtr) -> 'PyUnicodeObj' | t.CPtr:
obj: PyUnicodeObj | t.CPtr = PyUnicodeObj()
obj.ptr = PyUnicode_FromString(s)
return obj
def __add__(self, other: PyUnicodeObj | t.CPtr) -> 'PyUnicodeObj' | t.CPtr:
res: PyUnicodeObj | t.CPtr = PyUnicodeObj()
res.ptr = PyUnicode_Concat(self.ptr, other.ptr)
return res
def __len__(self) -> t.CPtrDiffT:
return PyUnicode_GetLength(self.ptr)
def as_utf8(self) -> t.CChar | t.CPtr:
return PyUnicode_AsUTF8(self.ptr)
def __str__(self) -> PyObject | t.CPtr:
return self.ptr
def dec_ref(self):
Py_DecRef(self.ptr)
# --- PyListObj: Python 列表包装 ---
class PyListObj:
ptr: PyObject | t.CPtr
def __new__(self) -> 'PyListObj' | t.CPtr:
return t.CPtr(malloc(PyListObj.__sizeof__()))
@staticmethod
def new() -> 'PyListObj' | t.CPtr:
obj: PyListObj | t.CPtr = PyListObj()
obj.ptr = PyList_New(0)
return obj
def __getitem__(self, idx: t.CSizeT) -> PyObject | t.CPtr:
return PyList_GetItem(self.ptr, idx)
def __setitem__(self, idx: t.CSizeT, val: PyObject | t.CPtr):
PyList_SetItem(self.ptr, idx, val)
def __len__(self) -> t.CSizeT:
return PyList_Size(self.ptr)
def append(self, item: PyObject | t.CPtr) -> t.CInt:
return PyList_Append(self.ptr, item)
def dec_ref(self):
Py_DecRef(self.ptr)
# --- PyDictObj: Python 字典包装 ---
class PyDictObj:
ptr: PyObject | t.CPtr
def __new__(self) -> 'PyDictObj' | t.CPtr:
return t.CPtr(malloc(PyDictObj.__sizeof__()))
@staticmethod
def new() -> 'PyDictObj' | t.CPtr:
obj: PyDictObj | t.CPtr = PyDictObj()
obj.ptr = PyDict_New()
return obj
def __getitem__(self, key: PyObject | t.CPtr) -> PyObject | t.CPtr:
return PyDict_GetItem(self.ptr, key)
def __setitem__(self, key: PyObject | t.CPtr, val: PyObject | t.CPtr):
PyDict_SetItem(self.ptr, key, val)
def __len__(self) -> t.CSizeT:
return PyDict_Size(self.ptr)
def get_string(self, key: t.CChar | t.CPtr) -> PyObject | t.CPtr:
return PyDict_GetItemString(self.ptr, key)
def set_string(self, key: t.CChar | t.CPtr, val: PyObject | t.CPtr):
PyDict_SetItemString(self.ptr, key, val)
def dec_ref(self):
Py_DecRef(self.ptr)
+359
View File
@@ -0,0 +1,359 @@
import t, c
from t import CInt, CLong, CDouble, CPtr, CSizeT
from stdio import printf
import cpython
import testcheck
def test_init_finalize():
testcheck.section("Py_Initialize / Py_Finalize")
cpython.Py_Initialize()
testcheck.check(cpython.Py_IsInitialized() != 0, "Py_Initialize succeeded", "Py_Initialize succeeded")
cpython.Py_Finalize()
testcheck.check(cpython.Py_IsInitialized() == 0, "Py_Finalize succeeded", "Py_Finalize succeeded")
def test_long_operations():
testcheck.section("PyLong operations")
cpython.Py_Initialize()
# 创建整数
py_num: cpython.PyObject | CPtr = cpython.PyLong_FromLong(12345)
testcheck.check(py_num != 0, "PyLong_FromLong != NULL", "PyLong_FromLong != NULL")
# 整数转字符串
py_str: cpython.PyObject | CPtr = cpython.PyObject_Str(py_num)
testcheck.check(py_str != 0, "PyObject_Str != NULL", "PyObject_Str != NULL")
# 获取 C 字符串
c_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_str)
testcheck.check(c_str != 0, "PyUnicode_AsUTF8 != NULL", "PyUnicode_AsUTF8 != NULL")
printf(" PyLong_FromLong(12345) -> str = %s\n", c_str)
# 读取回来
val: CLong = cpython.PyLong_AsLong(py_num)
testcheck.check(val == 12345, "PyLong_AsLong == 12345", "PyLong_AsLong == 12345")
# 负数
py_neg: cpython.PyObject | CPtr = cpython.PyLong_FromLong(-999)
neg_val: CLong = cpython.PyLong_AsLong(py_neg)
testcheck.check(neg_val == -999, "PyLong_FromLong(-999) == -999", "PyLong_FromLong(-999) == -999")
# 浮点数转整数
py_dbl: cpython.PyObject | CPtr = cpython.PyFloat_FromDouble(3.14159)
testcheck.check(py_dbl != 0, "PyFloat_FromDouble != NULL", "PyFloat_FromDouble != NULL")
dbl_val: CDouble = cpython.PyFloat_AsDouble(py_dbl)
testcheck.check(dbl_val > 3.14 and dbl_val < 3.15, "PyFloat_AsDouble ~= 3.14", "PyFloat_AsDouble ~= 3.14")
# 清理
cpython.Py_DecRef(py_dbl)
cpython.Py_DecRef(py_neg)
cpython.Py_DecRef(py_str)
cpython.Py_DecRef(py_num)
cpython.Py_Finalize()
def test_string_operations():
testcheck.section("PyUnicode operations")
cpython.Py_Initialize()
# 从 C 字符串创建
py_s1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Hello, Viper!")
testcheck.check(py_s1 != 0, "PyUnicode_FromString != NULL", "PyUnicode_FromString != NULL")
# 获取 UTF8
utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_s1)
testcheck.check(utf8 != 0, "AsUTF8 != NULL", "AsUTF8 != NULL")
printf(" PyUnicode_FromString -> %s\n", utf8)
# 字符串长度
length: CLong = cpython.PyUnicode_GetLength(py_s1)
testcheck.check(length == 13, "GetLength == 13", "GetLength == 13")
# 字符串拼接
py_s2: cpython.PyObject | CPtr = cpython.PyUnicode_FromString(" World")
py_concat: cpython.PyObject | CPtr = cpython.PyUnicode_Concat(py_s1, py_s2)
concat_utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_concat)
testcheck.check(py_concat != 0, "Concat != NULL", "Concat != NULL")
printf(" Concat -> %s\n", concat_utf8)
# 清理
cpython.Py_DecRef(py_concat)
cpython.Py_DecRef(py_s2)
cpython.Py_DecRef(py_s1)
cpython.Py_Finalize()
def test_list_operations():
testcheck.section("PyList operations")
cpython.Py_Initialize()
# 创建列表
py_list: cpython.PyObject | CPtr = cpython.PyList_New(0)
testcheck.check(py_list != 0, "PyList_New != NULL", "PyList_New != NULL")
# Append 元素
py_i1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(10)
py_i2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(20)
py_i3: cpython.PyObject | CPtr = cpython.PyLong_FromLong(30)
cpython.PyList_Append(py_list, py_i1)
cpython.PyList_Append(py_list, py_i2)
cpython.PyList_Append(py_list, py_i3)
# 检查大小
list_size: CSizeT = cpython.PyList_Size(py_list)
testcheck.check(list_size == 3, "PyList_Size == 3", "PyList_Size == 3")
# 获取元素
item0: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 0)
val0: CLong = cpython.PyLong_AsLong(item0)
testcheck.check(val0 == 10, "list[0] == 10", "list[0] == 10")
item2: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 2)
val2: CLong = cpython.PyLong_AsLong(item2)
testcheck.check(val2 == 30, "list[2] == 30", "list[2] == 30")
# 清理
cpython.Py_DecRef(py_i3)
cpython.Py_DecRef(py_i2)
cpython.Py_DecRef(py_i1)
cpython.Py_DecRef(py_list)
cpython.Py_Finalize()
def test_dict_operations():
testcheck.section("PyDict operations")
cpython.Py_Initialize()
# 创建字典
py_dict: cpython.PyObject | CPtr = cpython.PyDict_New()
testcheck.check(py_dict != 0, "PyDict_New != NULL", "PyDict_New != NULL")
# 设置键值对
py_key1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("name")
py_val1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Viper")
cpython.PyDict_SetItem(py_dict, py_key1, py_val1)
py_key2: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("version")
py_val2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(1)
cpython.PyDict_SetItem(py_dict, py_key2, py_val2)
# 检查大小
dict_size: CSizeT = cpython.PyDict_Size(py_dict)
testcheck.check(dict_size == 2, "PyDict_Size == 2", "PyDict_Size == 2")
# 获取值
got_val: cpython.PyObject | CPtr = cpython.PyDict_GetItem(py_dict, py_key1)
testcheck.check(got_val != 0, "GetItem(name) != NULL", "GetItem(name) != NULL")
got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_val)
testcheck.check(got_str != 0, "name == Viper", "name == Viper")
printf(" dict['name'] = %s\n", got_str)
# 使用 GetItemString
got_ver: cpython.PyObject | CPtr = cpython.PyDict_GetItemString(py_dict, "version")
testcheck.check(got_ver != 0, "GetItemString(version) != NULL", "GetItemString(version) != NULL")
ver_val: CLong = cpython.PyLong_AsLong(got_ver)
testcheck.check(ver_val == 1, "version == 1", "version == 1")
# 清理
cpython.Py_DecRef(py_val2)
cpython.Py_DecRef(py_key2)
cpython.Py_DecRef(py_val1)
cpython.Py_DecRef(py_key1)
cpython.Py_DecRef(py_dict)
cpython.Py_Finalize()
def test_pyrun_string():
testcheck.section("PyRun_SimpleString")
cpython.Py_Initialize()
# 执行简单 Python 代码
rc: CInt = cpython.PyRun_SimpleString("print('Hello from embedded Python!')")
testcheck.check(rc == 0, "PyRun_SimpleString == 0", "PyRun_SimpleString == 0")
# 执行赋值
rc2: CInt = cpython.PyRun_SimpleString("x = 6 * 7")
testcheck.check(rc2 == 0, "PyRun_SimpleString(assign) == 0", "PyRun_SimpleString(assign) == 0")
# 读取结果
rc3: CInt = cpython.PyRun_SimpleString("print(f'The answer is {x}')")
testcheck.check(rc3 == 0, "PyRun_SimpleString(print) == 0", "PyRun_SimpleString(print) == 0")
cpython.Py_Finalize()
def test_import_module():
testcheck.section("PyImport_ImportModule")
cpython.Py_Initialize()
# 导入 math 模块
math_mod: cpython.PyObject | CPtr = cpython.PyImport_ImportModule("math")
testcheck.check(math_mod != 0, "import math != NULL", "import math != NULL")
if math_mod != 0:
# 获取 math.pi
pi_val: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "pi")
testcheck.check(pi_val != 0, "math.pi != NULL", "math.pi != NULL")
if pi_val != 0:
pi_dbl: CDouble = cpython.PyFloat_AsDouble(pi_val)
testcheck.check(pi_dbl > 3.14 and pi_dbl < 3.15, "math.pi ~= 3.14", "math.pi ~= 3.14")
printf(" math.pi = %f\n", pi_dbl)
cpython.Py_DecRef(pi_val)
# 获取 math.sqrt 函数
sqrt_func: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "sqrt")
testcheck.check(sqrt_func != 0, "math.sqrt != NULL", "math.sqrt != NULL")
if sqrt_func != 0:
cpython.Py_DecRef(sqrt_func)
cpython.Py_DecRef(math_mod)
cpython.Py_Finalize()
def test_operator_overload():
testcheck.section("Operator Overload (PyLongObj / PyFloatObj / PyUnicodeObj / PyListObj / PyDictObj)")
cpython.Py_Initialize()
# --- PyLongObj: from_long, to_long, +, -, *, - (neg) ---
a: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(10)
b: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(3)
testcheck.check(a != 0 and b != 0, "PyLongObj.from_long != NULL", "PyLongObj.from_long != NULL")
add_r: cpython.PyLongObj | CPtr = a + b
testcheck.check(add_r.to_long() == 13, "PyLongObj 10 + 3 == 13", "PyLongObj 10 + 3 == 13")
sub_r: cpython.PyLongObj | CPtr = a - b
testcheck.check(sub_r.to_long() == 7, "PyLongObj 10 - 3 == 7", "PyLongObj 10 - 3 == 7")
mul_r: cpython.PyLongObj | CPtr = a * b
testcheck.check(mul_r.to_long() == 30, "PyLongObj 10 * 3 == 30", "PyLongObj 10 * 3 == 30")
neg_r: cpython.PyLongObj | CPtr = -b
testcheck.check(neg_r.to_long() == -3, "PyLongObj -3 == -3", "PyLongObj -3 == -3")
mul_r.dec_ref()
sub_r.dec_ref()
add_r.dec_ref()
neg_r.dec_ref()
b.dec_ref()
a.dec_ref()
# --- PyFloatObj: from_double, to_double, +, -, *, /, - (neg) ---
fa: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(10.0)
fb: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(4.0)
testcheck.check(fa != 0 and fb != 0, "PyFloatObj.from_double != NULL", "PyFloatObj.from_double != NULL")
fadd: cpython.PyFloatObj | CPtr = fa + fb
testcheck.check(fadd.to_double() == 14.0, "PyFloatObj 10.0 + 4.0 == 14.0", "PyFloatObj 10.0 + 4.0 == 14.0")
fsub: cpython.PyFloatObj | CPtr = fa - fb
testcheck.check(fsub.to_double() == 6.0, "PyFloatObj 10.0 - 4.0 == 6.0", "PyFloatObj 10.0 - 4.0 == 6.0")
fmul: cpython.PyFloatObj | CPtr = fa * fb
testcheck.check(fmul.to_double() == 40.0, "PyFloatObj 10.0 * 4.0 == 40.0", "PyFloatObj 10.0 * 4.0 == 40.0")
fdiv: cpython.PyFloatObj | CPtr = fa / fb
testcheck.check(fdiv.to_double() == 2.5, "PyFloatObj 10.0 / 4.0 == 2.5", "PyFloatObj 10.0 / 4.0 == 2.5")
fneg: cpython.PyFloatObj | CPtr = -fb
testcheck.check(fneg.to_double() == -4.0, "PyFloatObj -4.0 == -4.0", "PyFloatObj -4.0 == -4.0")
fadd.dec_ref()
fsub.dec_ref()
fmul.dec_ref()
fdiv.dec_ref()
fneg.dec_ref()
fb.dec_ref()
fa.dec_ref()
# --- PyUnicodeObj: from_string, as_utf8, len, + (concat) ---
sa: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string("Hello")
sb: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string(" World")
testcheck.check(sa != 0 and sb != 0, "PyUnicodeObj.from_string != NULL", "PyUnicodeObj.from_string != NULL")
sc: cpython.PyUnicodeObj | CPtr = sa + sb
sc_utf8: t.CChar | CPtr = sc.as_utf8()
testcheck.check(sc_utf8 != 0, "PyUnicodeObj concat != NULL", "PyUnicodeObj concat != NULL")
if sc_utf8 != 0:
printf(" PyUnicodeObj 'Hello' + ' World' = %s\n", sc_utf8)
sa_len: t.CPtrDiffT = len(sa)
testcheck.check(sa_len == 5, "PyUnicodeObj len('Hello') == 5", "PyUnicodeObj len('Hello') == 5")
sc.dec_ref()
sb.dec_ref()
sa.dec_ref()
# --- PyListObj: new, append, len, [], []= ---
lst: cpython.PyListObj | CPtr = cpython.PyListObj.new()
testcheck.check(lst != 0, "PyListObj.new != NULL", "PyListObj.new != NULL")
if lst != 0:
e1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(100)
e2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(200)
e3: cpython.PyObject | CPtr = cpython.PyLong_FromLong(300)
lst.append(e1)
lst.append(e2)
lst.append(e3)
testcheck.check(len(lst) == 3, "PyListObj len == 3", "PyListObj len == 3")
item0: cpython.PyObject | CPtr = lst[t.CSizeT(0)]
testcheck.check(cpython.PyLong_AsLong(item0) == 100, "PyListObj lst[0] == 100", "PyListObj lst[0] == 100")
# __setitem__
e4: cpython.PyObject | CPtr = cpython.PyLong_FromLong(999)
lst[t.CSizeT(1)] = e4
item1: cpython.PyObject | CPtr = lst[t.CSizeT(1)]
testcheck.check(cpython.PyLong_AsLong(item1) == 999, "PyListObj lst[1] = 999", "PyListObj lst[1] = 999")
cpython.Py_DecRef(e4)
cpython.Py_DecRef(e3)
cpython.Py_DecRef(e2)
cpython.Py_DecRef(e1)
lst.dec_ref()
# --- PyDictObj: new, [], []=, len, set_string, get_string ---
dct: cpython.PyDictObj | CPtr = cpython.PyDictObj.new()
testcheck.check(dct != 0, "PyDictObj.new != NULL", "PyDictObj.new != NULL")
if dct != 0:
dk1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("lang")
dv1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Viper")
dct[dk1] = dv1
testcheck.check(len(dct) == 1, "PyDictObj len == 1", "PyDictObj len == 1")
got_lang: cpython.PyObject | CPtr = dct[dk1]
got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_lang)
testcheck.check(got_str != 0, "PyDictObj dct['lang'] == Viper", "PyDictObj dct['lang'] == Viper")
if got_str != 0:
printf(" PyDictObj dct['lang'] = %s\n", got_str)
# get_string / set_string
dct.set_string("ver", cpython.PyLong_FromLong(3))
got_ver: cpython.PyObject | CPtr = dct.get_string("ver")
testcheck.check(got_ver != 0 and cpython.PyLong_AsLong(got_ver) == 3, "PyDictObj get_string('ver') == 3", "PyDictObj get_string('ver') == 3")
cpython.Py_DecRef(dv1)
cpython.Py_DecRef(dk1)
dct.dec_ref()
cpython.Py_Finalize()
def main() -> CInt | t.CExport:
testcheck.begin("CPython Integration Test")
test_init_finalize()
test_long_operations()
test_string_operations()
test_list_operations()
test_dict_operations()
test_pyrun_string()
test_import_module()
test_operator_overload()
return testcheck.end()
+35
View File
@@ -0,0 +1,35 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "CPythonTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": [
"-L", "D:\\Python312\\libs",
"-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex",
"-lkernel32", "-luser32",
"-lpython312",
"-Wl,--allow-multiple-definition"
],
"output": "CPythonTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": false
}
}
+31
View File
@@ -0,0 +1,31 @@
import t, c
from stdint import *
import stdio
def bump(v: char) -> char:
return char(v + 1)
def main() -> t.CInt | t.CExport:
# 1) char 注解:char = t.CChar = i8(标量内置类型,非指针)
ch: char = 65
stdio.printf("1 char annot: %d (expect 65)\n", int(ch))
# 2) char() 强转 int→char:300 trunc 到 i8 → 44
big: char = char(300)
stdio.printf("2 char cast trunc: %d (expect 44)\n", int(big))
# 3) 函数返回 char(i8 存储)
nx: char = bump(ch)
stdio.printf("3 char return: %d (expect 66)\n", int(nx))
# 4) 单字符字面量 'Z' 赋给 char(90)
lit: char = 'Z'
stdio.printf("4 char literal: %d (expect 90)\n", int(lit))
# 5) char 参与算术(i8 与 int 混合提升)
s: int = ch + 1
stdio.printf("5 char arith: %d (expect 66)\n", s)
return 0
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "CharTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "CharTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+246
View File
@@ -0,0 +1,246 @@
import stdio
import stdlib
import stdint
import t, c
class SimpleData():
x: t.CInt
y: t.CInt
class Point3D():
x: t.CFloat
y: t.CFloat
z: t.CFloat
class Student():
name: t.CChar | t.CPtr
age: t.CInt
score: t.CInt
def __init__(self, n: t.CChar | t.CPtr, a: t.CInt, s: t.CInt):
self.name = n
self.age = a
self.score = s
def get_age(self) -> t.CInt:
return self.age
def get_score(self) -> t.CInt:
return self.score
class Counter():
value: t.CInt
def __init__(self, initial: t.CInt):
self.value = initial
def increment(self):
self.value += 1
def get_value(self) -> t.CInt:
return self.value
class StackObj():
data: t.CInt
next_ptr: t.CPtr
def TestBasicDataClass():
stdio.printf("=== Test Basic Data Class ===\n")
p: SimpleData = SimpleData()
p.x = 10
p.y = 20
stdio.printf("SimpleData: x=%d, y=%d\n", p.x, p.y)
def TestPoint3DClass():
stdio.printf("=== Test Point3D Class ===\n")
pt: Point3D = Point3D()
pt.x = 1.5
pt.y = 2.5
pt.z = 3.5
stdio.printf("Point3D: x=%.1f, y=%.1f, z=%.1f\n", pt.x, pt.y, pt.z)
def TestStudentClass():
stdio.printf("=== Test Student Class ===\n")
s: Student = Student("Alice", 20, 95)
stdio.printf("Student: name=%s, age=%d, score=%d\n", s.name, s.age, s.score)
stdio.printf(" get_age()=%d, get_score()=%d\n", s.get_age(), s.get_score())
def TestCounterClass():
stdio.printf("=== Test Counter Class ===\n")
cnt: Counter = Counter(0)
stdio.printf("Initial value: %d\n", cnt.get_value())
cnt.increment()
cnt.increment()
cnt.increment()
stdio.printf("After 3 increments: %d\n", cnt.get_value())
def TestStackAllocation():
stdio.printf("=== Test Stack Allocation ===\n")
obj1: SimpleData = SimpleData()
obj1.x = 100
obj1.y = 200
stdio.printf("Stack obj1: x=%d, y=%d\n", obj1.x, obj1.y)
obj2: Point3D = Point3D()
obj2.x = 10.0
obj2.y = 20.0
obj2.z = 30.0
stdio.printf("Stack obj2: x=%.1f, y=%.1f, z=%.1f\n", obj2.x, obj2.y, obj2.z)
def TestHeapAllocation():
stdio.printf("=== Test Heap Allocation ===\n")
ptr: t.CPtr = stdlib.malloc(1024)
if ptr != 0:
stdio.printf("Allocated 1024 bytes at %p\n", ptr)
stdlib.free(ptr)
stdio.printf("Freed memory\n")
else:
stdio.printf("malloc failed\n")
def TestHeapObjectWithInit():
stdio.printf("=== Test Heap Object with Init ===\n")
mem_size: t.CSizeT = 256
ptr: t.CPtr = stdlib.malloc(mem_size)
if ptr != 0:
stdio.printf("Allocated %d bytes\n", mem_size)
stdlib.free(ptr)
else:
stdio.printf("malloc failed\n")
def TestMultipleStackObjects():
stdio.printf("=== Test Multiple Stack Objects ===\n")
objs: SimpleData = SimpleData()
objs.x = 1
objs.y = 2
obj2: Point3D = Point3D()
obj2.x = 5.0
obj2.y = 10.0
obj2.z = 15.0
obj3: Counter = Counter(42)
stdio.printf("objs: x=%d, y=%d\n", objs.x, objs.y)
stdio.printf("obj2: x=%.1f, y=%.1f, z=%.1f\n", obj2.x, obj2.y, obj2.z)
stdio.printf("obj3 initial: %d\n", obj3.get_value())
obj3.increment()
obj3.increment()
stdio.printf("obj3 after 2 increments: %d\n", obj3.get_value())
def TestImplicitInitCall():
stdio.printf("=== Test Implicit Init Call ===\n")
stu1: Student = Student("Bob", 22, 88)
stu2: Student = Student("Charlie", 19, 77)
stdio.printf("stu1: name=%s, age=%d, score=%d\n", stu1.name, stu1.age, stu1.score)
stdio.printf("stu2: name=%s, age=%d, score=%d\n", stu2.name, stu2.age, stu2.score)
def TestClassWithBitFields():
stdio.printf("=== Test Class with Bit Fields ===\n")
flags: StackObj = StackObj()
flags.data = 0
flags.next_ptr = 0
stdio.printf("StackObj: data=%d, next_ptr=%p\n", flags.data, flags.next_ptr)
def TestIntArray():
stdio.printf("=== Test Int Array ===\n")
arr: t.CArray[t.CInt, 5] = t.CArray[t.CInt, 5]()
i: t.CInt = 0
while i < 5:
arr[i] = i * 10
i += 1
i = 0
while i < 5:
stdio.printf("arr[%d]=%d\n", i, arr[i])
i += 1
def TestFloatArray():
stdio.printf("=== Test Float Array ===\n")
farr: t.CArray[t.CFloat, 4] = t.CArray[t.CFloat, 4]()
farr[0] = 1.5
farr[1] = 2.5
farr[2] = 3.5
farr[3] = 4.5
i: t.CInt = 0
while i < 4:
stdio.printf("farr[%d]=%.1f\n", i, farr[i])
i += 1
def TestCharArray():
stdio.printf("=== Test Char Array (String) ===\n")
str_arr: t.CArray[t.CChar, 32] = t.CArray[t.CChar, 32]()
str_arr[0] = 'H'
str_arr[1] = 'e'
str_arr[2] = 'l'
str_arr[3] = 'l'
str_arr[4] = 'o'
str_arr[5] = '\0'
stdio.printf("String: %s\n", str_arr)
def TestNestedArray():
stdio.printf("=== Test Nested Array (Array of Arrays) ===\n")
row0: t.CArray[t.CInt, 3] = t.CArray[t.CInt, 3]()
row1: t.CArray[t.CInt, 3] = t.CArray[t.CInt, 3]()
row0[0] = 0
row0[1] = 1
row0[2] = 2
row1[0] = 10
row1[1] = 11
row1[2] = 12
i: t.CInt = 0
while i < 3:
stdio.printf("row0[%d]=%d ", i, row0[i])
i += 1
stdio.printf("\n")
i = 0
while i < 3:
stdio.printf("row1[%d]=%d ", i, row1[i])
i += 1
stdio.printf("\n")
def TestArrayWithStruct():
stdio.printf("=== Test Array with Struct ===\n")
points: t.CArray[SimpleData, 3] = t.CArray[SimpleData, 3]()
i: t.CInt = 0
while i < 3:
points[i].x = i * 10
points[i].y = i * 100
i += 1
i = 0
while i < 3:
stdio.printf("Point[%d]: x=%d, y=%d\n", i, points[i].x, points[i].y)
i += 1
def TestArrayPointer():
stdio.printf("=== Test Array Pointer ===\n")
data: t.CArray[t.CInt, 8] = t.CArray[t.CInt, 8]()
data[0] = 100
data[1] = 200
data[2] = 300
ptr: t.CInt | t.CPtr = data
stdio.printf("ptr[0]=%d\n", ptr[0])
stdio.printf("ptr[1]=%d\n", ptr[1])
stdio.printf("ptr[2]=%d\n", ptr[2])
def TestDynamicString():
stdio.printf("=== Test Dynamic String ===\n")
name: str = "TransPyC"
stdio.printf("Hello %s!\n", name)
+47
View File
@@ -0,0 +1,47 @@
import t, c
import testcheck
import class_test
def main() -> t.CInt:
testcheck.begin("ClassArrayTest: 类与数组测试")
testcheck.section("CLASS TESTS")
class_test.TestBasicDataClass()
testcheck.ok("TestBasicDataClass")
class_test.TestPoint3DClass()
testcheck.ok("TestPoint3DClass")
class_test.TestStudentClass()
testcheck.ok("TestStudentClass")
class_test.TestCounterClass()
testcheck.ok("TestCounterClass")
class_test.TestStackAllocation()
testcheck.ok("TestStackAllocation")
class_test.TestHeapAllocation()
testcheck.ok("TestHeapAllocation")
class_test.TestHeapObjectWithInit()
testcheck.ok("TestHeapObjectWithInit")
class_test.TestMultipleStackObjects()
testcheck.ok("TestMultipleStackObjects")
class_test.TestImplicitInitCall()
testcheck.ok("TestImplicitInitCall")
class_test.TestClassWithBitFields()
testcheck.ok("TestClassWithBitFields")
testcheck.section("ARRAY TESTS")
class_test.TestIntArray()
testcheck.ok("TestIntArray")
class_test.TestFloatArray()
testcheck.ok("TestFloatArray")
class_test.TestCharArray()
testcheck.ok("TestCharArray")
class_test.TestNestedArray()
testcheck.ok("TestNestedArray")
class_test.TestArrayWithStruct()
testcheck.ok("TestArrayWithStruct")
class_test.TestArrayPointer()
testcheck.ok("TestArrayPointer")
class_test.TestDynamicString()
testcheck.ok("TestDynamicString")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ClassArrayTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "ClassArrayTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+39
View File
@@ -0,0 +1,39 @@
import t
import stdio
import testcheck
# ============================================================
# ClosureCallTest - t.CPtr 函数指针调用最小化复现
#
# closure_test.py 中 f: t.CPtr = make_counter() 后调用 f() 报错:
# Undefined function: 'f'
# 根因:f 是 t.CPtr(i8*),line 322 检查 pointee 是 FunctionType 失败
# ============================================================
# nonlocal 关键字测试:嵌套函数修改外层局部变量
def make_counter() -> t.CPtr:
count: int = 0
# 内部函数(闭包)捕获 count
def counter() -> int:
nonlocal count
count = count + 1
return count
return counter
def test_closure_call():
"""验证 t.CPtr 函数指针调用"""
testcheck.section("Closure call via t.CPtr")
f: t.CPtr = make_counter()
v: int = f()
testcheck.check(v == 1, "f() first call = 1", "expect 1")
def main() -> t.CInt:
testcheck.begin("ClosureCallTest: t.CPtr function pointer call")
test_closure_call()
return testcheck.end()
+39
View File
@@ -0,0 +1,39 @@
{
"name": "ClosureCallTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "ClosureCallTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+164
View File
@@ -0,0 +1,164 @@
import t
import stdio
import testcheck
# ============================================================
# Test 1: global 在嵌套函数中
# ============================================================
g_val: t.CInt = 100
def outer_modify_global():
global g_val
def inner_modify():
global g_val
g_val += 50
inner_modify()
def test_global_in_nested():
testcheck.section("Test 1: global in nested function")
global g_val
g_val = 100
outer_modify_global()
testcheck.check(g_val == 150, "global nested (g_val == 150)", "global nested (expect 150)")
# ============================================================
# Test 2: nonlocal 在多层嵌套中
# ============================================================
def test_nonlocal_multi_level():
testcheck.section("Test 2: nonlocal multi-level")
x: t.CInt = 1
def level1():
nonlocal x
x += 10
def level2():
nonlocal x
x += 100
def level3():
nonlocal x
x += 1000
level3()
level2()
level1()
testcheck.check(x == 1111, "nonlocal multi (x == 1111)", "nonlocal multi (expect 1111)")
# ============================================================
# Test 3: global 和 nonlocal 混合
# ============================================================
g_mixed: t.CInt = 0
def test_global_nonlocal_mixed():
testcheck.section("Test 3: global + nonlocal mixed")
global g_mixed
g_mixed = 0
local_var: t.CInt = 0
def modify_both():
nonlocal local_var
global g_mixed
g_mixed += 10
local_var += 20
modify_both()
modify_both()
testcheck.check(g_mixed == 20 and local_var == 40, "mixed (global==20 local==40)", "mixed (expect global=20 local=40)")
# ============================================================
# Test 4: lambda 捕获多个变量
# ============================================================
def test_lambda_multi_capture():
testcheck.section("Test 4: lambda multi-capture")
a: t.CInt = 10
b: t.CInt = 20
f = lambda: a + b
r: t.CInt = f()
testcheck.check(r == 30, "lambda multi-capture (a+b == 30)", "lambda multi-capture (expect 30)")
# ============================================================
# Test 5: lambda 带参数 + 捕获
# ============================================================
def test_lambda_arg_capture():
testcheck.section("Test 5: lambda arg + capture")
base: t.CInt = 100
add = lambda x: base + x
r: t.CInt = add(42)
testcheck.check(r == 142, "lambda arg+capture (100+42 == 142)", "lambda arg+capture (expect 142)")
# ============================================================
# Test 6: 嵌套函数返回值
# ============================================================
def test_nested_return():
testcheck.section("Test 6: nested function return")
x: t.CInt = 5
def double_x() -> t.CInt:
nonlocal x
x = x * 2
return x
r: t.CInt = double_x()
testcheck.check(r == 10 and x == 10, "nested return (r==10 x==10)", "nested return (expect r=10 x=10)")
# ============================================================
# Test 7: nonlocal 与循环变量
# ============================================================
def test_nonlocal_loop():
testcheck.section("Test 7: nonlocal with loop")
total: t.CInt = 0
def accumulate(n: t.CInt):
nonlocal total
for i in range(n):
total += i
accumulate(5)
accumulate(5)
# 0+1+2+3+4 = 10, twice = 20
testcheck.check(total == 20, "nonlocal loop (total == 20)", "nonlocal loop (expect 20)")
# ============================================================
# Test 8: global 数组操作
# ============================================================
g_arr: t.CArray[t.CInt, 4] = [0]
def test_global_array():
testcheck.section("Test 8: global array")
global g_arr
g_arr[0] = 10
g_arr[1] = 20
g_arr[2] = 30
g_arr[3] = 40
total: t.CInt = g_arr[0] + g_arr[1] + g_arr[2] + g_arr[3]
testcheck.check(total == 100, "global array (total == 100)", "global array (expect 100)")
# ============================================================
# Test 9: 嵌套函数条件调用
# ============================================================
def test_nested_conditional():
testcheck.section("Test 9: nested conditional call")
result: t.CInt = 0
def set_result(val: t.CInt):
nonlocal result
result = val
if 1:
set_result(42)
else:
set_result(99)
testcheck.check(result == 42, "nested conditional (result == 42)", "nested conditional (expect 42)")
# ============================================================
# Test 10: lambda 链式调用
# ============================================================
def test_lambda_chain():
testcheck.section("Test 10: lambda chain")
f1 = lambda: 10
f2 = lambda: 20
r: t.CInt = f1() + f2()
testcheck.check(r == 30, "lambda chain (10+20 == 30)", "lambda chain (expect 30)")
def main() -> t.CInt:
testcheck.begin("ClosureAdvancedTest: 高级闭包测试")
test_global_in_nested()
test_nonlocal_multi_level()
test_global_nonlocal_mixed()
test_lambda_multi_capture()
test_lambda_arg_capture()
test_nested_return()
test_nonlocal_loop()
test_global_array()
test_nested_conditional()
test_lambda_chain()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ClosureTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "ClosureTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+220
View File
@@ -0,0 +1,220 @@
import t
import stdio
import testcheck
# ============================================================
# Test 1: nonlocal 在条件分支中修改
# ============================================================
def test_nonlocal_conditional():
testcheck.section("Test 1: nonlocal in conditional branches")
x: t.CInt = 0
def modify(flag: t.CInt):
nonlocal x
if flag:
x += 10
else:
x += 100
modify(1)
modify(0)
modify(1)
testcheck.check(x == 120, "nonlocal conditional (x == 120)", "nonlocal conditional (expect 120)")
# ============================================================
# Test 2: 多个nonlocal变量同时修改
# ============================================================
def test_nonlocal_multi_var():
testcheck.section("Test 2: multiple nonlocal variables")
a: t.CInt = 1
b: t.CInt = 2
c_val: t.CInt = 3
def swap_add():
nonlocal a, b, c_val
tmp: t.CInt = a
a = b
b = c_val
c_val = tmp
swap_add()
testcheck.check(a == 2 and b == 3 and c_val == 1, "multi nonlocal (a==2 b==3 c==1)", "multi nonlocal (expect 2 3 1)")
# ============================================================
# Test 3: global 在多个函数中交叉修改
# ============================================================
g_counter: t.CInt = 0
def inc_global():
global g_counter
g_counter += 1
def add_global(n: t.CInt):
global g_counter
g_counter += n
def test_global_cross_functions():
testcheck.section("Test 3: global cross-function modification")
global g_counter
g_counter = 0
inc_global()
inc_global()
add_global(10)
inc_global()
testcheck.check(g_counter == 13, "global cross (g_counter == 13)", "global cross (expect 13)")
# ============================================================
# Test 4: 嵌套函数修改外层局部变量(引用捕获)
# ============================================================
def test_nested_ref_capture():
testcheck.section("Test 4: nested function ref capture")
arr: t.CArray[t.CInt, 4] = [0]
def fill():
nonlocal arr
for i in range(4):
arr[i] = (i + 1) * 10
fill()
total: t.CInt = arr[0] + arr[1] + arr[2] + arr[3]
testcheck.check(total == 100, "ref capture (total == 100)", "ref capture (expect 100)")
# ============================================================
# Test 5: lambda捕获后修改原变量
# ============================================================
def test_lambda_capture_then_modify():
testcheck.section("Test 5: lambda capture then modify")
x: t.CInt = 10
f = lambda: x
r1: t.CInt = f()
x = 20
r2: t.CInt = f()
testcheck.check(r1 == 10 and r2 == 10, "lambda value capture (before==10 after==10)", "lambda value capture (expect 10 10)")
# ============================================================
# Test 6: 嵌套函数中nonlocal与循环结合
# ============================================================
def test_nonlocal_loop_accumulate():
testcheck.section("Test 6: nonlocal with loop accumulate")
sum_val: t.CInt = 0
count: t.CInt = 0
def add_numbers(n: t.CInt):
nonlocal sum_val, count
for i in range(1, n + 1):
sum_val += i
count += 1
add_numbers(5) # 1+2+3+4+5=15
add_numbers(3) # 1+2+3=6
testcheck.check(sum_val == 21 and count == 8, "loop accumulate (sum==21 count==8)", "loop accumulate (expect 21 8)")
# ============================================================
# Test 7: 三层嵌套中每层修改不同变量
# ============================================================
def test_deep_nested_vars():
testcheck.section("Test 7: deep nested different vars")
a: t.CInt = 0
b: t.CInt = 0
c_val: t.CInt = 0
def level1():
nonlocal a
a += 1
def level2():
nonlocal b
b += 10
def level3():
nonlocal c_val
c_val += 100
level3()
level2()
level1()
level1()
testcheck.check(a == 2 and b == 20 and c_val == 200, "deep nested (a==2 b==20 c==200)", "deep nested (expect 2 20 200)")
# ============================================================
# Test 8: global + nonlocal 在同一嵌套函数中
# ============================================================
g_state: t.CInt = 0
def test_global_nonlocal_same_func():
testcheck.section("Test 8: global+nonlocal in same nested func")
global g_state
g_state = 0
local_state: t.CInt = 0
def worker(n: t.CInt):
nonlocal local_state
global g_state
for i in range(n):
g_state += 1
local_state += 2
worker(5)
testcheck.check(g_state == 5 and local_state == 10, "global+nonlocal same (g==5 l==10)", "global+nonlocal same (expect 5 10)")
# ============================================================
# Test 9: lambda带默认参数与捕获
# ============================================================
def test_lambda_default_and_capture():
testcheck.section("Test 9: lambda with arg and capture")
base: t.CInt = 100
multiply = lambda x: base * x
r1: t.CInt = multiply(3)
r2: t.CInt = multiply(5)
testcheck.check(r1 == 300 and r2 == 500, "lambda arg+capture (100*3==300 100*5==500)", "lambda arg+capture (expect 300 500)")
# ============================================================
# Test 10: 嵌套函数多次调用累积
# ============================================================
def test_nested_accumulate():
testcheck.section("Test 10: nested function accumulate")
total: t.CInt = 0
def add_val(n: t.CInt):
nonlocal total
total += n
add_val(10)
add_val(20)
add_val(30)
testcheck.check(total == 60, "nested accumulate (total == 60)", "nested accumulate (expect 60)")
# ============================================================
# Test 11: nonlocal在while循环中
# ============================================================
def test_nonlocal_while():
testcheck.section("Test 11: nonlocal in while loop")
result: t.CInt = 0
def countdown(n: t.CInt):
nonlocal result
i: t.CInt = n
while i > 0:
result += i
i -= 1
countdown(5) # 5+4+3+2+1=15
testcheck.check(result == 15, "nonlocal while (result == 15)", "nonlocal while (expect 15)")
# ============================================================
# Test 12: 嵌套函数修改结构体字段
# ============================================================
class Point:
x: t.CInt
y: t.CInt
def test_nested_modify_struct():
testcheck.section("Test 12: nested modify struct")
p: Point = Point()
p.x = 0
p.y = 0
def translate(dx: t.CInt, dy: t.CInt):
nonlocal p
p.x += dx
p.y += dy
translate(10, 20)
translate(5, 15)
testcheck.check(p.x == 15 and p.y == 35, "nested struct (x==15 y==35)", "nested struct (expect 15 35)")
def main() -> t.CInt:
testcheck.begin("ClosureTest2: Advanced Closure/Lambda/Global/Nonlocal")
test_nonlocal_conditional()
test_nonlocal_multi_var()
test_global_cross_functions()
test_nested_ref_capture()
test_lambda_capture_then_modify()
test_nonlocal_loop_accumulate()
test_deep_nested_vars()
test_global_nonlocal_same_func()
test_lambda_default_and_capture()
test_nested_accumulate()
test_nonlocal_while()
test_nested_modify_struct()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ClosureTest2",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "ClosureTest2.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+41
View File
@@ -0,0 +1,41 @@
import t, c
from stdint import *
import stdio
import coro
class MyError(Exception):
pass
async def leaf(x: int) -> int:
return x + 1
async def boom() -> int:
raise MyError("boom msg")
return 0
async def task() -> int:
fin: int = 0
try:
fin = 1
await boom()
finally:
fin = fin + 1
stdio.printf("finally ran, fin = %d\n", fin)
return 99
def main() -> t.CInt:
n: t.CInt = 0
for i in range(3):
tt: coro.Coroutine = c.Addr(task())
r: t.CInt = coro.coro_run(tt)
e: t.CInt = coro.coro_exception(tt)
m: t.CPtr = coro.coro_exception_msg(tt)
stdio.printf("[%d] r = %d, exc = %d, msg = %s\n", i, r, e, m)
coro.coro_destroy(tt)
n = n + 1
return 0
+39
View File
@@ -0,0 +1,39 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "CoroTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "CoroTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+299
View File
@@ -0,0 +1,299 @@
import t
from stdio import printf
import testcheck
# ============================================================
# 自定义装饰器处理函数
# 调用约定 (v4):
# i32 decor_name(i8* ctx, i8* func_name, i32 phase,
# i8* args_ptr, i8* ret_ptr, i8* decor_args_ptr)
#
# ctx: 栈帧局部上下文(32字节),每次调用独立,线程/递归安全
# args_ptr: 可读写,装饰器可修改函数入参
# ret_ptr: 后置阶段可读写,装饰器可修改返回值
# 返回值(前置阶段):
# 0 = 跳过原函数调用
# 1 = 正常调用一次
# N = 循环调用 N 次
# ============================================================
# @log 装饰器:打印函数进入/退出,返回 1(正常调用一次)
def log(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
if phase == 0:
printf("[LOG] >> %s enter\n", func_name)
return 1
else:
printf("[LOG] << %s exit\n", func_name)
return 0
# @trace 装饰器:详细追踪
def trace(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
if phase == 0:
printf("[TRACE] calling %s...\n", func_name)
return 1
else:
printf("[TRACE] %s returned\n", func_name)
return 0
# @timing 装饰器:使用全局变量记录计时
# 注意:理想情况下应使用 ctx 栈帧局部上下文替代全局变量,
# 但 Viper 当前前端尚不支持 i8* 到 i32* 的指针转型,
# 因此暂时使用全局变量演示计时逻辑
_timing_tmp: t.CInt = 0
def timing(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
global _timing_tmp
if phase == 0:
_timing_tmp = 100
printf("[TIMING] %s start at t=%d\n", func_name, _timing_tmp)
return 1
else:
elapsed: t.CInt = 105 - _timing_tmp
printf("[TIMING] %s took %d ms\n", func_name, elapsed)
return 0
# @repeat 装饰器(带参数,流程劫持):循环调用原函数 N 次
def repeat(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
if phase == 0:
printf("[REPEAT] %s will run 3 times\n", func_name)
return 3
else:
printf("[REPEAT] %s all iterations done\n", func_name)
return 0
# @skip 装饰器:跳过原函数调用(流程劫持,返回 0)
_skip_count: t.CInt = 0
def skip(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
global _skip_count
if phase == 0:
_skip_count = _skip_count + 1
printf("[SKIP] %s skipped! (call #%d)\n", func_name, _skip_count)
return 0
else:
printf("[SKIP] %s post (ret_ptr=%p)\n", func_name, ret_ptr)
return 0
# @count_calls 装饰器:统计函数被调用次数(递归保护测试用)
_call_count: t.CInt = 0
def count_calls(ctx: t.CPtr, func_name: str, phase: t.CInt,
args_ptr: t.CPtr,
ret_ptr: t.CPtr,
decor_args_ptr: t.CPtr) -> t.CInt | t.CExport:
global _call_count
if phase == 0:
_call_count = _call_count + 1
printf("[COUNT] %s call #%d\n", func_name, _call_count)
return 1
else:
printf("[COUNT] %s done (total calls: %d)\n", func_name, _call_count)
return 0
# ============================================================
# 测试 1:单个装饰器 @log
# ============================================================
@log
def add(a: t.CInt, b: t.CInt) -> t.CInt | t.CExport:
return a + b
# ============================================================
# 测试 2:链式装饰器 @log @trace => log(trace(f))
# 执行顺序:log_pre → trace_pre → f → trace_post → log_post
# ============================================================
@log
@trace
def multiply(a: t.CInt, b: t.CInt) -> t.CInt | t.CExport:
return a * b
# ============================================================
# 测试 3:装饰器修饰 void 返回函数
# ============================================================
@log
def greet(name: str) -> t.CVoid | t.CExport:
printf("Hello, %s!\n", name)
# ============================================================
# 测试 4:装饰器修饰无参数函数
# ============================================================
@log
def get_value() -> t.CInt | t.CExport:
return 42
# ============================================================
# 测试 5:@timing 装饰器
# ============================================================
@timing
export def compute(x: t.CInt) -> t.CInt:
return x * x + 1
# ============================================================
# 测试 6:带参数装饰器 @repeat(3) — 流程劫持,循环调用 3 次
# ============================================================
@repeat(3)
export def echo(msg: str):
printf(" echo: %s\n", msg)
# ============================================================
# 测试 7:链式 @timing @log
# ============================================================
@timing
@log
export def power(base: t.CInt, exp: t.CInt) -> t.CInt:
result: t.CInt = 1
i: t.CInt = 0
while i < exp:
result = result * base
i = i + 1
return result
# ============================================================
# 测试 8:@skip 装饰器 — 流程劫持,跳过原函数调用
# ============================================================
@skip
def dangerous() -> t.CInt | t.CExport:
printf("This should NOT be printed!\n")
return 999
# ============================================================
# 测试 9:@repeat(3) 修饰有返回值的函数
# ============================================================
@repeat(3)
def accumulate(x: t.CInt) -> t.CInt | t.CExport:
printf(" accumulate(%d)\n", x)
return x * 10
# ============================================================
# 测试 10:递归装饰保护 — @count_calls 修饰递归函数
# v4 递归保护:最外层 wrapper 检查全局标志位,
# 递归调用时跳过所有装饰逻辑,仅最外层调用触发装饰器
# ============================================================
@count_calls
def factorial(n: t.CInt) -> t.CInt | t.CExport:
if n <= 1:
return 1
return n * factorial(n - 1)
# ============================================================
# 测试 11:@log 修饰递归函数 — 验证递归保护
# 递归保护确保只有最外层调用打印 LOG,内部递归不触发
# ============================================================
@log
def fib(n: t.CInt) -> t.CInt | t.CExport:
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
# ============================================================
# 主函数
# ============================================================
def main() -> t.CInt | t.CExport:
testcheck.begin("Decorator Test v4")
# 测试 1:单个 @log
testcheck.section("Test 1: single @log")
r1: t.CInt = add(3, 4)
printf("add(3,4) = %d\n", r1)
testcheck.check(r1 == 7, "add(3,4) = 7", "add(3,4) expect 7")
# 测试 2:链式 @log @trace
testcheck.section("Test 2: chained @log @trace")
r2: t.CInt = multiply(5, 6)
printf("multiply(5,6) = %d\n", r2)
testcheck.check(r2 == 30, "multiply(5,6) = 30", "multiply(5,6) expect 30")
# 测试 3:void 返回
testcheck.section("Test 3: @log on void function")
greet("Viper")
testcheck.ok("@log on void function greet")
# 测试 4:无参数
testcheck.section("Test 4: @log on no-arg function")
r4: t.CInt = get_value()
printf("get_value() = %d\n", r4)
testcheck.check(r4 == 42, "get_value() = 42", "get_value() expect 42")
# 测试 5:@timing
testcheck.section("Test 5: @timing")
r5: t.CInt = compute(7)
printf("compute(7) = %d\n", r5)
testcheck.check(r5 == 50, "compute(7) = 50", "compute(7) expect 50")
# 测试 6:@repeat(3) — 流程劫持,循环 3 次
testcheck.section("Test 6: @repeat(3) flow hijack")
echo("hello")
testcheck.ok("@repeat(3) flow hijack echo")
# 测试 7:链式 @timing @log
testcheck.section("Test 7: chained @timing @log")
r7: t.CInt = power(2, 10)
printf("power(2,10) = %d\n", r7)
testcheck.check(r7 == 1024, "power(2,10) = 1024", "power(2,10) expect 1024")
# 测试 8:@skip — 跳过原函数调用
testcheck.section("Test 8: @skip flow hijack")
r8: t.CInt = dangerous()
printf("dangerous() = %d (should be 0, skipped)\n", r8)
testcheck.check(r8 == 0, "dangerous() skipped = 0", "dangerous() expect 0")
# 测试 9:@repeat(3) 有返回值
testcheck.section("Test 9: @repeat(3) with return value")
r9: t.CInt = accumulate(5)
printf("accumulate(5) = %d (last iteration result)\n", r9)
testcheck.check(r9 == 50, "accumulate(5) = 50", "accumulate(5) expect 50")
# 测试 10:递归装饰保护 — @count_calls
testcheck.section("Test 10: recursive decoration protection")
global _call_count
_call_count = 0
r10: t.CInt = factorial(5)
printf("factorial(5) = %d (should be 120)\n", r10)
printf(" decorator call count = %d (should be 1, not 5)\n", _call_count)
testcheck.check(r10 == 120 and _call_count == 1, "factorial(5)=120, calls=1", "factorial(5) expect 120, calls=1")
# 测试 11:@log 递归保护 — fib
testcheck.section("Test 11: @log on recursive fib")
r11: t.CInt = fib(6)
printf("fib(6) = %d (should be 8)\n", r11)
testcheck.check(r11 == 8, "fib(6) = 8", "fib(6) expect 8")
return testcheck.end()
+39
View File
@@ -0,0 +1,39 @@
{
"name": "DecoratorTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "DecoratorTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+70
View File
@@ -0,0 +1,70 @@
import t
import stdio
import testcheck
import remote
import vrandom
# 同模块:单个尾随默认值
def local_one(x: int, cap: t.CSizeT = 4096) -> t.CSizeT:
return cap
# 同模块:多个尾随默认值
def local_quad(a: int, b: int = 10, c: int = 20, d: int = 30) -> int:
return a + b * 100 + c * 10000 + d * 1000000
def main() -> t.CInt:
testcheck.begin("DefaultArgTest: default / named / out-of-order arguments")
# ① 同模块默认值
testcheck.section("same-module defaults")
r1: t.CSizeT = local_one(1)
testcheck.check(r1 == 4096, "local_one(1) cap = 4096", "local_one(1) cap != 4096")
r2: int = local_quad(1)
testcheck.check(r2 == 30201001, "local_quad(1) = 30201001", "local_quad(1) != 30201001")
# ② 跨模块默认值
testcheck.section("cross-module defaults")
r3: t.CSizeT = remote.one(1)
testcheck.check(r3 == 4096, "remote.one(1) cap = 4096", "remote.one(1) cap != 4096")
r4: t.CSizeT = remote.write(1, 2, False)
testcheck.check(r4 == 4096, "remote.write(1,2,False) cap = 4096", "remote.write(1,2,False) cap != 4096")
# ③ 显式覆盖默认值
testcheck.section("explicit override")
r5: t.CSizeT = remote.one(1, 8)
testcheck.check(r5 == 8, "remote.one(1,8) cap = 8", "remote.one(1,8) cap != 8")
# ④ 命名 / 乱序传参
testcheck.section("named / out-of-order arguments")
r6: t.CSizeT = remote.one(cap = 8, x = 1)
testcheck.check(r6 == 8, "remote.one(cap = 8, x = 1) = 8", "remote.one(cap = 8, x = 1) != 8")
r7: t.CSizeT = remote.one(x = 1, cap = 8)
testcheck.check(r7 == 8, "remote.one(x = 1, cap = 8) = 8", "remote.one(x = 1, cap = 8) != 8")
r8: t.CSizeT = remote.one(x = 1)
testcheck.check(r8 == 4096, "remote.one(x = 1) cap = 4096", "remote.one(x = 1) cap != 4096")
r9: int = remote.many(z = 3, x = 1, y = 2)
testcheck.check(r9 == 9, "remote.many(z = 3, x = 1, y = 2) = 9", "remote.many(z = 3, x = 1, y = 2) != 9")
# ⑤ 多个尾随默认值只给前几个
testcheck.section("partial trailing defaults")
r10: int = local_quad(1, 2)
testcheck.check(r10 == 30200201, "local_quad(1,2) = 30200201", "local_quad(1,2) != 30200201")
r11: int = remote.quad(1, 2)
testcheck.check(r11 == 30200201, "remote.quad(1,2) = 30200201", "remote.quad(1,2) != 30200201")
r12: int = local_quad(1, 2, 3)
testcheck.check(r12 == 30030201, "local_quad(1,2,3) = 30030201", "local_quad(1,2,3) != 30030201")
r13: int = remote.quad(1, 2, 3)
testcheck.check(r13 == 30030201, "remote.quad(1,2,3) = 30030201", "remote.quad(1,2,3) != 30030201")
r14: int = remote.quad(1)
testcheck.check(r14 == 30201001, "remote.quad(1) = 30201001", "remote.quad(1) != 30201001")
# ⑥ include 模块(顶层 .vp)默认值:vrandom.randrange(start, stop, step = 1)
# stop-start==1 ⇒ width==1 ⇒ 结果恒为 start;step 未填充时会退化为 0/垃圾
testcheck.section("include-module defaults")
r15: t.CInt = vrandom.randrange(5, 6)
testcheck.check(r15 == 5, "vrandom.randrange(5,6) = 5 (step default)", "vrandom.randrange(5,6) != 5")
return testcheck.end()
+21
View File
@@ -0,0 +1,21 @@
import t
# 跨模块:单个尾随默认值(对照 includes/json/__writer.vp 的 write 形态)
def one(x: int, cap: t.CSizeT = 4096) -> t.CSizeT:
return cap
# 跨模块:4 参、最后一个有默认值(与 json.write(pool, val, pretty, cap=4096) 同形)
def write(a: int, b: int, pretty: bool, cap: t.CSizeT = 4096) -> t.CSizeT:
return cap
# 跨模块:多个尾随默认值
def quad(a: int, b: int = 10, c: int = 20, d: int = 30) -> int:
return a + b * 100 + c * 10000 + d * 1000000
# 跨模块:乱序/命名传参(wiki 04-functions.md 的 add 形态)
def many(x: int, y: int, z: int = 1) -> int:
return (x + y) * z
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "DefaultArgTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "DefaultArgTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+421
View File
@@ -0,0 +1,421 @@
import t, c
from t import CInt, CInt32T, CUInt32T, CUInt64T, CFloat64T, CPtr, CChar, CDefine, CUInt16T
import viperlib
import stdlib
import platmacro
import w32.win32console
import testcheck
# ============================================================
# DefineTest - CDefine 宏 / c.CIf / platmacro 专项测试
#
# 从 TestProject3/App/definetest.vp 独立提取。
# 验证: CDefine 常量、宏函数、c.CIf/c.CIfdef/c.CIfndef、
# platmacro 平台宏(输出以 print 为准,人工核对)。
# ============================================================
MAX_SIZE: t.CDefine = 1024
MIN_VAL: t.CDefine = 0
MAX_VAL: t.CDefine = 100
MASK_BYTE: t.CDefine = 0xFF
SHIFT_BITS: t.CDefine = 8
PI_INT: t.CDefine = 3
ENABLED: t.CDefine = 1
DISABLED: t.CDefine = 0
PAGE_SIZE: t.CDefine = 4096
BUFFER_LEN: t.CDefine = 256
CODE_SEG: t.CDefine | t.CUInt16T = 0x08
DATA_SEG: t.CDefine | t.CUInt16T = 0x10
STACK_SEG: t.CDefine | t.CUInt16T = 0x20
def MAKE_FLAG(bit: CInt32T) -> t.CDefine:
return 1 << bit
def CLAMP(x: CInt32T, lo: CInt32T, hi: CInt32T) -> t.CDefine:
if x < lo:
return lo
if x > hi:
return hi
return x
def test_basic_define() -> CInt:
print(MAX_SIZE)
print(MIN_VAL)
print(MAX_VAL)
print(MASK_BYTE)
print(SHIFT_BITS)
return 0
def test_define_arithmetic() -> CInt:
a: CInt32T = 10
b: CInt32T = a + MAX_SIZE
print(b)
c_val: CInt32T = (a << SHIFT_BITS) & MASK_BYTE
print(c_val)
d: CInt32T = MAX_VAL - MIN_VAL
print(d)
e: CInt32T = PAGE_SIZE / 4
print(e)
return 0
def test_define_conditional() -> CInt:
mode: CInt32T = ENABLED
if mode == ENABLED:
print(1)
else:
print(0)
if mode == DISABLED:
print(0)
else:
print(1)
val: CInt32T = 50
if val > MAX_VAL:
print(1)
else:
print(0)
if val < MAX_VAL:
print(1)
else:
print(0)
return 0
def test_define_loop() -> CInt:
i: CInt32T = 0
while i < MAX_VAL:
i = i + 1
if i > 10:
break
print(i)
i = 0
while i < MAX_SIZE:
i = i + PAGE_SIZE
if i >= PAGE_SIZE * 4:
break
print(i)
return 0
def test_typed_define() -> CInt:
seg: CUInt16T = CODE_SEG | DATA_SEG | STACK_SEG
print(seg)
cs: CUInt16T = CODE_SEG
print(cs)
ds: CUInt16T = DATA_SEG
print(ds)
return 0
def test_define_function() -> CInt:
flag0 = MAKE_FLAG(0)
print(flag0)
flag3 = MAKE_FLAG(3)
print(flag3)
flag7 = MAKE_FLAG(7)
print(flag7)
return 0
def test_define_clamp() -> CInt:
v1 = CLAMP(50, 0, 100)
print(v1)
v2 = CLAMP(-10, 0, 100)
print(v2)
v3 = CLAMP(150, 0, 100)
print(v3)
return 0
def test_define_string() -> CInt:
buf: CChar | CPtr = CPtr(stdlib.malloc(BUFFER_LEN))
viperlib.snprintf(buf, BUFFER_LEN, "MAX_SIZE=%d PAGE=%d MASK=0x%x", MAX_SIZE, PAGE_SIZE, MASK_BYTE)
print(buf)
stdlib.free(buf)
return 0
def test_define_combined() -> CInt:
flags: CUInt32T = MAKE_FLAG(0) | MAKE_FLAG(1) | MAKE_FLAG(2)
print(flags)
shifted: CUInt32T = MASK_BYTE << SHIFT_BITS
print(shifted)
total: CUInt32T = PAGE_SIZE + BUFFER_LEN
print(total)
return 0
def test_cif_basic() -> CInt:
if c.CIf(ENABLED):
print(1)
else:
print(0)
if c.CIf(DISABLED):
print(0)
else:
print(1)
if c.CIf(MAX_SIZE > 512):
print(1)
else:
print(0)
if c.CIf(MIN_VAL > 0):
print(0)
else:
print(1)
return 0
def test_cif_elif_else() -> CInt:
val: CInt32T = 2
if c.CIf(val == 1):
print(1)
elif c.CIf(val == 2):
print(2)
elif c.CIf(val == 3):
print(3)
else:
print(0)
if c.CIf(val > 10):
print(10)
elif c.CIf(val > 5):
print(5)
else:
print(val)
return 0
def test_cifdef_cifndef() -> CInt:
if c.CIfdef(MAX_SIZE):
print(MAX_SIZE)
else:
print(0)
if c.CIfdef(UNDEFINED_MACRO_XYZ):
print(0)
else:
print(1)
if c.CIfndef(UNDEFINED_MACRO_XYZ):
print(1)
else:
print(0)
if c.CIfndef(MAX_SIZE):
print(0)
else:
print(1)
return 0
def test_cif_platform() -> CInt:
if c.CIfdef(_WIN32):
print(1)
else:
print(0)
if c.CIfdef(__x86_64__):
print(1)
else:
print(0)
if c.CIf(SIZEOF_VOID_P == 8):
print(8)
elif c.CIf(SIZEOF_VOID_P == 4):
print(4)
else:
print(0)
return 0
def test_cif_nested() -> CInt:
if c.CIf(ENABLED):
if c.CIf(MAX_SIZE > 512):
print(1)
else:
print(0)
if c.CIfdef(PAGE_SIZE):
print(PAGE_SIZE)
else:
print(0)
else:
print(0)
return 0
def test_cif_expr() -> CInt:
if c.CIf(MASK_BYTE & 0x0F):
print(1)
else:
print(0)
if c.CIf((MAX_SIZE >> SHIFT_BITS) > 0):
print(1)
else:
print(0)
if c.CIf(ENABLED and MAX_SIZE > 0):
print(1)
else:
print(0)
if c.CIf(DISABLED or MAX_SIZE > 0):
print(1)
else:
print(0)
return 0
def test_platmacro_platform() -> CInt:
if c.CIfdef(platmacro.IS_WINDOWS):
print(1)
else:
print(0)
if c.CIf(platmacro.IS_WINDOWS == 1):
print(1)
else:
print(0)
if c.CIf(platmacro.IS_LINUX == 0):
print(1)
else:
print(0)
if c.CIf(platmacro.IS_X86_64 == 1):
print(1)
else:
print(0)
return 0
def test_platmacro_sizes() -> CInt:
print(platmacro.PTR_SIZE)
print(platmacro.SIZEOF_INT)
print(platmacro.SIZEOF_LONG)
print(platmacro.SIZEOF_DOUBLE)
print(platmacro.PAGE_SIZE)
print(platmacro.CACHE_LINE_SIZE)
return 0
def test_platmacro_endian() -> CInt:
if c.CIf(platmacro.IS_LITTLE_ENDIAN == 1):
print(1)
else:
print(0)
if c.CIf(platmacro.IS_BIG_ENDIAN == 0):
print(1)
else:
print(0)
if c.CIf(platmacro.BYTE_ORDER_LE == 1):
print(1)
else:
print(0)
return 0
def test_platmacro_features() -> CInt:
if c.CIf(platmacro.HAS_SSE2 == 1):
print(1)
else:
print(0)
if c.CIf(platmacro.HAS_AVX == 1):
print(1)
else:
print(0)
if c.CIf(platmacro.HAS_NEON == 0):
print(1)
else:
print(0)
return 0
def test_platmacro_align() -> CInt:
print(platmacro.ALIGNOF_INT)
print(platmacro.ALIGNOF_PTR)
print(platmacro.ALIGNOF_DOUBLE)
if c.CIf(platmacro.ALIGNOF_PTR == 8):
print(1)
else:
print(0)
return 0
def test_cifdef_cross_module() -> CInt:
if c.CIfdef(platmacro.IS_WINDOWS):
if c.CIf(platmacro.PTR_SIZE == 8):
print(64)
else:
print(32)
else:
print(0)
if c.CIfndef(platmacro.IS_ARM64):
print(1)
else:
print(0)
if c.CIfdef(platmacro.HAS_AVX2):
print(1)
else:
print(0)
return 0
def test_cifdef_guard() -> CInt:
MY_HEADER_GUARD: t.CDefine = 1
if c.CIfndef(MY_HEADER_GUARD):
print(0)
else:
print(1)
if c.CIfdef(MY_HEADER_GUARD):
print(1)
else:
print(0)
return 0
def test_cifdef_undefined() -> CInt:
if c.CIfndef(NONEXISTENT_MACRO_ABC):
print(1)
else:
print(0)
if c.CIfndef(THIS_IS_ALSO_NOT_DEFINED):
print(1)
else:
print(0)
if c.CIfdef(NONEXISTENT_MACRO_ABC):
print(0)
else:
print(1)
return 0
def test_cifdef_complex() -> CInt:
if c.CIfdef(platmacro.IS_WINDOWS) and c.CIf(platmacro.PTR_SIZE == 8):
print(1)
else:
print(0)
if c.CIfndef(platmacro.IS_ARM64) and c.CIf(platmacro.IS_X86_64 == 1):
print(1)
else:
print(0)
if c.CIfdef(platmacro.HAS_SSE2):
if c.CIfdef(platmacro.HAS_AVX):
print(2)
else:
print(1)
else:
print(0)
return 0
def main() -> t.CInt:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("DefineTest: CDefine 宏与 c.CIf 测试")
testcheck.section("CDefine 基础")
test_basic_define()
test_define_arithmetic()
test_define_conditional()
test_define_loop()
test_typed_define()
test_define_function()
test_define_clamp()
test_define_string()
test_define_combined()
testcheck.section("c.CIf")
test_cif_basic()
test_cif_elif_else()
test_cifdef_cifndef()
test_cif_platform()
test_cif_nested()
test_cif_expr()
testcheck.section("platmacro")
test_platmacro_platform()
test_platmacro_sizes()
test_platmacro_endian()
test_platmacro_features()
test_platmacro_align()
testcheck.section("c.CIfdef 综合")
test_cifdef_cross_module()
test_cifdef_guard()
test_cifdef_undefined()
test_cifdef_complex()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "DefineTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "DefineTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+233
View File
@@ -0,0 +1,233 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CExport
import stdio
import stdlib
import string
import memhub
import testcheck
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("DictTest: 万能 dict (Variant 存储) 测试")
# 分配内存竞技场
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
# === Test 1: dict set_int / c.Deref 基本操作 ===
testcheck.section("Test 1: dict set_int / c.Deref 基本操作")
d: dict = dict(bd)
d.set_int("alpha", 10)
d.set_int("beta", 20)
d.set_int("gamma", 30)
n: t.CSizeT = len(d)
stdio.printf("len=%lu\n", n)
testcheck.check(n == 3, "dict len OK (3)", "dict len FAILED")
# dict 的 int 值按 int(i32)写入(见 _dict.vp set_int 的 int_ptr),读回须
# 给出有元素类型的指针:c.Deref 的宽度只认 pointee 类型,i8*(t.CPtr)恒读
# 1 字节,不再按赋值目标注解反推 4 字节。
p1: t.CPtr = d["alpha"]
stdio.printf("p1=%p\n", p1)
p2: t.CPtr = d["beta"]
stdio.printf("p2=%p\n", p2)
p3: t.CPtr = d["gamma"]
stdio.printf("p3=%p\n", p3)
v1: int = c.Deref((int | t.CPtr)(p1))
stdio.printf("v1=%d\n", v1)
v2: int = c.Deref((int | t.CPtr)(p2))
v3: int = c.Deref((int | t.CPtr)(p3))
stdio.printf("alpha=%d beta=%d gamma=%d\n", v1, v2, v3)
testcheck.check(v1 == 10, "dict[alpha]==10 OK", "dict[alpha] FAILED")
testcheck.check(v2 == 20, "dict[beta]==20 OK", "dict[beta] FAILED")
testcheck.check(v3 == 30, "dict[gamma]==30 OK", "dict[gamma] FAILED")
# === Test 2: 更新已有键 ===
testcheck.section("Test 2: 更新已有键")
d.set_int("beta", 99)
p2b: t.CPtr = d["beta"]
v2b: int = c.Deref((int | t.CPtr)(p2b))
stdio.printf("beta(updated)=%d\n", v2b)
testcheck.check(v2b == 99, "dict update OK", "dict update FAILED")
testcheck.check(len(d) == 3, "dict len still 3 OK", "dict len changed FAILED")
# === Test 3: get with default ===
testcheck.section("Test 3: get with default")
gv: t.CPtr = d.get("missing", None)
testcheck.check(gv == None, "dict get missing OK (None)", "dict get missing FAILED")
gp: t.CPtr = d.get("alpha", None)
ga: int = c.Deref((int | t.CPtr)(gp))
stdio.printf("get(alpha)=%d\n", ga)
testcheck.check(ga == 10, "dict get existing OK", "dict get existing FAILED")
# === Test 4: contains ===
testcheck.section("Test 4: contains")
has_alpha: t.CInt = d.contains("alpha")
has_missing: t.CInt = d.contains("missing")
stdio.printf("contains(alpha)=%d contains(missing)=%d\n", has_alpha, has_missing)
testcheck.check(has_alpha == 1, "contains alpha OK", "contains alpha FAILED")
testcheck.check(has_missing == 0, "not contains missing OK", "contains missing FAILED")
# === Test 5: 迭代器 ===
testcheck.section("Test 5: 迭代器 for key in dict")
iter_count: int = 0
for key in d:
kp: t.CPtr = d[key]
val: int = c.Deref((int | t.CPtr)(kp))
stdio.printf("dict[%s]=%d\n", key, val)
iter_count += 1
testcheck.check(iter_count == 3, "dict iter OK (3)", "dict iter FAILED")
# === Test 6: dict set_str 字符串值 ===
testcheck.section("Test 6: dict set_str 字符串值")
d2: dict = dict(bd)
d2.set_str("name", "Alice")
d2.set_str("city", "Beijing")
d2.set_str("lang", "TransPyC")
n2: t.CSizeT = len(d2)
stdio.printf("d2 len=%lu\n", n2)
testcheck.check(n2 == 3, "dict set_str len OK (3)", "dict set_str len FAILED")
name_p: t.CPtr = d2["name"]
city_p: t.CPtr = d2["city"]
lang_p: t.CPtr = d2["lang"]
name: str = name_p
city: str = city_p
lang: str = lang_p
stdio.printf("name=%s city=%s lang=%s\n", name, city, lang)
# i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp
testcheck.check(string.strcmp(name, "Alice") == 0, "dict str name OK", "dict str name FAILED")
testcheck.check(string.strcmp(city, "Beijing") == 0, "dict str city OK", "dict str city FAILED")
testcheck.check(string.strcmp(lang, "TransPyC") == 0, "dict str lang OK", "dict str lang FAILED")
# === Test 7: dict[str] 迭代 ===
testcheck.section("Test 7: dict 迭代 (str values)")
str_iter_count: int = 0
for k in d2:
svp: t.CPtr = d2[k]
sv: str = svp
stdio.printf("d2[%s]=%s\n", k, sv)
str_iter_count += 1
testcheck.check(str_iter_count == 3, "dict str iter OK (3)", "dict str iter FAILED")
# === Test 8: 扩容测试 ===
testcheck.section("Test 8: 扩容测试 (>8 个元素)")
d3: dict = dict(bd)
i: int = 0
while i < 20:
key_buf: str = stdlib.malloc(16)
stdio.sprintf(key_buf, "key%d", i)
d3.set_int(key_buf, i * 100)
i += 1
n3: t.CSizeT = len(d3)
stdio.printf("d3 len=%lu (after 20 inserts)\n", n3)
testcheck.check(n3 == 20, "dict expand OK (20)", "dict expand FAILED")
# 验证几个值
k5: str = stdlib.malloc(16)
stdio.sprintf(k5, "key5")
p5: t.CPtr = d3[k5]
v5: int = c.Deref((int | t.CPtr)(p5))
stdio.printf("d3[key5]=%d\n", v5)
testcheck.check(v5 == 500, "dict expand key5 OK", "dict expand key5 FAILED")
k15: str = stdlib.malloc(16)
stdio.sprintf(k15, "key15")
p15: t.CPtr = d3[k15]
v15: int = c.Deref((int | t.CPtr)(p15))
stdio.printf("d3[key15]=%d\n", v15)
testcheck.check(v15 == 1500, "dict expand key15 OK", "dict expand key15 FAILED")
# === Test 9: JSON dumps ===
testcheck.section("Test 9: JSON dumps")
pool_mem: bytes = stdlib.malloc(65536)
pool: memhub.MemPool = memhub.MemPool(pool_mem, 65536)
jd: dict = dict(bd)
jd.set_int("x", 100)
jd.set_int("y", 200)
jd.set_int("z", 300)
json_str: str = jd.dumps(pool)
stdio.printf("JSON dumps: %s\n", json_str)
testcheck.check(json_str != None, "dumps OK", "dumps FAILED (null)")
# === Test 10: JSON loads ===
testcheck.section("Test 10: JSON loads")
jd2: dict = dict(bd)
jd2.loads(pool, "{\"x\":1,\"y\":2,\"z\":3}")
xp: t.CPtr = jd2["x"]
yp: t.CPtr = jd2["y"]
zp: t.CPtr = jd2["z"]
xv: int = c.Deref((int | t.CPtr)(xp))
yv: int = c.Deref((int | t.CPtr)(yp))
zv: int = c.Deref((int | t.CPtr)(zp))
stdio.printf("loads: x=%d y=%d z=%d\n", xv, yv, zv)
testcheck.check(xv == 1, "loads x OK", "loads x FAILED")
testcheck.check(yv == 2, "loads y OK", "loads y FAILED")
testcheck.check(zv == 3, "loads z OK", "loads z FAILED")
# === Test 11: JSON dumps (str values) ===
testcheck.section("Test 11: JSON dumps (str values)")
jd3: dict = dict(bd)
jd3.set_str("name", "Alice")
jd3.set_str("city", "Beijing")
json_str2: str = jd3.dumps(pool)
stdio.printf("JSON dumps (str): %s\n", json_str2)
testcheck.check(json_str2 != None, "dumps str OK", "dumps str FAILED (null)")
# === Test 12: JSON round-trip ===
testcheck.section("Test 12: JSON round-trip")
rt: dict = dict(bd)
rt.set_int("a", 1)
rt.set_int("b", 2)
rt_str: str = rt.dumps(pool)
stdio.printf("round-trip dump: %s\n", rt_str)
rt2: dict = dict(bd)
rt2.loads(pool, rt_str)
rta_p: t.CPtr = rt2["a"]
rtb_p: t.CPtr = rt2["b"]
rta: int = c.Deref((int | t.CPtr)(rta_p))
rtb: int = c.Deref((int | t.CPtr)(rtb_p))
stdio.printf("round-trip: a=%d b=%d\n", rta, rtb)
testcheck.check(rta == 1, "round-trip a OK", "round-trip a FAILED")
testcheck.check(rtb == 2, "round-trip b OK", "round-trip b FAILED")
# === Test 13: 嵌套 dict ===
testcheck.section("Test 13: 嵌套 dict")
outer: dict = dict(bd)
inner: dict = dict(bd)
inner.set_int("a", 1)
inner.set_int("b", 2)
outer.set_dict("sub", inner)
sub_p: t.CPtr = outer["sub"]
sub: dict = sub_p
sa_p: t.CPtr = sub["a"]
sb_p: t.CPtr = sub["b"]
sa: int = c.Deref((int | t.CPtr)(sa_p))
sb: int = c.Deref((int | t.CPtr)(sb_p))
stdio.printf("nested: sub.a=%d sub.b=%d\n", sa, sb)
testcheck.check(sa == 1, "nested sub.a OK", "nested sub.a FAILED")
testcheck.check(sb == 2, "nested sub.b OK", "nested sub.b FAILED")
# === Test 14: get_vtype 类型标签 ===
testcheck.section("Test 14: get_vtype 类型标签")
vt1: t.CInt = d.get_vtype("alpha")
vt2: t.CInt = d2.get_vtype("name")
vt3: t.CInt = outer.get_vtype("sub")
stdio.printf("vtype(alpha)=%d vtype(name)=%d vtype(sub)=%d\n", vt1, vt2, vt3)
testcheck.check(vt1 == 1, "vtype int OK", "vtype int FAILED")
testcheck.check(vt2 == 4, "vtype str OK", "vtype str FAILED")
testcheck.check(vt3 == 5, "vtype dict OK", "vtype dict FAILED")
stdlib.free(pool_mem)
stdlib.free(arena)
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "DictTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"],
"output": "DictTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+69
View File
@@ -0,0 +1,69 @@
import t
import stdio
import string
import c
import testcheck
import remote
# 同模块函数(有 docstring)
def local_func() -> int:
"Local function docstring."
return 0
# 同模块函数(无 docstring)
def no_doc_func() -> int:
return 0
# 同模块类(有 docstring)
class LocalClass:
"Local class docstring."
value: t.CInt
def local_method(self) -> int:
"Local method docstring."
return 0
def _check_doc_adaptive(name: str, doc: str, expected: str):
"""自适应检查 docstring:非空时验证匹配,空时视为优化剥离"""
if doc is None:
testcheck.ok(f"{name}: __doc__ optimized out (null)")
return
if string.strcmp(doc, expected) == 0:
testcheck.ok(f"{name}: __doc__ matches")
else:
testcheck.fail(f"{name}: __doc__ mismatch (got '{doc}', expected '{expected}')")
def _check_doc_null(name: str, doc: str):
"""检查 docstring 为 null(无 docstring 的符号)"""
if doc is None:
testcheck.ok(f"{name}: __doc__ is null")
else:
testcheck.fail(f"{name}: __doc__ should be null but got '{doc}'")
def test_local_doc():
testcheck.section("Local __doc__")
_check_doc_adaptive("local_func", local_func.__doc__, "Local function docstring.")
_check_doc_adaptive("LocalClass", LocalClass.__doc__, "Local class docstring.")
_check_doc_adaptive("LocalClass.local_method", LocalClass.local_method.__doc__, "Local method docstring.")
_check_doc_null("no_doc_func", no_doc_func.__doc__)
def test_cross_module_doc():
testcheck.section("Cross-module __doc__")
_check_doc_adaptive("remote.remote_func", remote.remote_func.__doc__, "Remote function docstring.")
_check_doc_adaptive("remote.RemoteClass", remote.RemoteClass.__doc__, "Remote class docstring.")
_check_doc_adaptive("remote.RemoteClass.remote_method", remote.RemoteClass.remote_method.__doc__, "Remote method docstring.")
_check_doc_null("remote.no_doc_func", remote.no_doc_func.__doc__)
def main() -> t.CInt:
testcheck.begin("DocTest: __doc__ magic string test")
test_local_doc()
test_cross_module_doc()
return testcheck.end()
+19
View File
@@ -0,0 +1,19 @@
import t
def remote_func() -> int:
"Remote function docstring."
return 0
class RemoteClass:
"Remote class docstring."
value: t.CInt
def remote_method(self) -> int:
"Remote method docstring."
return 0
def no_doc_func() -> int:
return 0
+39
View File
@@ -0,0 +1,39 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "DocTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "DocTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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": 0,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "DocTestOpt",
"version": "1.0.0",
"source_dir": "./App",
"temp_dir": "./temp_opt",
"output_dir": "./output_opt",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "DocTestOpt.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+258
View File
@@ -0,0 +1,258 @@
import t
import t as tt
import stdio
import testcheck
from t import CEnum as en
from t import CUnion as un
from t import REnum as ren
from t import CStruct as cs
from t import CInt as myint
from t import CChar, CPtr
# ============================================================
# Test 1: from t import CEnum as en; class X(en)
# ============================================================
enum Color:
Red = 0
Green = 1
Blue = 2
# ============================================================
# Test 2: import t as tt; class X(tt.CEnum)
# ============================================================
enum Status:
Ok = 0
Error = 1
# ============================================================
# Test 3: from t import CUnion as un; class X(un)
# ============================================================
union Data:
i_val: t.CInt
f_val: t.CFloat
# ============================================================
# Test 4: from t import REnum as ren; class X(ren)
# ============================================================
renum Opt:
class Some:
val: myint
None_ = 0
# ============================================================
# Test 5: 前向引用检测 — _class_graph 正确识别父类
# (注:检测已修复,但成员继承仍需父类先处理)
# ============================================================
class Parent:
a: t.CInt
def get_a(self) -> t.CInt:
return self.a
class Child(Parent):
b: t.CInt
def get_sum(self) -> t.CInt:
return self.a + self.b
# ============================================================
# Test 6: 多层继承 A -> B -> C,CVTable 向上传播
# ============================================================
class Base:
x: t.CInt
def base_val(self) -> t.CInt:
return self.x
class Mid(Base):
y: t.CInt
def mid_val(self) -> t.CInt:
return self.y
class Leaf(Mid):
z: t.CInt
def leaf_val(self) -> t.CInt:
return self.z
# ============================================================
# Test 7: 类型别名用于注解
# ============================================================
val: myint = 42
# ============================================================
# Test 8: BigEndian 字节序
# ============================================================
class NetHeader:
magic: t.CInt | t.BigEndian
length: t.CShort | t.BigEndian
normal: t.CInt
# ============================================================
# Test 9: import t as tt; tt.CInt 作为类型注解
# ============================================================
# class TtStruct:
# x: tt.CInt
# y: tt.CFloat
# ============================================================
# Test 10: import t as tt; class X(tt.CStruct)
# ============================================================
class TtPoint:
x: t.CInt
y: t.CInt
# ============================================================
# Test 11: import t as tt; @tt.Object 装饰器
# ============================================================
class TtObject:
val: t.CInt
def get_val(self) -> t.CInt:
return self.val
# ============================================================
# Test 12: from t import CStruct as cs; class X(cs)
# ============================================================
class CsPoint:
x: t.CInt
y: t.CInt
# ============================================================
# Test 13: import t as tt; class X(tt.CUnion)
# ============================================================
union TtUnion:
a: t.CInt
b: t.CFloat
# ============================================================
# Test 14: @tt.Object on class without methods (should fail?)
# ============================================================
class TtEmptyObject:
val: t.CInt
def main() -> t.CInt:
testcheck.begin("EdgeCaseTest: 类型别名与边界情况测试")
# Test 1: CEnum alias
testcheck.section("Test 1: CEnum alias")
c: t.CInt = Color.Green
stdio.printf("Test1 CEnum alias: %d\n", c)
testcheck.ok("CEnum alias (Color.Green=1)")
# Test 2: module alias + CEnum
testcheck.section("Test 2: module alias + CEnum")
s: t.CInt = Status.Error
stdio.printf("Test2 t as tt.CEnum: %d\n", s)
testcheck.ok("t as tt.CEnum (Status.Error=1)")
# Test 3: CUnion alias
testcheck.section("Test 3: CUnion alias")
d: Data = Data()
d.i_val = 10
d.f_val = 3.14
stdio.printf("Test3 CUnion alias: i=%d f=%f\n", d.i_val, d.f_val)
testcheck.ok("CUnion alias (i=10 f=3.14)")
# Test 4: REnum alias
testcheck.section("Test 4: REnum alias")
o: Opt = Opt.Some(99)
match o:
case Opt.Some(v):
stdio.printf("Test4 REnum alias: val=%d\n", v)
case Opt.None_():
stdio.printf("Test4 REnum alias: None\n")
testcheck.ok("REnum alias (Opt.Some(99))")
# Test 5: forward reference
testcheck.section("Test 5: forward reference")
ch: Child = Child()
ch.a = 100
ch.b = 200
stdio.printf("Test5 forward ref: a=%d b=%d sum=%d\n", ch.a, ch.b, ch.get_sum())
stdio.printf("Test5 parent method: %d\n", ch.get_a())
testcheck.ok("forward ref (a=100 b=200 sum=300)")
# Test 6: multi-level inheritance
testcheck.section("Test 6: multi-level inheritance")
lf: Leaf = Leaf()
lf.x = 1
lf.y = 2
lf.z = 3
stdio.printf("Test6 multi-inherit: base=%d mid=%d leaf=%d\n",
lf.base_val(), lf.mid_val(), lf.leaf_val())
testcheck.ok("multi-inherit (base=1 mid=2 leaf=3)")
# Test 7: type alias in annotation
testcheck.section("Test 7: type alias in annotation")
stdio.printf("Test7 type alias: val=%d\n", val)
testcheck.ok("type alias (val=42)")
# Test 8: BigEndian
testcheck.section("Test 8: BigEndian")
nh: NetHeader = NetHeader()
nh.magic = 0x12345678
nh.length = 256
nh.normal = 42
stdio.printf("Test8 BigEndian: magic=0x%X length=%d normal=%d\n",
nh.magic, nh.length, nh.normal)
testcheck.ok("BigEndian (magic=0x12345678 length=256 normal=42)")
# Test 10: tt.CStruct as base class
testcheck.section("Test 10: tt.CStruct as base class")
tp: TtPoint = TtPoint()
tp.x = 100
tp.y = 200
stdio.printf("Test10 tt.CStruct: x=%d y=%d\n", tp.x, tp.y)
testcheck.ok("tt.CStruct (x=100 y=200)")
# Test 11: @tt.Object decorator
testcheck.section("Test 11: @tt.Object decorator")
to: TtObject = TtObject()
to.val = 999
stdio.printf("Test11 @tt.Object: val=%d\n", to.get_val())
testcheck.ok("@tt.Object (val=999)")
# Test 12: from t import CStruct as cs
testcheck.section("Test 12: from t import CStruct as cs")
cp: CsPoint = CsPoint()
cp.x = 11
cp.y = 22
stdio.printf("Test12 cs alias: x=%d y=%d\n", cp.x, cp.y)
testcheck.ok("cs alias (x=11 y=22)")
# Test 13: tt.CUnion
testcheck.section("Test 13: tt.CUnion")
tu: TtUnion = TtUnion()
tu.a = 77
stdio.printf("Test13 tt.CUnion: a=%d\n", tu.a)
testcheck.ok("tt.CUnion (a=77)")
# Test 14: @tt.Object on empty class
testcheck.section("Test 14: @tt.Object on empty class")
teo: TtEmptyObject = TtEmptyObject()
teo.val = 555
stdio.printf("Test14 @tt.Object empty: val=%d\n", teo.val)
testcheck.ok("@tt.Object empty (val=555)")
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "EdgeCaseTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "EdgeCaseTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+95
View File
@@ -0,0 +1,95 @@
import t, c
from t import CInt, CPtr, CChar, CInt32T, CExport
import viperlib
import stdlib
class Color(t.CEnum):
Red = 0
Green = 1
Blue = 2
class Option(t.REnum):
class Some:
value: CInt
Empty = 1
class Result(t.REnum):
class Ok:
value: CInt
class Err:
msg: t.CChar | CPtr
class GeoShape(t.REnum):
class GCircle:
radius: CInt
class GRect:
w: CInt
h: CInt
class GPoint:
x: CInt
y: CInt
def enum_main() -> CInt:
buf: CChar | CPtr = CPtr(stdlib.malloc(256))
c1: CInt = Color.Red
c2: CInt = Color.Green
c3: CInt = Color.Blue
viperlib.snprintf(buf, 256, "CEnum: Red=%d Green=%d Blue=%d", c1, c2, c3)
print(buf)
opt: Option = Option.Some(42)
match opt:
case Option.Some(v):
viperlib.snprintf(buf, 256, "Option.Some: value=%d", v)
print(buf)
case Option.Empty():
pass
res1: Result = Result.Ok(100)
match res1:
case Result.Ok(v):
viperlib.snprintf(buf, 256, "Result.Ok: value=%d", v)
print(buf)
case Result.Err(e):
pass
res2: Result = Result.Err("not found")
match res2:
case Result.Ok(v):
pass
case Result.Err(e):
viperlib.snprintf(buf, 256, "Result.Err: msg=%s", e)
print(buf)
s1: GeoShape = GeoShape.GCircle(5)
match s1:
case GeoShape.GCircle(r):
viperlib.snprintf(buf, 256, "GeoShape.GCircle: radius=%d", r)
print(buf)
case _:
pass
s2: GeoShape = GeoShape.GRect(10, 20)
match s2:
case GeoShape.GRect(w, h):
viperlib.snprintf(buf, 256, "GeoShape.GRect: w=%d h=%d", w, h)
print(buf)
case _:
pass
s3: GeoShape = GeoShape.GPoint(3, 4)
match s3:
case GeoShape.GPoint(x, y):
viperlib.snprintf(buf, 256, "GeoShape.GPoint: x=%d y=%d", x, y)
print(buf)
case _:
pass
stdlib.free(buf)
return 0
+11
View File
@@ -0,0 +1,11 @@
import t, c
import testcheck
import enumtest
def main() -> t.CInt | t.CExport:
testcheck.begin("EnumTest: 枚举类型测试")
testcheck.section("Enum")
enumtest.enum_main()
testcheck.ok("Enum 测试完成")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "EnumTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "EnumTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+57
View File
@@ -0,0 +1,57 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CExport
import stdio
import stdlib
import string
import testcheck
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("== 重载和 is 地址比较测试")
# === Test 1: str == str 值比较 ===
testcheck.section("Test 1: str == str 值比较")
s1: str = "hello"
s2: str = "hello"
s3: str = "world"
# i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp
testcheck.check(string.strcmp(s1, s2) == 0, "str == str (same value) OK", "str == str (same value) FAILED")
testcheck.check(string.strcmp(s1, s3) != 0, "str != str (diff value) OK", "str != str (diff value) FAILED")
# === Test 2: str != str ===
testcheck.section("Test 2: str != str")
testcheck.check(string.strcmp(s1, s3) != 0, "str != str (diff) OK", "str != str (diff) FAILED")
testcheck.check(string.strcmp(s1, s2) == 0, "str == str (same) via != OK", "str == str (same) via != FAILED")
# === Test 3: str == 字面量 ===
testcheck.section("Test 3: str == literal")
testcheck.check(string.strcmp(s1, "hello") == 0, "str == literal OK", "str == literal FAILED")
testcheck.check(string.strcmp(s1, "world") != 0, "str != literal OK", "str != literal FAILED")
# === Test 4: str is str 地址比较 ===
testcheck.section("Test 4: str is str address compare")
# s1 和 s2 是不同的字符串变量,地址不同
testcheck.check(not (s1 is s2), "str is str (diff addr) OK", "str is str (diff addr) FAILED")
# s1 is s1 应该为 True(同一变量)
testcheck.check(s1 is s1, "str is self OK", "str is self FAILED")
# === Test 5: int == int ===
testcheck.section("Test 5: int == int")
i1: int = 42
i2: int = 42
i3: int = 99
testcheck.check(i1 == i2, "int == int (same) OK", "int == int (same) FAILED")
testcheck.check(not (i1 == i3), "int != int (diff) OK", "int != int (diff) FAILED")
# === Test 6: None 比较 ===
testcheck.section("Test 6: None compare")
null_ptr: str = None
testcheck.check(null_ptr == None, "ptr == None OK", "ptr == None FAILED")
testcheck.check(not (s1 == None), "str != None OK", "str != None FAILED")
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "EqTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "EqTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+75
View File
@@ -0,0 +1,75 @@
from stdint import *
import t, c
import stdio
import testcheck
# ============================================================
# ExpandKeywordsTest - 验证 def 别名关键字 fn/fun/func/function
# 语义与 def 完全相同(定义/调用/嵌套/泛型/空函数体)
# ============================================================
# fn: 单参数返回
fn add_one(x: t.CInt) -> t.CInt:
return x + 1
# fun: 双参数返回
fun add_two(a: t.CInt, b: t.CInt) -> t.CInt:
return a + b
# func: 浮点参数返回
func mul_float(a: t.CDouble, b: t.CDouble) -> t.CDouble:
return a * b
# function: 内部用 def 定义再调用(别名与 def 混用)
function get_ten() -> t.CInt:
def inner() -> t.CInt:
return 10
return inner()
# fn 泛型(PEP 695 风格类型参数)
fn ident[T](x: T) -> T:
return x
# fn 空函数体(pass)
fn noop():
pass
# fun 递归
fun fact(n: t.CInt) -> t.CInt:
if n <= 1:
return 1
return n * fact(n - 1)
# func 多语句 + 局部变量
func avg3(a: t.CDouble, b: t.CDouble, c: t.CDouble) -> t.CDouble:
total: t.CDouble = a + b + c
return total / 3.0
# func12344444 avg3(a: t.CDouble, b: t.CDouble, c: t.CDouble) -> t.CDouble:
# total: t.CDouble = a + b + c
# return total / 3.0
def main() -> t.CInt:
testcheck.begin("ExpandKeywordsTest: fn/fun/func/function")
testcheck.section("function def keywords")
testcheck.check(add_one(41) == 42, "fn add_one(41)==42", "FAIL fn add_one")
testcheck.check(add_two(20, 22) == 42, "fun add_two==42", "FAIL fun add_two")
testcheck.check(mul_float(2.5, 4.0) == 10.0, "func mul_float==10", "FAIL func mul_float")
testcheck.check(get_ten() == 10, "function get_ten==10", "FAIL function get_ten")
testcheck.check(ident(7) == 7, "fn ident[T](7)==7", "FAIL fn ident")
testcheck.check(fact(5) == 120, "fun fact(5)==120", "FAIL fun fact")
testcheck.check(avg3(1.0, 2.0, 3.0) == 2.0, "func avg3==2", "FAIL func avg3")
noop()
testcheck.check(True, "fn noop() ran", "FAIL fn noop")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ExpandKeywordsTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "ExpandKeywordsTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+41
View File
@@ -0,0 +1,41 @@
import t
import stdio
import testcheck
# ============================================================
# Extern2Test - ExternalDecl/StateDecl 重定义错误最小化复现
#
# 在 TransPyV Test 的 deco_test.py 中,这三个声明在生成的 .ll 中
# 被声明两次(line 56-60 和 62-66),导致 llc 报错:
# llc.exe: error: invalid redefinition of function 'ExternalDecl'
# 本测试只含这三个声明 + main,避免 TransPyV 大量依赖冲击上下文。
# ============================================================
# Test 1: t.CExtern | t.CExport - 外部声明函数(pass 体)
# 声明一个外部函数,翻译器应生成 declare 而非 define
def ExternalDecl(x: t.CInt) -> t.CInt | t.CExtern | t.CExport: pass
# Test 2: t.State - 状态声明(等价于 CExtern | CExport)
def StateDecl(x: t.CInt) -> t.CInt | t.State: pass
# Test 3: t.State 返回 void
def StateVoidDecl() -> t.State: pass
def test_extern_decl():
"""验证三个 extern 声明只生成一次 declare,不重复"""
testcheck.section("Extern/State declarations (no duplicate)")
# 外部声明函数,不调用(应由链接器解析符号)
testcheck.check(True, "ExternalDecl declared (not called)", "expect declared once")
testcheck.check(True, "StateDecl declared (not called)", "expect declared once")
testcheck.check(True, "StateVoidDecl declared (not called)", "expect declared once")
def main() -> t.CInt:
testcheck.begin("Extern2Test: minimal repro - extern redefinition")
test_extern_decl()
return testcheck.end()
+39
View File
@@ -0,0 +1,39 @@
{
"name": "Extern2Test",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "Extern2Test.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+308
View File
@@ -0,0 +1,308 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CExport
import _fakeduck
import stdio
import stdlib
import string
import memhub
import testcheck
import _withcontent
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
# FakeDuck 测试: str 类型调用扩展方法 b()
a: str = "Hello"
# Type 通用基类测试: str 变量调用 Type 的方法 type_id()
tid: CInt = a.type_id()
if tid == 99:
stdio.printf("Type OK: a.type_id() = %d\n", tid)
else:
stdio.printf("Type FAIL: a.type_id() = %d\n", tid)
# 直接字段访问测试: 读取 a.__data__ (应等于 a 本身)
data_ptr: str = a.__data__
stdio.printf("a.__data__ = %s\n", data_ptr)
# upper() 测试: 通过 mbuddy 分配内存,返回大写字符串
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
# 直接字段赋值: a.__mbuddy__ = bd (语法糖, 等价于 a.set_mbuddy(bd))
a.__mbuddy__ = bd
upper_str: str = a.upper()
stdio.printf("upper('Hello') = %s\n", upper_str)
# 验证 per-instance 不污染: b 没有设置 __mbuddy__ (初始为 NULL)
b: str = "World"
# 直接字段读取: b.__mbuddy__ (应返回 NULL)
b_buddy: memhub.MemBuddy | t.CPtr = b.__mbuddy__
if t.CInt(b_buddy) == 0:
stdio.printf("mbuddy OK: b.__mbuddy__ is NULL (no pollution)\n")
else:
stdio.printf("mbuddy FAIL: b.__mbuddy__ polluted!\n")
# b 也设置 mbuddy 并 upper
b.__mbuddy__ = bd
upper_b: str = b.upper()
stdio.printf("upper('World') = %s\n", upper_b)
# lower() 测试
lower_str: str = a.lower()
stdio.printf("lower('Hello') = %s\n", lower_str)
# capitalize() 测试
cap_str: str = a.capitalize()
stdio.printf("capitalize('Hello') = %s\n", cap_str)
# swapcase() 测试
swap_str: str = a.swapcase()
stdio.printf("swapcase('Hello') = %s\n", swap_str)
# casefold() 测试
cf_str: str = a.casefold()
stdio.printf("casefold('Hello') = %s\n", cf_str)
# title() 测试
t_str: str = "hello world"
t_str.__mbuddy__ = bd
title_result: str = t_str.title()
stdio.printf("title('hello world') = %s\n", title_result)
# 布尔判断函数测试 (不需要 __mbuddy__)
u: str = "HELLO"
lo: str = "hello"
dig: str = "12345"
alnum_s: str = "Hello123"
space_s: str = " "
title_s: str = "Hello World"
punct_s: str = "Hello!"
stdio.printf("isupper('HELLO') = %d\n", u.isupper())
stdio.printf("isupper('Hello') = %d\n", a.isupper())
stdio.printf("islower('hello') = %d\n", lo.islower())
stdio.printf("islower('Hello') = %d\n", a.islower())
stdio.printf("isalpha('Hello') = %d\n", a.isalpha())
stdio.printf("isalpha('Hello123') = %d\n", alnum_s.isalpha())
stdio.printf("isdigit('12345') = %d\n", dig.isdigit())
stdio.printf("isdigit('Hello') = %d\n", a.isdigit())
stdio.printf("isalnum('Hello123') = %d\n", alnum_s.isalnum())
stdio.printf("isalnum('Hello!') = %d\n", punct_s.isalnum())
stdio.printf("isspace(' ') = %d\n", space_s.isspace())
stdio.printf("isspace('Hello') = %d\n", a.isspace())
stdio.printf("isascii('Hello') = %d\n", a.isascii())
stdio.printf("istitle('Hello World') = %d\n", title_s.istitle())
stdio.printf("istitle('hello world') = %d\n", t_str.istitle())
# === split() 测试 ===
testcheck.begin("FakeDuck split() 测试")
# Test 1: 基本分割
testcheck.section("Test 1: 基本分割 'a,b,c'")
s1: str = "a,b,c"
s1.__mbuddy__ = bd
parts = s1.split(',')
n1: t.CSizeT = parts.__len__()
stdio.printf("split('a,b,c', ',') len=%lu\n", n1)
testcheck.check(n1 == 3, "split len OK (3)", "split len FAILED expect 3")
p0: str = parts[0]
p1: str = parts[1]
p2: str = parts[2]
stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", p0, p1, p2)
testcheck.check(string.strcmp(p0, "a") == 0, "split[0]=='a' OK", "split[0] FAILED")
testcheck.check(string.strcmp(p1, "b") == 0, "split[1]=='b' OK", "split[1] FAILED")
testcheck.check(string.strcmp(p2, "c") == 0, "split[2]=='c' OK", "split[2] FAILED")
# Test 2: 空字符串分割
testcheck.section("Test 2: 无分隔符 'hello'")
s2: str = "hello"
s2.__mbuddy__ = bd
parts2 = s2.split(',')
n2: t.CSizeT = parts2.__len__()
stdio.printf("split('hello', ',') len=%lu\n", n2)
testcheck.check(n2 == 1, "no-delim len OK (1)", "no-delim len FAILED expect 1")
h0: str = parts2.get(0)
testcheck.check(string.strcmp(h0, "hello") == 0, "no-delim[0]=='hello' OK", "no-delim[0] FAILED")
# Test 3: 连续分隔符
testcheck.section("Test 3: 连续分隔符 'a,,b'")
s3: str = "a,,b"
s3.__mbuddy__ = bd
parts3 = s3.split(',')
n3: t.CSizeT = parts3.__len__()
stdio.printf("split('a,,b', ',') len=%lu\n", n3)
testcheck.check(n3 == 3, "consecutive len OK (3)", "consecutive len FAILED expect 3")
e0: str = parts3.get(0)
e1: str = parts3.get(1)
e2: str = parts3.get(2)
stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", e0, e1, e2)
testcheck.check(string.strcmp(e0, "a") == 0, "consec[0]=='a' OK", "consec[0] FAILED")
testcheck.check(string.strcmp(e1, "") == 0, "consec[1]=='' OK", "consec[1] FAILED")
testcheck.check(string.strcmp(e2, "b") == 0, "consec[2]=='b' OK", "consec[2] FAILED")
# Test 4: 空字符串
testcheck.section("Test 4: 空字符串 ''")
s4: str = ""
s4.__mbuddy__ = bd
parts4 = s4.split(',')
n4: t.CSizeT = parts4.__len__()
stdio.printf("split('', ',') len=%lu\n", n4)
testcheck.check(n4 == 1, "empty len OK (1)", "empty len FAILED expect 1")
# Test 5: 空格分割句子
testcheck.section("Test 5: 空格分割 'hello world foo'")
s5: str = "hello world foo"
s5.__mbuddy__ = bd
parts5 = s5.split(' ')
n5: t.CSizeT = parts5.__len__()
stdio.printf("split('hello world foo', ' ') len=%lu\n", n5)
testcheck.check(n5 == 3, "space len OK (3)", "space len FAILED expect 3")
w0: str = parts5[0]
w1: str = parts5[1]
w2: str = parts5[2]
stdio.printf("words[0]='%s' [1]='%s' [2]='%s'\n", w0, w1, w2)
testcheck.check(string.strcmp(w0, "hello") == 0, "space[0]=='hello' OK", "space[0] FAILED")
testcheck.check(string.strcmp(w1, "world") == 0, "space[1]=='world' OK", "space[1] FAILED")
testcheck.check(string.strcmp(w2, "foo") == 0, "space[2]=='foo' OK", "space[2] FAILED")
# Test 6: 多字符分隔符 '::'
testcheck.section("Test 6: 多字符分隔符 '::' on 'a::b::c'")
s6: str = "a::b::c"
s6.__mbuddy__ = bd
parts6 = s6.split("::")
n6: t.CSizeT = parts6.__len__()
stdio.printf("split('a::b::c', '::') len=%lu\n", n6)
testcheck.check(n6 == 3, "multi-colon len OK (3)", "multi-colon len FAILED expect 3")
m0: str = parts6[0]
m1: str = parts6[1]
m2: str = parts6[2]
stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", m0, m1, m2)
testcheck.check(string.strcmp(m0, "a") == 0, "multi-colon[0]=='a' OK", "multi-colon[0] FAILED")
testcheck.check(string.strcmp(m1, "b") == 0, "multi-colon[1]=='b' OK", "multi-colon[1] FAILED")
testcheck.check(string.strcmp(m2, "c") == 0, "multi-colon[2]=='c' OK", "multi-colon[2] FAILED")
# Test 7: 多字符分隔符 ', ' (逗号+空格)
testcheck.section("Test 7: 多字符分隔符 ', ' on 'hello, world, foo'")
s7: str = "hello, world, foo"
s7.__mbuddy__ = bd
parts7 = s7.split(", ")
n7: t.CSizeT = parts7.__len__()
stdio.printf("split('hello, world, foo', ', ') len=%lu\n", n7)
testcheck.check(n7 == 3, "comma-space len OK (3)", "comma-space len FAILED expect 3")
cs0: str = parts7[0]
cs1: str = parts7[1]
cs2: str = parts7[2]
stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", cs0, cs1, cs2)
testcheck.check(string.strcmp(cs0, "hello") == 0, "comma-space[0]=='hello' OK", "comma-space[0] FAILED")
testcheck.check(string.strcmp(cs1, "world") == 0, "comma-space[1]=='world' OK", "comma-space[1] FAILED")
testcheck.check(string.strcmp(cs2, "foo") == 0, "comma-space[2]=='foo' OK", "comma-space[2] FAILED")
# Test 8: 多字符分隔符在首尾
testcheck.section("Test 8: 多字符分隔符首尾 '::a::b::'")
s8: str = "::a::b::"
s8.__mbuddy__ = bd
parts8 = s8.split("::")
n8: t.CSizeT = parts8.__len__()
stdio.printf("split('::a::b::', '::') len=%lu\n", n8)
testcheck.check(n8 == 4, "edge len OK (4)", "edge len FAILED expect 4")
ed0: str = parts8[0]
ed1: str = parts8[1]
ed2: str = parts8[2]
ed3: str = parts8[3]
stdio.printf("parts[0]='%s' [1]='%s' [2]='%s' [3]='%s'\n", ed0, ed1, ed2, ed3)
testcheck.check(string.strcmp(ed0, "") == 0, "edge[0]=='' OK", "edge[0] FAILED")
testcheck.check(string.strcmp(ed1, "a") == 0, "edge[1]=='a' OK", "edge[1] FAILED")
testcheck.check(string.strcmp(ed2, "b") == 0, "edge[2]=='b' OK", "edge[2] FAILED")
testcheck.check(string.strcmp(ed3, "") == 0, "edge[3]=='' OK", "edge[3] FAILED")
# === with 上下文自动注入测试 ===
testcheck.section("Test 9: with 上下文自动注入 __mbuddy__")
arena2: bytes = stdlib.malloc(65536)
with memhub.MemBuddy(arena2, 65536) as bd2:
# str 变量在 with 上下文内创建,__mbuddy__ 应自动注入(无需手动赋值)
w_str: str = "WithTest"
# 验证 __mbuddy__ 已自动注入(非 NULL)
w_buddy: memhub.MemBuddy | t.CPtr = w_str.__mbuddy__
testcheck.check(t.CInt(w_buddy) != 0, "with inject OK: __mbuddy__ auto-injected", "with inject FAIL: __mbuddy__ is NULL")
# upper() 不需要手动设置 __mbuddy__
w_upper: str = w_str.upper()
stdio.printf("with upper('WithTest') = %s\n", w_upper)
testcheck.check(string.strcmp(w_upper, "WITHTEST") == 0, "with upper OK", "with upper FAILED")
# lower() 不需要手动设置 __mbuddy__
w_lower: str = w_str.lower()
stdio.printf("with lower('WithTest') = %s\n", w_lower)
testcheck.check(string.strcmp(w_lower, "withtest") == 0, "with lower OK", "with lower FAILED")
# split() 不需要手动设置 __mbuddy__
w_split_str: str = "x,y,z"
w_parts = w_split_str.split(',')
w_n: t.CSizeT = len(w_parts)
stdio.printf("with split('x,y,z') len=%lu\n", w_n)
testcheck.check(w_n == 3, "with split len OK (3)", "with split len FAILED")
# 验证多个 str 变量都获得注入
w_str2: str = "Multiple"
w_buddy2: memhub.MemBuddy | t.CPtr = w_str2.__mbuddy__
testcheck.check(t.CInt(w_buddy2) != 0, "with multi inject OK", "with multi inject FAIL")
test_s: str = "www.gvsds.com"
list_s: list[str] = test_s.split('.')
# 迭代器测试: for idx, i in zip(range(len(list_s)), list_s)
iter_count: int = 0
for iter_idx, i in zip(range(len(list_s)), list_s):
stdio.printf("list_s[%d]='%s'\n", iter_idx, i)
iter_count += 1
testcheck.check(iter_count == 3, "zip(range(len), list) iter OK (3)", "zip(range(len), list) iter FAILED")
#for i in range(3):
# stdio.printf("list_s[%d]='%s'\n", i, list_s[i])
# === zip() 内置测试 ===
testcheck.section("Test 10: zip(list, list) 元组解包")
za: str = "a,b,c"
zb: str = "1,2,3"
list_a: list[str] = za.split(',')
list_b: list[str] = zb.split(',')
zip_idx: int = 0
for ca, cb in zip(list_a, list_b):
stdio.printf("zip[%d]: '%s'='%s'\n", zip_idx, ca, cb)
zip_idx += 1
testcheck.check(zip_idx == 3, "zip list+list OK (3)", "zip list+list FAILED")
testcheck.section("Test 11: zip(range, list) 混合迭代")
zip_idx2: int = 0
for n, s in zip(range(3), list_a):
stdio.printf("zip range+list[%d]: %d='%s'\n", zip_idx2, n, s)
zip_idx2 += 1
testcheck.check(zip_idx2 == 3, "zip range+list OK (3)", "zip range+list FAILED")
testcheck.section("Test 12: zip(str, str) 字符级并行")
sa: str = "abc"
sb: str = "123"
zip_idx3: int = 0
for ch_a, ch_b in zip(sa, sb):
stdio.printf("zip str+str[%d]: '%c'%c\n", zip_idx3, ch_a, ch_b)
zip_idx3 += 1
testcheck.check(zip_idx3 == 3, "zip str+str OK (3)", "zip str+str FAILED")
stdio.printf("%d\n", " ".isspace())
stdlib.free(arena2)
stdlib.free(arena)
return testcheck.end()
+33
View File
@@ -0,0 +1,33 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "FakeDuckTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"static_libs": [
"D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a",
"D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic_runtime_thunk-x86_64.a"
],
"output": "FakeDuckTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+395
View File
@@ -0,0 +1,395 @@
import t, c
from t import CInt, CInt32T, CUInt32T, CPtr, CChar, CExport
from stdint import *
import stdlib
import viperlib
import w32.win32base
import w32.win32file
import w32.win32console
import w32.fileio
from w32.fileio import File, FileW, MODE, FRESULT, SEEK_SET, SEEK_CUR, SEEK_END
BUF_SIZE: t.CDefine = 4096
def fileio_main():
buf: bytes = stdlib.malloc(256)
write_buf: bytes = stdlib.malloc(BUF_SIZE)
read_buf: bytes = stdlib.malloc(BUF_SIZE)
bytes_written: ULONG = 0
bytes_read: ULONG = 0
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
hFile: w32.win32base.HANDLE = w32.win32file.CreateFileA(
"testfile.txt",
w32.win32file.GENERIC_WRITE,
w32.win32file.FILE_SHARE_READ,
None,
w32.win32file.CREATE_ALWAYS,
w32.win32file.FILE_ATTRIBUTE_NORMAL,
None
)
if hFile == w32.win32base.INVALID_HANDLE_VALUE:
print("Failed to create file")
return
viperlib.snprintf(write_buf, BUF_SIZE, "Hello from TransPyC Win32 FileIO!\nLine 2: %d + %d = %d\n", 10, 20, 30)
write_len: ULONG = 0
i: CInt = 0
ch: bytes = write_buf
while i < BUF_SIZE:
if CInt(c.Deref(ch)) == 0:
break
write_len = write_len + 1
i = i + 1
ch = ch + 1
result: BOOL = w32.win32file.WriteFile(hFile, write_buf, write_len, c.Addr(bytes_written), None)
if result == 0:
print("WriteFile failed")
else:
viperlib.snprintf(buf, 256, "Written %d bytes to testfile.txt", bytes_written)
print(buf)
w32.win32file.FlushFileBuffers(hFile)
w32.win32base.CloseHandle(hFile)
hFile = w32.win32file.CreateFileA(
"testfile.txt",
w32.win32file.GENERIC_READ,
w32.win32file.FILE_SHARE_READ,
None,
w32.win32file.OPEN_EXISTING,
w32.win32file.FILE_ATTRIBUTE_NORMAL,
None
)
if hFile == w32.win32base.INVALID_HANDLE_VALUE:
print("Failed to open file for reading")
return
read_len: ULONG = 0
result = w32.win32file.ReadFile(hFile, read_buf, BUF_SIZE - 1, c.Addr(read_len), None)
if result == 0:
print("ReadFile failed")
else:
viperlib.snprintf(buf, 256, "Read %d bytes from testfile.txt", read_len)
print(buf)
read_ptr: bytes = read_buf
read_ptr = read_ptr + read_len
c.DerefAs(read_ptr, 0)
print("--- File content ---")
print(read_buf)
print("--- End ---")
fileSize: ULONG = w32.win32file.GetFileSize(hFile, None)
viperlib.snprintf(buf, 256, "File size: %d bytes", fileSize)
print(buf)
w32.win32base.CloseHandle(hFile)
attrs: ULONG = w32.win32file.GetFileAttributesA("testfile.txt")
if attrs == w32.win32base.INVALID_HANDLE_VALUE:
print("GetFileAttributes failed")
else:
viperlib.snprintf(buf, 256, "File attributes: 0x%X", attrs)
print(buf)
w32.win32file.DeleteFileA("testfile.txt")
print("File deleted")
stdlib.free(write_buf)
stdlib.free(read_buf)
print("=== OOP FileIO: with context manager ===")
fileio_with_test()
print("=== OOP FileIO: f handle style ===")
fileio_handle_test()
print("=== OOP FileIO: RP/WP/AP modes ===")
fileio_rw_test()
def fileio_with_test():
buf: bytes = stdlib.malloc(256)
write_buf: bytes = stdlib.malloc(BUF_SIZE)
read_buf: bytes = stdlib.malloc(BUF_SIZE)
with File("oop_with.txt", MODE.W) as f:
viperlib.snprintf(write_buf, BUF_SIZE, "with context manager test!\nLine 2: %d\n", 42)
n: LONG = f.write_str(write_buf)
if n < 0:
print("[with] write failed")
else:
viperlib.snprintf(buf, 256, "[with] wrote %d bytes", n)
print(buf)
with File("oop_with.txt", MODE.R) as f:
n = f.read_all(read_buf, BUF_SIZE)
if n < 0:
print("[with] read failed")
else:
viperlib.snprintf(buf, 256, "[with] read %d bytes", n)
print(buf)
print("[with] content:")
print(read_buf)
with File("oop_with.txt", MODE.R) as f:
line1_len: LONG = f.readline(buf, 256)
viperlib.snprintf(read_buf, BUF_SIZE, "[with] Line1(%d): ", line1_len)
print(read_buf)
print(buf)
line2_len: LONG = f.readline(buf, 256)
viperlib.snprintf(read_buf, BUF_SIZE, "[with] Line2(%d): ", line2_len)
print(read_buf)
print(buf)
with File("oop_with.txt", MODE.A) as f:
f.write_str("Appended line!\n")
with File("oop_with.txt", MODE.R) as f:
n = f.read_all(read_buf, BUF_SIZE)
print("[with] after append:")
print(read_buf)
with File("oop_with.txt", MODE.R) as f:
sz: LONGLONG = f.size()
pos: LONG = f.tell()
viperlib.snprintf(buf, 256, "[with] Size=%lld Pos=%d", sz, pos)
print(buf)
f.seek(5, SEEK_SET)
pos = f.tell()
viperlib.snprintf(buf, 256, "[with] After seek: Pos=%d", pos)
print(buf)
w32.win32file.DeleteFileA("oop_with.txt")
print("[with] test file deleted")
stdlib.free(buf)
stdlib.free(write_buf)
stdlib.free(read_buf)
def fileio_handle_test():
buf: bytes = stdlib.malloc(256)
write_buf: bytes = stdlib.malloc(BUF_SIZE)
read_buf: bytes = stdlib.malloc(BUF_SIZE)
fw: File = File("oop_handle.txt", MODE.W)
viperlib.snprintf(write_buf, BUF_SIZE, "f handle style test!\nLine 2: %d\n", 99)
n: LONG = fw.write_str(write_buf)
viperlib.snprintf(buf, 256, "[handle] wrote %d bytes", n)
print(buf)
fw.flush()
fw.close()
fr: File = File("oop_handle.txt", MODE.R)
n = fr.read_all(read_buf, BUF_SIZE)
viperlib.snprintf(buf, 256, "[handle] read %d bytes", n)
print(buf)
print("[handle] content:")
print(read_buf)
fr.close()
fr2: File = File("oop_handle.txt", MODE.R)
line1_len: LONG = fr2.readline(buf, 256)
viperlib.snprintf(read_buf, BUF_SIZE, "[handle] Line1(%d): ", line1_len)
print(read_buf)
print(buf)
line2_len: LONG = fr2.readline(buf, 256)
viperlib.snprintf(read_buf, BUF_SIZE, "[handle] Line2(%d): ", line2_len)
print(read_buf)
print(buf)
fr2.close()
fa: File = File("oop_handle.txt", MODE.A)
fa.write_str("Appended by handle!\n")
fa.close()
fr3: File = File("oop_handle.txt", MODE.R)
n = fr3.read_all(read_buf, BUF_SIZE)
print("[handle] after append:")
print(read_buf)
fr3.close()
fr4: File = File("oop_handle.txt", MODE.R)
sz: LONGLONG = fr4.size()
pos: LONG = fr4.tell()
viperlib.snprintf(buf, 256, "[handle] Size=%lld Pos=%d", sz, pos)
print(buf)
fr4.seek(5, SEEK_SET)
pos = fr4.tell()
viperlib.snprintf(buf, 256, "[handle] After seek: Pos=%d", pos)
print(buf)
fr4.close()
w32.win32file.DeleteFileA("oop_handle.txt")
print("[handle] test file deleted")
stdlib.free(buf)
stdlib.free(write_buf)
stdlib.free(read_buf)
def fileio_rw_test():
buf: bytes = stdlib.malloc(256)
fw: File = File("rw_test.txt", MODE.W)
fw.write_str("original content\n")
fw.close()
frp: File = File("rw_test.txt", MODE.RP)
n: LONG = frp.read_all(buf, 256)
viperlib.snprintf(buf, 256, "[rp] read %d bytes", n)
print(buf)
frp.seek(0, SEEK_END)
frp.write_str("appended via RP\n")
frp.seek(0, SEEK_SET)
n = frp.read_all(buf, 256)
print("[rp] after RP append:")
print(buf)
frp.close()
fwp: File = File("rw_test.txt", MODE.WP)
fwp.write_str("truncated + new\n")
fwp.seek(0, SEEK_SET)
n = fwp.read_all(buf, 256)
print("[wp] WP (truncate+read):")
print(buf)
fwp.close()
fap: File = File("rw_test.txt", MODE.AP)
fap.write_str("a+ appended\n")
fap.seek(0, SEEK_SET)
n = fap.read_all(buf, 256)
print("[ap] AP (append+read):")
print(buf)
fap.close()
w32.win32file.DeleteFileA("rw_test.txt")
print("[rw] test file deleted")
print("=== OOP FileIO: wide char (u\"...\") ===")
fileio_wide_test()
stdlib.free(buf)
def fileio_wide_test():
buf: bytes = stdlib.malloc(256)
fw: File = File("wide_test.txt", MODE.W)
fw.write_str("wide char test\n")
fw.close()
fw2: FileW = FileW(u"wide_test.txt", MODE.R)
n: LONG = fw2.read_all(buf, 256)
viperlib.snprintf(buf, 256, "[wide] read %d bytes", n)
print(buf)
fw2.close()
w32.win32file.DeleteFileA("wide_test.txt")
print("[wide] test file deleted")
stdlib.free(buf)
print("=== OOP FileIO: Chinese filename & content (u\"...\" = WCHAR_T) ===")
fileio_chinese_test()
def fileio_chinese_test():
buf: bytes = stdlib.malloc(512)
bytes_written: ULONG = 0
# === T1: Chinese filename (WCHAR_T) + ANSI content ===
print("[chinese] T1: Chinese filename + ANSI content")
fw: FileW = FileW(u"中文文件.txt", MODE.W)
if fw.closed:
print("[chinese] T1: create failed")
else:
fw.write_str("Hello from Chinese filename!\n")
fw.close()
fr: FileW = FileW(u"中文文件.txt", MODE.R)
n: LONG = fr.read_all(buf, 512)
viperlib.snprintf(buf, 256, "[chinese] T1: read %d bytes", n)
print(buf)
print("[chinese] T1 content:")
print(buf)
fr.close()
w32.win32file.DeleteFileW(u"中文文件.txt")
print("[chinese] T1: deleted")
# === T2: Chinese filename + Chinese wide content (WCHAR_T) ===
print("[chinese] T2: Chinese filename + Chinese wide content")
fw2: FileW = FileW(u"中文内容.txt", MODE.W)
if fw2.closed:
print("[chinese] T2: create failed")
else:
# u"你好世界\n" = 5 WCHARs = 10 bytes (UTF-16LE)
w32.win32file.WriteFile(fw2.handle, u"你好世界\n", 10, c.Addr(bytes_written), None)
viperlib.snprintf(buf, 256, "[chinese] T2: wrote %d WCHAR bytes", bytes_written)
print(buf)
fw2.close()
fr2: FileW = FileW(u"中文内容.txt", MODE.R)
n = fr2.read_all(buf, 512)
viperlib.snprintf(buf, 256, "[chinese] T2: read %d bytes (UTF-16LE)", n)
print(buf)
fr2.close()
w32.win32file.DeleteFileW(u"中文内容.txt")
print("[chinese] T2: deleted")
# === T3: Chinese filename + mixed ANSI + wide content ===
print("[chinese] T3: Chinese filename + mixed content")
fw3: FileW = FileW(u"混合测试.txt", MODE.WP)
if fw3.closed:
print("[chinese] T3: create failed")
else:
fw3.write_str("ASCII line\n")
# u"中文行\n" = 4 WCHARs = 8 bytes (UTF-16LE)
w32.win32file.WriteFile(fw3.handle, u"中文行\n", 8, c.Addr(bytes_written), None)
fw3.seek(0, SEEK_SET)
n: LONG = fw3.read_all(buf, 512)
viperlib.snprintf(buf, 256, "[chinese] T3: total %d bytes", n)
print(buf)
fw3.close()
w32.win32file.DeleteFileW(u"混合测试.txt")
print("[chinese] T3: deleted")
# === T4: Chinese filename + Chinese content via WriteConsoleW ===
print("[chinese] T4: Write wide content and print via WriteConsoleW")
fw4: FileW = FileW(u"控制台测试.txt", MODE.W)
if fw4.closed:
print("[chinese] T4: create failed")
else:
# u"你好,世界!\n" = 7 WCHARs = 14 bytes (UTF-16LE)
w32.win32file.WriteFile(fw4.handle, u"你好,世界!\n", 14, c.Addr(bytes_written), None)
viperlib.snprintf(buf, 256, "[chinese] T4: wrote %d WCHAR bytes", bytes_written)
print(buf)
fw4.close()
fr4: FileW = FileW(u"控制台测试.txt", MODE.R)
n = fr4.read_all(buf, 512)
viperlib.snprintf(buf, 256, "[chinese] T4: read %d bytes", n)
print(buf)
# Print wide content to console using WriteConsoleW
chars_written: ULONG = 0
hOut: w32.win32base.HANDLE = w32.win32file.GetStdHandle(w32.win32file.STD_OUTPUT_HANDLE)
w32.win32console.WriteConsoleW(hOut, u"你好,世界!\n", 7, c.Addr(chars_written), None)
fr4.close()
w32.win32file.DeleteFileW(u"控制台测试.txt")
print("[chinese] T4: deleted")
stdlib.free(buf)
+11
View File
@@ -0,0 +1,11 @@
import t, c
import testcheck
import fileiotest
def main() -> t.CInt | t.CExport:
testcheck.begin("FileIoTest: Win32 FileIO 测试")
testcheck.section("Win32 FileIO")
fileiotest.fileio_main()
testcheck.ok("Win32 FileIO 测试完成")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "FileIoTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "FileIoTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+165
View File
@@ -0,0 +1,165 @@
import t
import c
import stdio
import stdlib
import string
import memhub
import testcheck
def test_for_in_range():
testcheck.section("Test 1: for i in range(n)")
s: t.CInt = 0
for i in range(10):
s += i
testcheck.check(s == 45, "range sum OK (45)", "range sum FAILED expect 45")
def test_for_in_str():
testcheck.section("Test 2: for ch in str")
cnt: t.CInt = 0
for ch in "hello":
cnt += 1
testcheck.check(cnt == 5, "str iter OK (5)", "str iter FAILED expect 5")
def test_for_in_list():
testcheck.section("Test 3: for v in list[str]")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
lst: list[str] = list[str](bd)
lst.append("x")
lst.append("y")
lst.append("z")
lst.append("w")
total: t.CInt = 0
for v in lst:
total += 1
testcheck.check(total == 4, "list iter OK (4)", "list iter FAILED expect 4")
stdlib.free(arena)
def test_zip_list_list():
testcheck.section("Test 4: zip(list, list)")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
la: list[str] = list[str](bd)
la.append("a")
la.append("b")
la.append("c")
lb: list[str] = list[str](bd)
lb.append("1")
lb.append("2")
lb.append("3")
cnt: t.CInt = 0
for ca, cb in zip(la, lb):
stdio.printf("zip[%d]: '%s'='%s'\n", cnt, ca, cb)
cnt += 1
testcheck.check(cnt == 3, "zip list+list OK (3)", "zip list+list FAILED")
stdlib.free(arena)
def test_zip_range_list():
testcheck.section("Test 5: zip(range, list)")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
lst: list[str] = list[str](bd)
lst.append("p")
lst.append("q")
lst.append("r")
cnt: t.CInt = 0
for n, v in zip(range(3), lst):
stdio.printf("zip range+list[%d]: %d='%s'\n", cnt, n, v)
cnt += 1
testcheck.check(cnt == 3, "zip range+list OK (3)", "zip range+list FAILED")
stdlib.free(arena)
def test_zip_str_str():
testcheck.section("Test 6: zip(str, str)")
sa: str = "abc"
sb: str = "123"
cnt: t.CInt = 0
for ca, cb in zip(sa, sb):
stdio.printf("zip str+str[%d]: '%c'%c\n", cnt, ca, cb)
cnt += 1
testcheck.check(cnt == 3, "zip str+str OK (3)", "zip str+str FAILED")
def test_zip_range_len_list():
testcheck.section("Test 7: zip(range(len), list)")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
lst: list[str] = list[str](bd)
lst.append("www")
lst.append("gvsds")
lst.append("com")
cnt: t.CInt = 0
for idx, v in zip(range(len(lst)), lst):
stdio.printf("lst[%d]='%s'\n", idx, v)
cnt += 1
testcheck.check(cnt == 3, "zip(range(len),list) OK (3)", "zip(range(len),list) FAILED")
stdlib.free(arena)
def test_enumerate_list():
testcheck.section("Test 8: enumerate(list)")
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
lst: list[str] = list[str](bd)
lst.append("alpha")
lst.append("beta")
lst.append("gamma")
cnt: t.CInt = 0
last_idx: t.CInt = -1
for idx, v in enumerate(lst):
stdio.printf("enum[%d]='%s'\n", idx, v)
last_idx = idx
cnt += 1
testcheck.check(cnt == 3, "enumerate list OK (3)", "enumerate list FAILED")
testcheck.check(last_idx == 2, "enumerate last_idx OK (2)", "enumerate last_idx FAILED expect 2")
stdlib.free(arena)
def test_enumerate_str():
testcheck.section("Test 9: enumerate(str)")
cnt: t.CInt = 0
last_idx: t.CInt = -1
for idx, ch in enumerate("ABCD"):
stdio.printf("enum str[%d]='%c'\n", idx, ch)
last_idx = idx
cnt += 1
testcheck.check(cnt == 4, "enumerate str OK (4)", "enumerate str FAILED expect 4")
testcheck.check(last_idx == 3, "enumerate str last_idx OK (3)", "enumerate str last_idx FAILED expect 3")
def test_enumerate_range():
testcheck.section("Test 10: enumerate(range)")
cnt: t.CInt = 0
last_idx: t.CInt = -1
last_val: t.CInt = -1
for idx, v in enumerate(range(5)):
stdio.printf("enum range[%d]=%d\n", idx, v)
last_idx = idx
last_val = v
cnt += 1
testcheck.check(cnt == 5, "enumerate range OK (5)", "enumerate range FAILED expect 5")
testcheck.check(last_idx == 4, "enumerate range last_idx OK (4)", "enumerate range last_idx FAILED expect 4")
testcheck.check(last_val == 4, "enumerate range last_val OK (4)", "enumerate range last_val FAILED expect 4")
def main() -> t.CInt:
testcheck.begin("ForAndLoopTest: 迭代器与循环测试")
test_for_in_range()
test_for_in_str()
test_for_in_list()
test_zip_list_list()
test_zip_range_list()
test_zip_str_str()
test_zip_range_len_list()
test_enumerate_list()
test_enumerate_str()
test_enumerate_range()
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "ForAndLoopTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"],
"output": "ForAndLoopTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+52
View File
@@ -0,0 +1,52 @@
from stdint import *
import t, c
import ctraits
import stdio
import testcheck
# ============================================================
# FormatStringTest - 格式化字符串回归测试
# ============================================================
@t.CExport
def main() -> int:
testcheck.begin("FormatStringTest: Format String Regression")
b: str = "hello world"
for i in b:
stdio.printf("%c\n", i)
b += 1
print(b-11)
l: t.CArray[u64] = [0, 43, 2, 3, 4]
l[0] = 1000
for i in l:
stdio.printf("%llu\n", i)
print("Value: ", f"0x{ULONGLONG(0x11)}")
print("ULL Hex: ", f"0x{ULONGLONG(0x11):016X}")
print("LL Hex: ", f"{LONGLONG(0x11):016X}")
print("ULL Dec: ", f"{ULONGLONG(42):d}")
print("LL Dec: ", f"{LONGLONG(42):d}")
print("Hex: ", f"{0x11:016X}")
print("Dec: ", f"{42:d}")
print("Float: ", f"{3.14159:.2f}")
# f-string 赋值测试(验证不再直接 printf,而是生成字符串)
s: str = f"Value=0x{ULONGLONG(42)}, Hex=0x{ULONGLONG(0x11):016X}"
print("Assigned: ", s)
# ctraits.isptr 编译时类型判断测试
ptr_var: INTPTR = c.Addr(s)
val_var: int = 42
if c.CIf(ctraits.isptr(ptr_var)):
print("ptr_var is pointer")
if c.CIf(not ctraits.isptr(val_var)):
print("val_var is not pointer")
testcheck.section("placeholder")
testcheck.ok("testcheck framework ready")
testcheck.info("placeholder test")
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "FormatStringTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "FormatStringTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+106
View File
@@ -0,0 +1,106 @@
import t
import stdio
import testcheck
# 测试基本函数调用
def add(a: t.CInt, b: t.CInt) -> t.CInt:
return a + b
def sub(a: t.CInt, b: t.CInt) -> t.CInt:
return a - b
# 测试多参数
def multi_args(a: t.CInt, b: t.CInt, c: t.CInt, d: t.CInt) -> t.CInt:
return a + b + c + d
# 测试递归
def factorial(n: t.CInt) -> t.CInt:
if n <= 1:
return 1
return n * factorial(n - 1)
# 测试尾递归式斐波那契
def fib(n: t.CInt) -> t.CInt:
if n <= 0:
return 0
if n == 1:
return 1
return fib(n - 1) + fib(n - 2)
# 测试指针参数
def add_via_ptr(p: t.CInt | t.CPtr, val: t.CInt):
p[0] = p[0] + val
# 测试 u64 返回值
def make_u64() -> t.CUInt64T:
return t.CUInt64T(0xDEADBEEF)
# 测试 bool 返回值
def is_even(n: t.CInt) -> t.CBool:
return n % 2 == 0
def test_basic_call():
testcheck.section("Test 1: basic function call")
r: t.CInt = add(10, 20)
testcheck.check(r == 30, "add(10,20)=30", "add(10,20) expect 30")
def test_multi_args():
testcheck.section("Test 2: multi args")
r: t.CInt = multi_args(1, 2, 3, 4)
testcheck.check(r == 10, "multi_args(1,2,3,4)=10", "multi_args(1,2,3,4) expect 10")
def test_recursion():
testcheck.section("Test 3: recursion (factorial)")
r: t.CInt = factorial(10)
# 10! = 3628800
testcheck.check(r == 3628800, "factorial(10)=3628800", "factorial(10) expect 3628800")
def test_fibonacci():
testcheck.section("Test 4: fibonacci")
r: t.CInt = fib(10)
# fib(10) = 55
testcheck.check(r == 55, "fib(10)=55", "fib(10) expect 55")
def test_ptr_param():
testcheck.section("Test 5: pointer parameter")
x: t.CInt = 10
# 需要取 x 的地址
import w32.win32memory
buf: t.CInt | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 12288, 4)
if t.CUInt64T(buf) == 0:
testcheck.info("SKIP: VirtualAlloc returned NULL")
return
buf[0] = 10
add_via_ptr(buf, 25)
testcheck.check(buf[0] == 35, "ptr param (result=35)", "ptr param expect 35")
def test_u64_return():
testcheck.section("Test 6: u64 return")
r: t.CUInt64T = make_u64()
testcheck.check(r == t.CUInt64T(0xDEADBEEF), "u64 return (0xdeadbeef)", "u64 return expect 0xdeadbeef")
def test_bool_return():
testcheck.section("Test 7: bool return")
r1: t.CBool = is_even(4)
r2: t.CBool = is_even(7)
testcheck.check(r1 and not r2, "bool return (is_even(4)=1, is_even(7)=0)", "bool return expect is_even(4)=1, is_even(7)=0")
def test_nested_call():
testcheck.section("Test 8: nested function call")
r: t.CInt = add(factorial(3), sub(10, 3))
# 3! = 6, 10-3 = 7, 6+7 = 13
testcheck.check(r == 13, "nested call (add(factorial(3), sub(10,3))=13)", "nested call expect 13")
import w32.win32memory
export def main() -> t.CInt:
testcheck.begin("FuncTest: 函数调用基准测试")
test_basic_call()
test_multi_args()
test_recursion()
test_fibonacci()
test_ptr_param()
test_u64_return()
test_bool_return()
test_nested_call()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "FuncTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "FuncTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+63
View File
@@ -0,0 +1,63 @@
import t
import stdio
import testcheck
from linkedlist import GSListNode
# ============================================================
# G3: 测试 F-bounded polymorphism
# class Node(GSListNode[Node]) — 继承泛型基类,特化自身为类型参数
# 这与 TransPyV 中 class Value(GSListNode[Value]) 是相同的模式
# ============================================================
@t.NoVTable
class Node(GSListNode[Node]):
value: t.CInt
def __init__(self):
self.value = 0
self.Next = None
def test_node_create():
testcheck.section("Test 1: Node(GSListNode[Node]) create")
n: Node = Node()
n.value = 42
testcheck.check(n.value == 42, "Node.value = 42", "expect 42")
def test_node_next_field():
testcheck.section("Test 2: Next field from GSListNode[Node]")
n1: Node = Node()
n2: Node = Node()
n1.value = 10
n2.value = 20
n1.Next = n2
next_node: Node = n1.Next
v: t.CInt = next_node.value
testcheck.check(v == 20, "n1.Next.value = 20", "expect 20")
def test_node_chain():
testcheck.section("Test 3: Node chain traversal")
a: Node = Node()
b: Node = Node()
c: Node = Node()
a.value = 1
b.value = 2
c.value = 3
a.Next = b
b.Next = c
sum: t.CInt = a.value
p: Node = a.Next
sum = sum + p.value
p = p.Next
sum = sum + p.value
testcheck.check(sum == 6, "chain sum = 1+2+3 = 6", "expect 6")
def main() -> t.CInt:
testcheck.begin("G3: GSListNode inheritance (F-bounded polymorphism)")
test_node_create()
test_node_next_field()
test_node_chain()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "G3",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "G3.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+42
View File
@@ -0,0 +1,42 @@
import t
import stdio
import stdlib
import memhub
from g4node import G4Node, new_g4node
# ============================================================
# caller1: 导入 G4Node 并直接访问 Next 字段(不通过访问器)
#
# 模拟 TransPyV/HandlesExprCall.py 的情况:
# 直接访问 n.Next 触发 GEP 指令,若 stub 字段缺失则 GEP 越界
# ============================================================
def caller1_make_chain(pool: memhub.MemBuddy | t.CPtr) -> G4Node | t.CPtr:
"""创建 3 节点链表,直接访问 Next 字段"""
a: G4Node | t.CPtr = new_g4node(pool)
b: G4Node | t.CPtr = new_g4node(pool)
c: G4Node | t.CPtr = new_g4node(pool)
if a is None or b is None or c is None:
return None
a.IntVal = 100
b.IntVal = 200
c.IntVal = 300
# 直接访问 Next 字段(不通过 g4node_set_next 访问器)
a.Next = b
b.Next = c
return a
def caller1_sum_chain(head: G4Node | t.CPtr) -> t.CInt:
"""遍历链表求和,直接访问 Next 字段"""
if head is None:
return 0
total: t.CInt = head.IntVal
cur: G4Node | t.CPtr = head
# 直接访问 Next 字段(不通过 g4node_get_next 访问器)
while cur.Next is not None:
cur = cur.Next
total = total + cur.IntVal
return total
+36
View File
@@ -0,0 +1,36 @@
import t
import stdio
import stdlib
import memhub
from g4node import G4Node, new_g4node
# ============================================================
# caller2: 另一个导入 G4Node 的模块
#
# 增加 G4Node 的跨模块引用次数,触发多模块竞争条件
# ============================================================
def caller2_reverse_chain(head: G4Node | t.CPtr) -> G4Node | t.CPtr:
"""反转链表,直接访问 Next 字段"""
if head is None:
return None
prev: G4Node | t.CPtr = None
cur: G4Node | t.CPtr = head
while cur is not None:
nxt: G4Node | t.CPtr = cur.Next
cur.Next = prev
prev = cur
cur = nxt
return prev
def caller2_count_nodes(head: G4Node | t.CPtr) -> t.CInt:
"""计算链表节点数"""
count: t.CInt = 0
cur: G4Node | t.CPtr = head
while cur is not None:
count = count + 1
cur = cur.Next
return count
+31
View File
@@ -0,0 +1,31 @@
import t
import stdio
import stdlib
import memhub
from g4node import G4Node, new_g4node
# ============================================================
# caller3: 第三个导入 G4Node 的模块
#
# 进一步增加跨模块引用,模拟 TransPyV 30+ 模块环境
# ============================================================
def caller3_find_tail(head: G4Node | t.CPtr) -> G4Node | t.CPtr:
"""找到链表尾部节点,直接访问 Next"""
if head is None:
return None
cur: G4Node | t.CPtr = head
while cur.Next is not None:
cur = cur.Next
return cur
def caller3_append(head: G4Node | t.CPtr, new_node: G4Node | t.CPtr) -> G4Node | t.CPtr:
"""在链表末尾追加节点"""
if head is None:
return new_node
tail: G4Node | t.CPtr = caller3_find_tail(head)
tail.Next = new_node
return head
+154
View File
@@ -0,0 +1,154 @@
import t
import stdio
import testcheck
import stdlib
from g4node import G4Node, new_g4node, g4node_get_next, g4node_set_next
import memhub
import caller1
import caller2
import caller3
# ============================================================
# G4: 验证 includes 中继承 GSListNode[X] 的类是否会出现
# Next 字段缺失或类型降级的问题
#
# G4Node 类在 includes/g4node.py 中(走 Phase1 路径)
# G4Node 有 5 个自有字段 + 1 个继承字段(Next) = 6 字段
# caller1/caller2/caller3 模拟 TransPyV 多模块环境
# ============================================================
def test_g4node_create():
testcheck.section("Test 1: G4Node create (from includes)")
arena: bytes = stdlib.malloc(4096)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
n: G4Node | t.CPtr = new_g4node(pool)
if n is None:
testcheck.check(False, "new_g4node", "FAIL")
return
n.IntVal = 42
v: t.CInt = n.IntVal
testcheck.check(v == 42, "G4Node.IntVal = 42", "expect 42")
def test_g4node_next_field():
testcheck.section("Test 2: Next field from GSListNode[G4Node]")
arena: bytes = stdlib.malloc(4096)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
n1: G4Node | t.CPtr = new_g4node(pool)
n2: G4Node | t.CPtr = new_g4node(pool)
if n1 is None or n2 is None:
testcheck.check(False, "new_g4node", "FAIL")
return
n1.IntVal = 10
n2.IntVal = 20
g4node_set_next(n1, n2)
next_node: G4Node | t.CPtr = g4node_get_next(n1)
if next_node is None:
testcheck.check(False, "g4node_get_next", "FAIL")
return
v: t.CInt = next_node.IntVal
testcheck.check(v == 20, "n1.Next.IntVal = 20", "expect 20")
def test_g4node_chain():
testcheck.section("Test 3: G4Node chain traversal")
arena: bytes = stdlib.malloc(4096)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
a: G4Node | t.CPtr = new_g4node(pool)
b: G4Node | t.CPtr = new_g4node(pool)
c: G4Node | t.CPtr = new_g4node(pool)
if a is None or b is None or c is None:
testcheck.check(False, "new_g4node", "FAIL")
return
a.IntVal = 1
b.IntVal = 2
c.IntVal = 3
g4node_set_next(a, b)
g4node_set_next(b, c)
sum: t.CInt = a.IntVal
p: G4Node | t.CPtr = g4node_get_next(a)
sum = sum + p.IntVal
p = g4node_get_next(p)
sum = sum + p.IntVal
testcheck.check(sum == 6, "chain sum = 1+2+3 = 6", "expect 6")
def test_caller1_direct_access():
"""caller1: 直接访问 Next 字段(不通过访问器)"""
testcheck.section("Test 4: caller1 direct Next access")
arena: bytes = stdlib.malloc(8192)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 8192)
head: G4Node | t.CPtr = caller1.caller1_make_chain(pool)
if head is None:
testcheck.check(False, "caller1_make_chain", "FAIL")
return
total: t.CInt = caller1.caller1_sum_chain(head)
stdio.printf("caller1 chain total = %d\n", total)
testcheck.check(total == 600, "caller1 sum = 100+200+300 = 600", "expect 600")
def test_caller2_reverse():
"""caller2: 反转链表直接访问 Next"""
testcheck.section("Test 5: caller2 reverse chain")
arena: bytes = stdlib.malloc(8192)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 8192)
head: G4Node | t.CPtr = caller1.caller1_make_chain(pool)
if head is None:
testcheck.check(False, "caller1_make_chain", "FAIL")
return
count_before: t.CInt = caller2.caller2_count_nodes(head)
reversed_head: G4Node | t.CPtr = caller2.caller2_reverse_chain(head)
count_after: t.CInt = caller2.caller2_count_nodes(reversed_head)
stdio.printf("caller2 count before=%d after=%d\n", count_before, count_after)
testcheck.check(count_before == 3 and count_after == 3,
"caller2 reverse count OK (3,3)", "caller2 count mismatch")
def test_caller3_append():
"""caller3: 追加节点直接访问 Next"""
testcheck.section("Test 6: caller3 append node")
arena: bytes = stdlib.malloc(8192)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 8192)
head: G4Node | t.CPtr = caller1.caller1_make_chain(pool)
if head is None:
testcheck.check(False, "caller1_make_chain", "FAIL")
return
extra: G4Node | t.CPtr = new_g4node(pool)
if extra is None:
testcheck.check(False, "new_g4node", "FAIL")
return
extra.IntVal = 400
head = caller3.caller3_append(head, extra)
total: t.CInt = caller1.caller1_sum_chain(head)
stdio.printf("caller3 after append total = %d\n", total)
testcheck.check(total == 1000, "caller3 append sum = 600+400 = 1000", "expect 1000")
def main() -> t.CInt:
testcheck.begin("G4: GSListNode inheritance from includes (Phase1 path)")
test_g4node_create()
test_g4node_next_field()
test_g4node_chain()
test_caller1_direct_access()
test_caller2_reverse()
test_caller3_append()
return testcheck.end()
+53
View File
@@ -0,0 +1,53 @@
import t
from linkedlist import GSListNode
import memhub
# ============================================================
# G4Node: 继承 GSListNode[G4Node] 的测试类
#
# 这个类在 includes 目录中,会走 Phase1 路径
# 模拟 TransPyV 中 Value 类的结构:
# - 继承 GSListNode[G4Node] 获取 Next 字段
# - 5 个自有字段(与 Value 相同数量)
# - @t.NoVTable 装饰器
#
# 继承展平后应有 6 个字段:Next + 5 自有
# 若继承展平失败,只有 5 个字段(缺少 Next)
# ============================================================
@t.NoVTable
class G4Node(GSListNode[G4Node]):
Ty: t.CPtr # 模拟 Value.Ty
Name: t.CPtr # 模拟 Value.Name
IsConst: t.CInt # 模拟 Value.IsConst
IntVal: t.CInt64T # 模拟 Value.IntVal
FloatVal: t.CDouble # 模拟 Value.FloatVal
def __init__(self):
self.Ty = None
self.Name = None
self.IsConst = 0
self.IntVal = 0
self.FloatVal = 0.0
self.Next = None
# 工厂函数(与 __values.py 中的 new_value 类似)
def new_g4node(pool: memhub.MemBuddy | t.CPtr) -> G4Node | t.CPtr:
ptr: G4Node | t.CPtr = pool.alloc(48)
if ptr:
ptr.Ty = None
ptr.Name = None
ptr.IsConst = 0
ptr.IntVal = 0
ptr.FloatVal = 0.0
ptr.Next = None
return ptr
def g4node_get_next(node: G4Node | t.CPtr) -> G4Node | t.CPtr:
return node.Next
def g4node_set_next(node: G4Node | t.CPtr, next_node: G4Node | t.CPtr):
node.Next = next_node
+41
View File
@@ -0,0 +1,41 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "G4",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "G4.exe"
},
"includes": [
"../../includes",
"./includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+176
View File
@@ -0,0 +1,176 @@
import t
import stdio
import testcheck
import stdlib
import memhub
import string
from linkedlist import GSListNode, GSList
# ============================================================
# G5: 验证 GSList[T] 被降级为 opaque 的问题
#
# 版本 2: 不使用 malloc/MemBuddy,直接用构造函数(像 G3 那样)
# 这样能隔离 GSList opaque 问题
# ============================================================
# G5Node: 继承 GSListNode[G5Node](Phase2 路径,正确特化)
@t.NoVTable
class G5Node(GSListNode[G5Node]):
Value: t.CInt
def __init__(self):
self.Next = None
self.Value = 0
# G5ListWrapper: 包装 GSList[G5Node],测试 GSList 字段访问
# 注意:GSList[G5Node] 走 Phase2 特化路径
# 用 pool 工厂函数分配 GSList,避免栈分配悬垂指针
GSLIST_SIZE: t.CDefine = 24 # Head(8) + Tail(8) + Count(8)
@t.NoVTable
class G5ListWrapper:
List: GSList[G5Node] | t.CPtr
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
gsl: GSList[G5Node] | t.CPtr = pool.alloc(GSLIST_SIZE)
if gsl is None:
self.List = None
return
string.memset(gsl, 0, GSLIST_SIZE)
self.List = gsl
# ============================================================
# Test 1: G5Node 字段访问(基准测试,应通过)
# ============================================================
def test_g5node_create():
testcheck.section("Test 1: G5Node create and field access")
n: G5Node = G5Node()
n.Value = 42
v: t.CInt = n.Value
testcheck.check(v == 42, "G5Node.Value = 42", "expect 42")
def test_g5node_next():
testcheck.section("Test 2: G5Node.Next field (GSListNode inheritance)")
n1: G5Node = G5Node()
n2: G5Node = G5Node()
n1.Value = 10
n2.Value = 20
n1.Next = n2
next_node: G5Node = n1.Next
if next_node is None:
testcheck.check(False, "n1.Next is None", "FAIL")
return
v: t.CInt = next_node.Value
testcheck.check(v == 20, "n1.Next.Value = 20", "expect 20")
# ============================================================
# Test 3: GSList 字段访问 — 核心测试
# ============================================================
def test_gslist_create():
testcheck.section("Test 3: GSList[G5Node] create")
lst: GSList[G5Node] | t.CPtr = GSList[G5Node]()
if lst is None:
testcheck.check(False, "GSList[G5Node]() is None", "FAIL")
return
# 检查初始状态
head: G5Node | t.CPtr = lst.Head
tail: G5Node | t.CPtr = lst.Tail
count: t.CSizeT = lst.Count
testcheck.check(head is None, "initial Head is None", "expect None")
testcheck.check(tail is None, "initial Tail is None", "expect None")
testcheck.check(count == 0, "initial Count = 0", "expect 0")
def test_gslist_append():
testcheck.section("Test 4: GSList[G5Node].append 3 nodes")
lst: GSList[G5Node] | t.CPtr = GSList[G5Node]()
if lst is None:
testcheck.check(False, "GSList[G5Node]() is None", "FAIL")
return
a: G5Node = G5Node()
b: G5Node = G5Node()
c: G5Node = G5Node()
a.Value = 1
b.Value = 2
c.Value = 3
lst.append(a)
lst.append(b)
lst.append(c)
# 验证 Count
count: t.CSizeT = lst.Count
testcheck.check(count == 3, "Count = 3 after 3 appends", "expect 3")
# 验证 Head
head: G5Node | t.CPtr = lst.Head
if head is None:
testcheck.check(False, "Head is None", "FAIL")
return
testcheck.check(head.Value == 1, "Head.Value = 1", "expect 1")
# 验证 Tail
tail: G5Node | t.CPtr = lst.Tail
if tail is None:
testcheck.check(False, "Tail is None", "FAIL")
return
testcheck.check(tail.Value == 3, "Tail.Value = 3", "expect 3")
# 遍历链表验证顺序
sum: t.CInt = 0
cur: G5Node | t.CPtr = lst.Head
while cur is not None:
sum = sum + cur.Value
cur = cur.Next
testcheck.check(sum == 6, "chain sum = 1+2+3 = 6", "expect 6")
# ============================================================
# Test 5: G5ListWrapper.List 字段访问(嵌套 GSList 测试)
# ============================================================
def test_wrapper_list_field():
testcheck.section("Test 5: G5ListWrapper.List field (nested GSList, pool alloc)")
arena: bytes = stdlib.malloc(4096)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
wrapper: G5ListWrapper = G5ListWrapper(pool)
if wrapper is None:
testcheck.check(False, "G5ListWrapper(pool) is None", "FAIL")
return
if wrapper.List is None:
testcheck.check(False, "wrapper.List is None", "FAIL")
return
n: G5Node = G5Node()
n.Value = 999
wrapper.List.append(n)
# 通过 wrapper.List 访问 GSList 字段
head: G5Node | t.CPtr = wrapper.List.Head
if head is None:
testcheck.check(False, "wrapper.List.Head is None", "FAIL")
return
count: t.CSizeT = wrapper.List.Count
testcheck.check(head.Value == 999, "wrapper.List.Head.Value = 999", "expect 999")
testcheck.check(count == 1, "wrapper.List.Count = 1", "expect 1")
def main() -> t.CInt:
testcheck.begin("G5: GSList[T] field access (Phase2 path, pool alloc for wrapper)")
test_g5node_create()
test_g5node_next()
test_gslist_create()
test_gslist_append()
test_wrapper_list_field()
return testcheck.end()
+173
View File
@@ -0,0 +1,173 @@
import t
import string
from linkedlist import GSListNode, GSList
import memhub
# ============================================================
# G5Node: 继承 GSListNode[G5Node] 的测试节点
#
# 与 __function.py 中的 Line(GSListNode[Line]) 模式相同。
# 这个类在 includes 目录中,走 Phase1 路径。
# Phase1 的 _specialize_member_types 会将 Next 字段类型 T 降级为 i8*
# 而不是 G5Node*(与 TPV 中 Value/Line 类的情况相同)
# ============================================================
@t.NoVTable
class G5Node(GSListNode[G5Node]):
Value: t.CInt
# ============================================================
# G5Container: 持有 GSList[G5Node] 字段的容器
#
# 这是 G5 测试的核心:GSList[T] 在 Phase1 中被降级为 opaque,
# 导致 List.Head / List.Tail / List.Count 字段访问无法生成 GEP。
#
# 与 __function.py 中的 Function(GSListNode[Function]):
# Params: GSList[Param] | t.CPtr
# Blocks: GSList[BasicBlock] | t.CPtr
# 模式完全相同。
# ============================================================
@t.NoVTable
class G5Container:
List: GSList[G5Node] | t.CPtr
# ============================================================
# 工厂函数(与 __function.py 的 new_line/new_function 模式相同)
# ============================================================
# G5Node 硬编码大小: Next(8) + Value(4) + padding(4) = 16 字节
G5NODE_SIZE: t.CDefine = 16
def new_g5node(pool: memhub.MemBuddy | t.CPtr) -> G5Node | t.CPtr:
"""从 pool 分配并零初始化一个 G5Node"""
ptr: G5Node | t.CPtr = pool.alloc(G5NODE_SIZE)
if ptr is None: return None
string.memset(ptr, 0, G5NODE_SIZE)
return ptr
# GSList 硬编码大小: Head(8) + Tail(8) + Count(8) = 24 字节
G5LIST_SIZE: t.CDefine = 24
def new_g5list(pool: memhub.MemBuddy | t.CPtr) -> GSList | t.CPtr:
"""从 pool 分配并零初始化一个 GSList 容器(Head/Tail/Count 全零)"""
gsl: t.CPtr = pool.alloc(G5LIST_SIZE)
if gsl is None: return None
string.memset(gsl, 0, G5LIST_SIZE)
return gsl
# G5Container 硬编码大小: List(8) = 8 字节
G5CONTAINER_SIZE: t.CDefine = 8
def new_g5container(pool: memhub.MemBuddy | t.CPtr) -> G5Container | t.CPtr:
"""从 pool 分配并零初始化一个 G5Container"""
ptr: G5Container | t.CPtr = pool.alloc(G5CONTAINER_SIZE)
if ptr is None: return None
string.memset(ptr, 0, G5CONTAINER_SIZE)
return ptr
# ============================================================
# 字段访问器(供其他模块绕过 stub 类型限制使用)
#
# 跨模块编译时,使用方模块只有 GSList 的 stub 类型(opaque),
# 导致 TransPyC 静默跳过字段访问(不生成 GEP,不报错),
# 字段值永远为 null。
#
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问
# 所有字段。其他模块通过函数调用获取字段值,绕过 stub 限制。
# ============================================================
def g5list_get_head(lst: GSList | t.CPtr) -> G5Node | t.CPtr:
"""获取链表头节点"""
if lst is None: return None
return lst.Head
def g5list_get_tail(lst: GSList | t.CPtr) -> G5Node | t.CPtr:
"""获取链表尾节点"""
if lst is None: return None
return lst.Tail
def g5list_get_count(lst: GSList | t.CPtr) -> t.CSizeT:
"""获取链表节点数"""
if lst is None: return 0
return lst.Count
def g5list_set_head(lst: GSList | t.CPtr, node: G5Node | t.CPtr):
"""设置链表头节点"""
if lst is None: return
lst.Head = node
def g5list_set_tail(lst: GSList | t.CPtr, node: G5Node | t.CPtr):
"""设置链表尾节点"""
if lst is None: return
lst.Tail = node
def g5list_set_count(lst: GSList | t.CPtr, count: t.CSizeT):
"""设置链表节点数"""
if lst is None: return
lst.Count = count
def g5list_append(lst: GSList | t.CPtr, node: G5Node | t.CPtr):
"""将 node 追加到链表末尾(O(1))
直接操作 Head/Tail/Count 字段,不依赖 GSList.append 方法
(因为跨模块时方法实现可能缺失)
"""
if lst is None or node is None: return
node.Next = None
if lst.Head is None:
lst.Head = node
else:
lst.Tail.Next = node
lst.Tail = node
lst.Count += 1
# ============================================================
# G5Node 访问器
# ============================================================
def g5node_get_value(node: G5Node | t.CPtr) -> t.CInt:
if node is None: return 0
return node.Value
def g5node_set_value(node: G5Node | t.CPtr, value: t.CInt):
if node is None: return
node.Value = value
def g5node_get_next(node: G5Node | t.CPtr) -> G5Node | t.CPtr:
if node is None: return None
return node.Next
def g5node_set_next(node: G5Node | t.CPtr, next_node: G5Node | t.CPtr):
if node is None: return
node.Next = next_node
# ============================================================
# G5Container 访问器
# ============================================================
def g5container_get_list(container: G5Container | t.CPtr) -> GSList | t.CPtr:
if container is None: return None
return container.List
def g5container_set_list(container: G5Container | t.CPtr, lst: GSList | t.CPtr):
if container is None: return
container.List = lst
+41
View File
@@ -0,0 +1,41 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "G5",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "G5.exe"
},
"includes": [
"../../includes",
"./includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+71
View File
@@ -0,0 +1,71 @@
import t, c
import stdio
import testcheck
import atom
# ============================================================
# G6: 验证 atom 模块的内联汇编原子操作
#
# TPV 在编译 atom.py 的 __atomic_test_and_set 时崩溃
# (ACCESS_VIOLATION in ASM args loop ai3=2)
# 此测试用 TPC 编译验证 atom 模块是否正确工作
# ============================================================
def test_atomic_test_and_set():
testcheck.section("Test 1: __atomic_test_and_set")
flag: t.CUInt8T = 0
result: t.CBool = atom.__atomic_test_and_set(c.Addr(flag), atom.ATOMIC_ACQUIRE)
# test_and_set 返回旧值: flag=0 -> 返回 0, flag 变为 1
testcheck.check(result == t.CBool(0), "first set returns old value 0", "expect 0")
testcheck.check(flag == 1, "flag is 1 after set", "expect 1")
# 第二次设置应返回 1(旧值已为 1)
result2: t.CBool = atom.__atomic_test_and_set(c.Addr(flag), atom.ATOMIC_ACQUIRE)
testcheck.check(result2 == t.CBool(1), "second set returns old value 1", "expect 1")
def test_atomic_clear():
testcheck.section("Test 2: __atomic_clear")
flag: t.CUInt8T = 1
atom.__atomic_clear(c.Addr(flag), atom.ATOMIC_RELEASE)
testcheck.check(flag == 0, "flag is 0 after clear", "expect 0")
def test_atomic_thread_fence():
testcheck.section("Test 3: __atomic_thread_fence")
# 只是验证不崩溃
atom.__atomic_thread_fence(atom.ATOMIC_SEQ_CST)
testcheck.ok("mfence executed OK")
def test_atomic_lock_free():
testcheck.section("Test 4: __atomic_is_lock_free")
flag: t.CUInt8T = 0
result: t.CBool = atom.__atomic_is_lock_free(1, c.Addr(flag))
testcheck.check(result == t.CBool(1), "1-byte is lock free", "expect 1")
def test_atomic_spinlock():
testcheck.section("Test 5: spinlock pattern (test_and_set + clear)")
lock: t.CUInt8T = 0
# 获取锁
while atom.__atomic_test_and_set(c.Addr(lock), atom.ATOMIC_ACQUIRE) == t.CBool(1):
pass
testcheck.check(lock == 1, "lock acquired", "expect lock=1")
# 释放锁
atom.__atomic_clear(c.Addr(lock), atom.ATOMIC_RELEASE)
testcheck.check(lock == 0, "lock released", "expect lock=0")
def main() -> t.CInt:
testcheck.begin("G6: atom module (inline asm atomic operations)")
test_atomic_test_and_set()
test_atomic_clear()
test_atomic_thread_fence()
test_atomic_lock_free()
test_atomic_spinlock()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "G6",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "G6.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+52
View File
@@ -0,0 +1,52 @@
import t
import stdio
import testcheck
import stdlib
import memhub
from conflict_node import Value
# ============================================================
# 关键冲突点:全局变量名 'Value' 与类名 'Value' 相同
#
# LlvmGenerator 预处理扫描会将 'Value' 注册为 IsVariable=True
# 覆盖 SymbolTable 中的类条目。
# 之后 _get_or_create_struct('Value') 发现 IsVariable=True,
# 返回 _TypedPointerType 而非 IdentifiedStructType,
# 导致 _TryLoadStructFromStub 中 set_body 被跳过。
# ============================================================
Value: t.CPtr = None
def test_value_struct_fields():
"""验证 Value struct 有 6 个字段(Next + 5 自有)"""
testcheck.section("Value struct field access (6 fields expected)")
arena: bytes = stdlib.malloc(4096)
if arena is None:
testcheck.check(False, "malloc arena", "FAIL")
return
pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
node: Value | t.CPtr = pool.alloc(48)
if node is None:
testcheck.check(False, "alloc Value", "FAIL")
return
# 写入字段 0 (Next, 继承自 GSListNode)
node.Next = None
# 写入字段 1-5 (自有字段)
node.Ty = None
node.Name = None
node.IsConst = 1
node.IntVal = 42
node.FloatVal = 3.14
# 读取验证
v: t.CInt = node.IntVal
testcheck.check(v == 42, "Value.IntVal = 42", "expect 42")
f: t.CDouble = node.FloatVal
testcheck.check(f > 3.0 and f < 4.0, "Value.FloatVal = 3.14", "expect ~3.14")
c: t.CInt = node.IsConst
testcheck.check(c == 1, "Value.IsConst = 1", "expect 1")
def main() -> t.CInt:
testcheck.begin("G7: Minimal repro - class name 'Value' conflicts with variable")
test_value_struct_fields()
return testcheck.end()
+30
View File
@@ -0,0 +1,30 @@
import t
from linkedlist import GSListNode
# ============================================================
# 最小化复现:类名 'Value' 与全局变量名冲突
#
# 这个类在 includes 目录中(走 Phase1 路径),生成 stub.ll
# 继承 GSListNode[Value] 获取 Next 字段
# 5 个自有字段 + 1 个继承字段(Next) = 6 字段
#
# 若 _get_or_create_struct('Value') 因 SymbolTable 中
# IsVariable=True 而返回 _TypedPointerType,
# 则 set_body 被跳过,struct 保持不完整 → GEP 越界崩溃
# ============================================================
@t.NoVTable
class Value(GSListNode[Value]):
Ty: t.CPtr
Name: t.CPtr
IsConst: t.CInt
IntVal: t.CInt64T
FloatVal: t.CDouble
def __init__(self):
self.Ty = None
self.Name = None
self.IsConst = 0
self.IntVal = 0
self.FloatVal = 0.0
self.Next = None
+41
View File
@@ -0,0 +1,41 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "G7",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "G7.exe"
},
"includes": [
"../../includes",
"./includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+136
View File
@@ -0,0 +1,136 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CPtr, CChar, CInt32T, CUInt64T, CFloat64T, CExport, State
import viperlib
import stdlib
import testcheck
# === 函数泛型 ===
def add[T](a: T, b: T) -> T:
return a + b
def add_u64[T](a: T, b: T, c: CUInt64T) -> T:
return a + b + T(c)
def fxi[T1, T2](a: T1, b: T2) -> T1:
return a + fxi2(a, b, CUInt64T(178900))
def fxi2[T1, T2, T3](a: T1, b: T2, c: T3) -> T1:
return a + T1(b) + T1(c)
def wrap_add[T](a: T, b: T) -> T:
return add(a, b)
def double_add[T](a: T, b: T) -> T:
return add(a, b) + add(a, b)
# === 结构体泛型 ===
class A[T]():
a: T
def __init__(self, a: T):
self.a = T(a)
def get_a(self) -> T:
return self.a
class Pair[T1, T2]():
first: T1
second: T2
def __init__(self, first: T1, second: T2):
self.first = T1(first)
self.second = T2(second)
def get_first(self) -> T1:
return self.first
def get_second(self) -> T2:
return self.second
class Calculator[T]():
val: T
def __init__(self, init_val: T):
self.val = T(init_val)
def compute(self, other: T) -> T:
return add(self.val, other)
def double_compute(self, other: T) -> T:
return double_add(self.val, other)
class Container[T]():
value: T
flag: CInt32T
def __init__(self, v: T):
self.value = T(v)
self.flag = CInt32T(1)
def get_value(self) -> T:
return self.value
def get_flag(self) -> CInt32T:
return self.flag
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("GenericOopTest: 泛型专项测试")
buf: CChar | CPtr = CPtr(stdlib.malloc(256))
# === 基础函数泛型 ===
testcheck.section("基础函数泛型")
print(add(3, 5))
print(add(1.5, 2.5))
print(add_u64(1, 2, CUInt64T(3000000000000000)))
print(fxi(0.2, 6))
print(wrap_add(10, 20))
print(double_add(5, 7))
testcheck.ok("基础函数泛型测试完成")
# === 基础结构体泛型 ===
testcheck.section("基础结构体泛型")
a = A(100)
print(a.get_a())
p1 = Pair(10, 20)
print(p1.get_first())
print(p1.get_second())
testcheck.ok("基础结构体泛型测试完成")
# === 泛型 + OOP 组合 ===
testcheck.section("泛型 + OOP 组合")
calc1 = Calculator(10)
print(calc1.compute(5))
calc2 = Calculator(2)
print(calc2.compute(3))
c1_gen = Container(42)
print(c1_gen.get_value())
print(c1_gen.get_flag())
testcheck.ok("泛型 + OOP 组合测试完成")
# === snprintf 格式化 ===
testcheck.section("snprintf 格式化")
viperlib.snprintf(buf, 256, "int=%d, float=%.2f", 42, 3.14)
print(buf)
viperlib.snprintf(buf, 256, "result=%d", add(100, 200))
print(buf)
testcheck.ok("snprintf 格式化测试完成")
# === 新语法类型强转 (t1|t2)(x) ===
testcheck.section("新语法类型强转 (t1|t2)(x)")
val_i64: CUInt64T = CUInt64T(42)
val_i32 = (t.CInt)(val_i64)
print(val_i32)
ptr_raw = stdlib.malloc(8)
ptr_typed = (t.CInt | t.CPtr)(ptr_raw)
viperlib.snprintf(buf, 256, "cast ptr=%p", ptr_typed)
print(buf)
val_f = (t.CDouble)(42)
viperlib.snprintf(buf, 256, "cast float=%.1f", val_f)
print(buf)
testcheck.ok("新语法类型强转测试完成")
stdlib.free(buf)
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "GenericOopTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "GenericOopTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+167
View File
@@ -0,0 +1,167 @@
import t
import stdio
import testcheck
# ============================================================
# Test 1: 泛型函数 - 基本加法
# ============================================================
def add[T](a: T, b: T) -> T:
return a + b
def test_generic_add():
testcheck.section("Test 1: generic add")
r1: t.CInt = add(3, 5)
r2: t.CInt = add(100, 200)
testcheck.check(r1 == 8 and r2 == 300, "generic add (3+5=8, 100+200=300)", "generic add expect 8 and 300")
# ============================================================
# Test 2: 泛型函数 - 多类型参数
# ============================================================
def combine[T1, T2](a: T1, b: T2) -> T1:
return a + T1(b)
def test_generic_combine():
testcheck.section("Test 2: generic combine")
r: t.CInt = combine(10, 20)
testcheck.check(r == 30, "generic combine (10+T1(20)=30)", "generic combine expect 30")
# ============================================================
# Test 3: 泛型函数 - 最大值
# ============================================================
def max_val[T](a: T, b: T) -> T:
if a > b:
return a
return b
def test_generic_max():
testcheck.section("Test 3: generic max")
r1: t.CInt = max_val(10, 20)
r2: t.CInt = max_val(50, 30)
testcheck.check(r1 == 20 and r2 == 50, "generic max (max(10,20)=20, max(50,30)=50)", "generic max expect 20 and 50")
# ============================================================
# Test 4: 泛型类 - Box[T]
# ============================================================
class Box[T]():
value: T
def __init__(self, v: T):
self.value = T(v)
def get(self) -> T:
return self.value
def set(self, v: T):
self.value = T(v)
def test_generic_box():
testcheck.section("Test 4: generic Box[T]")
b = Box(42)
v: t.CInt = b.get()
testcheck.check(v == 42, "Box[int] (get=42)", "Box[int] expect 42")
# ============================================================
# Test 5: 泛型类 - Pair[T1, T2]
# ============================================================
class Pair[T1, T2]():
first: T1
second: T2
def __init__(self, a: T1, b: T2):
self.first = T1(a)
self.second = T2(b)
def sum_as_int(self) -> t.CInt:
return t.CInt(self.first) + t.CInt(self.second)
def test_generic_pair():
testcheck.section("Test 5: generic Pair[T1,T2]")
p = Pair(10, 20)
r: t.CInt = p.sum_as_int()
testcheck.check(r == 30, "Pair[int,int] (sum=30)", "Pair[int,int] expect 30")
# ============================================================
# Test 6: list[T, N] 固定数组
# ============================================================
def test_fixed_array():
testcheck.section("Test 6: list[T, N] fixed array")
arr: t.CArray[t.CInt, 5] = [0]
for i in range(5):
arr[i] = i * 10
total: t.CInt = 0
for i in range(5):
total += arr[i]
# 0+10+20+30+40 = 100
testcheck.check(total == 100, "fixed array (total=100)", "fixed array expect 100")
# ============================================================
# Test 7: list[t.CChar, N] 字符数组
# ============================================================
def test_char_array():
testcheck.section("Test 7: list[t.CChar, N] char array")
buf: t.CArray[t.CChar, 32] = [0]
buf[0] = 72 # H
buf[1] = 105 # i
buf[2] = 0
testcheck.check(buf[0] == 72 and buf[1] == 105, "char array (H=72 i=105)", "char array expect H=72 i=105")
# ============================================================
# Test 8: 泛型函数多次特化
# ============================================================
def identity[T](x: T) -> T:
return x
def test_generic_identity():
testcheck.section("Test 8: generic identity")
r1: t.CInt = identity(42)
r2: t.CInt = identity(0)
testcheck.check(r1 == 42 and r2 == 0, "identity (42=42, 0=0)", "identity expect 42 and 0")
# ============================================================
# Test 9: 泛型函数嵌套调用
# ============================================================
def double_val[T](x: T) -> T:
return add(x, x)
def test_generic_nested():
testcheck.section("Test 9: generic nested call")
r: t.CInt = double_val(21)
testcheck.check(r == 42, "generic nested (double(21)=42)", "generic nested expect 42")
# ============================================================
# Test 10: 泛型类方法调用
# ============================================================
class Counter[T]():
count: T
def __init__(self, start: T):
self.count = T(start)
def increment(self):
self.count = add(self.count, T(1))
def get_count(self) -> T:
return self.count
def test_generic_counter():
testcheck.section("Test 10: generic Counter[T]")
c = Counter(0)
c.increment()
c.increment()
c.increment()
r: t.CInt = c.get_count()
testcheck.check(r == 3, "Counter[int] (count=3)", "Counter[int] expect 3")
def main() -> t.CInt:
testcheck.begin("GenericTest: 泛型测试")
test_generic_add()
test_generic_combine()
test_generic_max()
test_generic_box()
test_generic_pair()
test_fixed_array()
test_char_array()
test_generic_identity()
test_generic_nested()
test_generic_counter()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "GenericTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "GenericTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+273
View File
@@ -0,0 +1,273 @@
import t
import stdio
import c
import testcheck
# ============================================================
# Test 1: 泛型函数 - 不同整数类型特化
# ============================================================
def square[T](x: T) -> T:
return x * x
def test_generic_square_types():
testcheck.section("Test 1: generic square with different types")
r1: t.CInt = square(5)
r2: t.CInt = square(10)
testcheck.check(r1 == 25 and r2 == 100, "square (5^2=25 10^2=100)", "square expect 25 100")
# ============================================================
# Test 2: 泛型函数 - 三参数
# ============================================================
def clamp[T](val: T, lo: T, hi: T) -> T:
if val < lo:
return lo
if val > hi:
return hi
return val
def test_generic_clamp():
testcheck.section("Test 2: generic clamp")
r1: t.CInt = clamp(5, 0, 10)
r2: t.CInt = clamp(-3, 0, 10)
r3: t.CInt = clamp(15, 0, 10)
testcheck.check(r1 == 5 and r2 == 0 and r3 == 10, "clamp (5 0 10)", "clamp expect 5 0 10")
# ============================================================
# Test 3: 泛型类 - Stack[T]
# ============================================================
class Stack[T]():
data: t.CArray[t.CInt, 16]
top: t.CInt
def __init__(self):
self.top = 0
def push(self, val: T):
self.data[self.top] = t.CInt(val)
self.top += 1
def pop(self) -> T:
self.top -= 1
return T(self.data[self.top])
def is_empty(self) -> t.CInt:
if self.top == 0:
return 1
return 0
def size_of(self) -> t.CSizeT:
return self.__sizeof__()
def type_size(self) -> t.CSizeT:
return Stack[T].__sizeof__()
def test_generic_stack():
testcheck.section("Test 3: generic Stack[T]")
# 显式标注 Stack[int]:T 无法从实参推断(__init__ 无参),且 T 决定
# push/pop 的元素宽度(t.CInt(val) ↔ i32),静默默认 int 已被禁止。
s = Stack[int]()
s.push(10)
s.push(20)
s.push(30)
r1: t.CInt = s.pop()
r2: t.CInt = s.pop()
r3: t.CInt = s.pop()
testcheck.check(r1 == 30 and r2 == 20 and r3 == 10, "Stack (pop=30 20 10)", "Stack expect 30 20 10")
# ============================================================
# Test 4: 泛型函数 - swap via pointer
# ============================================================
class IntPair:
a: t.CInt
b: t.CInt
def generic_swap[T](p: IntPair | t.CPtr):
tmp: t.CInt = c.Deref(p).a
c.Deref(p).a = c.Deref(p).b
c.Deref(p).b = tmp
def test_generic_swap():
testcheck.section("Test 4: generic swap via pointer")
p: IntPair = IntPair()
p.a = 100
p.b = 200
generic_swap(c.Addr(p))
testcheck.check(p.a == 200 and p.b == 100, "swap (a=200 b=100)", "swap expect 200 100")
# ============================================================
# Test 5: 泛型类 - Range[T] 迭代器
# ============================================================
class Range[T]():
start: T
end_val: T
step: T
def __init__(self, s: T, e: T, st: T):
self.start = T(s)
self.end_val = T(e)
self.step = T(st)
def sum_all(self) -> T:
result: T = T(0)
i: T = self.start
while i < self.end_val:
result = result + i
i = i + self.step
return result
def test_generic_range():
testcheck.section("Test 5: generic Range[T]")
r = Range(0, 10, 1) # 0+1+2+...+9=45
s: t.CInt = r.sum_all()
testcheck.check(s == 45, "Range sum (0..9=45)", "Range sum expect 45")
# ============================================================
# Test 6: 泛型函数 - 数组求和(非泛型数组参数)
# ============================================================
def array_sum(arr: t.CArray[t.CInt, 8], n: t.CInt) -> t.CInt:
result: t.CInt = 0
for i in range(n):
result += arr[i]
return result
def test_generic_array_sum():
testcheck.section("Test 6: array sum")
arr: t.CArray[t.CInt, 8] = [0]
for i in range(8):
arr[i] = (i + 1) * 10
s: t.CInt = array_sum(arr, 8)
testcheck.check(s == 360, "array sum (360)", "array sum expect 360")
# ============================================================
# Test 7: 泛型函数 - 比较并返回较大值
# ============================================================
def max_of_three[T](a: T, b: T, c_val: T) -> T:
m: T = a
if b > m:
m = b
if c_val > m:
m = c_val
return m
def test_generic_max_three():
testcheck.section("Test 7: generic max of three")
r1: t.CInt = max_of_three(1, 2, 3)
r2: t.CInt = max_of_three(10, 30, 20)
r3: t.CInt = max_of_three(50, 50, 50)
testcheck.check(r1 == 3 and r2 == 30 and r3 == 50, "max3 (3 30 50)", "max3 expect 3 30 50")
# ============================================================
# Test 8: 泛型类 - 带方法的容器
# ============================================================
class Container[T]():
values: t.CArray[t.CInt, 8]
size: t.CInt
def __init__(self):
self.size = 0
def add(self, v: T):
self.values[self.size] = t.CInt(v)
self.size += 1
def get(self, idx: t.CInt) -> T:
return T(self.values[idx])
def contains(self, v: T) -> t.CInt:
for i in range(self.size):
if self.values[i] == t.CInt(v):
return 1
return 0
def total(self) -> T:
result: T = T(0)
for i in range(self.size):
result = result + T(self.values[i])
return result
def test_generic_container():
testcheck.section("Test 8: generic Container[T]")
# 显式标注 Container[int]:__init__ 无参 ⇒ T 无从推断;
# 元素由 add(10)/contains(20)/total() 证据确定是 int(t.CArray[t.CInt, 8])。
c = Container[int]()
c.add(10)
c.add(20)
c.add(30)
has20: t.CInt = c.contains(20)
has99: t.CInt = c.contains(99)
total: t.CInt = c.total()
testcheck.check(has20 == 1 and has99 == 0 and total == 60, "Container (has20=1 has99=0 total=60)", "Container expect 1 0 60")
# ============================================================
# Test 9: 泛型函数 - 阶乘
# ============================================================
def factorial[T](n: T) -> T:
result: T = T(1)
i: T = T(2)
while i <= n:
result = result * i
i = i + T(1)
return result
def test_generic_factorial():
testcheck.section("Test 9: generic factorial")
r1: t.CInt = factorial(5)
r2: t.CInt = factorial(10)
testcheck.check(r1 == 120 and r2 == 3628800, "factorial (5!=120 10!=3628800)", "factorial expect 120 3628800")
# ============================================================
# Test 10: 泛型类 - 累加器
# ============================================================
class Accumulator[T]():
total: T
def __init__(self, start: T):
self.total = T(start)
def add_val(self, v: T):
self.total = self.total + v
def get_result(self) -> T:
return self.total
def test_generic_accumulator():
testcheck.section("Test 10: generic Accumulator[T]")
a = Accumulator(0)
a.add_val(10)
a.add_val(20)
a.add_val(30)
r: t.CInt = a.get_result()
testcheck.check(r == 60, "Accumulator (result=60)", "Accumulator expect 60")
# ============================================================
# Test 11: 泛型结构体 sizeof (修复验证)
# 特化后 Stack[int] = { [16 x i32], i32 } = 68 字节
# 验证 obj.__sizeof__() 和类内部 self.__sizeof__() 均返回正确大小
# ============================================================
def test_generic_sizeof_bug():
testcheck.section("Test 11: generic sizeof (fixed)")
# 同 Test 3:无参构造必须显式标注类型实参;Stack[int] = { [16 x i32], i32 } = 68。
s = Stack[int]()
s.push(10)
sz: t.CSizeT = s.__sizeof__()
inner_sz: t.CSizeT = s.size_of()
type_sz: t.CSizeT = s.type_size()
stdio.printf("Stack[int] obj.__sizeof__() = %lu, self.__sizeof__() = %lu, Stack[T].__sizeof__() = %lu (expect 68)\n", sz, inner_sz, type_sz)
testcheck.check(sz == 68, "obj.__sizeof__() == 68 OK", "obj.__sizeof__() FAILED")
testcheck.check(inner_sz == 68, "self.__sizeof__() == 68 OK", "self.__sizeof__() FAILED")
testcheck.check(type_sz == 68, "Stack[T].__sizeof__() == 68 OK", "Stack[T].__sizeof__() FAILED")
def main() -> t.CInt:
testcheck.begin("GenericTest2: Advanced Generic Tests")
test_generic_square_types()
test_generic_clamp()
test_generic_stack()
test_generic_swap()
test_generic_range()
test_generic_array_sum()
test_generic_max_three()
test_generic_container()
test_generic_factorial()
test_generic_accumulator()
test_generic_sizeof_bug()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "GenericTest2",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "GenericTest2.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+57
View File
@@ -0,0 +1,57 @@
import t
import stdio
import testcheck
# ============================================================
# Test 1: 泛型函数手动传类型参数 - 基本调用
# def xxx[T](x: int) 然后调用 xxx[T](x)
# ============================================================
def double[T](x: int) -> int:
return x * 2
def test_explicit_type_arg():
testcheck.section("Test 1: explicit type arg xxx[T](x)")
r: t.CInt = double[t.CInt](21)
testcheck.check(r == 42, "double[t.CInt](21) = 42", "expect 42")
# ============================================================
# Test 2: 泛型函数手动传类型参数 - 多次调用不同类型
# ============================================================
def identity[T](x: int) -> int:
return x
def test_identity_explicit():
testcheck.section("Test 2: identity[T](x)")
r1: t.CInt = identity[t.CInt](10)
r2: t.CInt = identity[t.CInt](20)
testcheck.check(r1 == 10 and r2 == 20, "identity[t.CInt](10)=10 (20)=20", "expect 10 20")
# ============================================================
# Test 3: 泛型函数手动传类型参数 - 用 T 作为参数类型
# ============================================================
def add_one[T](x: T) -> T:
return x + T(1)
def test_add_one_explicit():
testcheck.section("Test 3: add_one[T](x) with T param")
r: t.CInt = add_one[t.CInt](41)
testcheck.check(r == 42, "add_one[t.CInt](41) = 42", "expect 42")
# ============================================================
# Test 4: 泛型函数手动传类型参数 - 混合自动推导和手动传
# ============================================================
def test_mixed_inference_explicit():
testcheck.section("Test 4: mixed inference and explicit")
# 自动推导
r1: t.CInt = add_one(99)
# 手动传
r2: t.CInt = add_one[t.CInt](99)
testcheck.check(r1 == 100 and r2 == 100, "add_one(99)=100 add_one[t.CInt](99)=100", "expect 100 100")
def main() -> t.CInt:
testcheck.begin("GenericTest3: 手动传类型参数 xxx[T](x)")
test_explicit_type_arg()
test_identity_explicit()
test_add_one_explicit()
test_mixed_inference_explicit()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "GenericTest3",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "GenericTest3.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+109
View File
@@ -0,0 +1,109 @@
import t
import stdio
import testcheck
# ============================================================
# Test 1: 泛型类手动传类型参数 - Box[t.CInt](v)
# ============================================================
class Box[T]():
value: T
def __init__(self, v: T):
self.value = T(v)
def get(self) -> T:
return self.value
def set(self, v: T):
self.value = T(v)
def test_explicit_box():
testcheck.section("Test 1: Box[t.CInt](42)")
b = Box[t.CInt](42)
v: t.CInt = b.get()
testcheck.check(v == 42, "Box[t.CInt](42).get() = 42", "expect 42")
# ============================================================
# Test 2: 泛型类手动传类型参数 - Pair[t.CInt, t.CInt]
# ============================================================
class Pair[T1, T2]():
first: T1
second: T2
def __init__(self, a: T1, b: T2):
self.first = T1(a)
self.second = T2(b)
def sum_as_int(self) -> t.CInt:
return t.CInt(self.first) + t.CInt(self.second)
def test_explicit_pair():
testcheck.section("Test 2: Pair[t.CInt, t.CInt](10, 20)")
p = Pair[t.CInt, t.CInt](10, 20)
r: t.CInt = p.sum_as_int()
testcheck.check(r == 30, "Pair[t.CInt,t.CInt](10,20).sum = 30", "expect 30")
# ============================================================
# Test 3: 泛型类手动传 + 自动推导混合
# ============================================================
class Wrapper[T]():
data: T
def __init__(self, v: T):
self.data = T(v)
def get(self) -> T:
return self.data
def test_mixed_generic_class():
testcheck.section("Test 3: mixed explicit and inferred")
# 手动传
w1 = Wrapper[t.CInt](100)
# 自动推导
w2 = Wrapper(200)
r1: t.CInt = w1.get()
r2: t.CInt = w2.get()
testcheck.check(r1 == 100 and r2 == 200, "Wrapper[t.CInt](100)=100 Wrapper(200)=200", "expect 100 200")
# ============================================================
# Test 4: 泛型类手动传 - 方法调用
# ============================================================
class Counter[T]():
count: T
def __init__(self, start: T):
self.count = T(start)
def increment(self):
self.count = self.count + T(1)
def get_count(self) -> T:
return self.count
def test_explicit_counter():
testcheck.section("Test 4: Counter[t.CInt](0) with methods")
c = Counter[t.CInt](0)
c.increment()
c.increment()
c.increment()
r: t.CInt = c.get_count()
testcheck.check(r == 3, "Counter[t.CInt](0) +3 = 3", "expect 3")
# ============================================================
# Test 5: 泛型类手动传 - set 方法
# ============================================================
def test_explicit_box_set():
testcheck.section("Test 5: Box[t.CInt] set method")
b = Box[t.CInt](10)
b.set(99)
v: t.CInt = b.get()
testcheck.check(v == 99, "Box[t.CInt].set(99) get = 99", "expect 99")
def main() -> t.CInt:
testcheck.begin("GenericTest4: 泛型结构体手动传类型参数")
test_explicit_box()
test_explicit_pair()
test_mixed_generic_class()
test_explicit_counter()
test_explicit_box_set()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "GenericTest4",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "GenericTest4.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+123
View File
@@ -0,0 +1,123 @@
import t, c
import stdio
import stdlib
import string
import testcheck
import hashlib
import binascii
import base64
import w32.win32console
# ==============================================
# 工具函数:打印十六进制哈希串
# ==============================================
def print_hex(buf: t.CUInt8T | t.CPtr, length: t.CInt):
for i in range(length):
stdio.printf("%02x", buf[i])
stdio.printf("\n")
def default_value_test_function(a: t.CInt, b: t.CInt = 1):
print(a, b)
def main() -> t.CInt | t.CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("HashLibTest: 哈希与校验测试")
# ---------- hashlib 摘要测试 ----------
testcheck.section("HASHLIB")
plain: str = "hello123"
md5_buf: t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN]
mctx = hashlib.md5()
mctx.update(plain)
mctx.final(md5_buf)
print("MD5: ")
print_hex(md5_buf, hashlib.MD5_DIGEST_LEN)
testcheck.ok("HASHLIB md5 completed")
sha1_buf: t.CArray[t.CUInt8T, hashlib.SHA1_DIGEST_LEN]
s1ctx = hashlib.sha1()
s1ctx.update(plain)
s1ctx.final(sha1_buf)
print("SHA1: ")
print_hex(sha1_buf, hashlib.SHA1_DIGEST_LEN)
testcheck.ok("HASHLIB sha1 completed")
sha256_buf: t.CArray[t.CUInt8T, hashlib.SHA256_DIGEST_LEN]
s2ctx = hashlib.sha256()
s2ctx.update(plain)
s2ctx.final(sha256_buf)
print("SHA256: ")
print_hex(sha256_buf, hashlib.SHA256_DIGEST_LEN)
testcheck.ok("HASHLIB sha256 completed")
sha512_buf: t.CArray[t.CUInt8T, hashlib.SHA512_DIGEST_LEN]
s5ctx = hashlib.sha512()
s5ctx.update(plain)
s5ctx.final(sha512_buf)
print("SHA512: ")
print_hex(sha512_buf, hashlib.SHA512_DIGEST_LEN)
testcheck.ok("HASHLIB sha512 completed")
default_value_test_function(b=2, a=1)
testcheck.ok("default value test completed")
# ---------- base64 编解码测试 ----------
testcheck.section("BASE64")
b64_out: t.CArray[t.CChar, 256]
b64_dec: t.CArray[t.CUInt8T, 256]
base64.b64encode(plain, b64_out)
print("Base64 编码:", b64_out)
dlen: t.CSizeT = base64.b64decode(b64_out, b64_dec)
b64_dec[dlen] = 0
print("Base64 解码:", b64_dec)
testcheck.ok("BASE64 encode/decode completed")
# ---------- binascii 全套测试 ----------
testcheck.section("BINASCII")
binascii.init_binascii()
raw: str = "HelloWorld!"
raw_length: t.CInt = 11
hex_out: str = binascii.b2a_hex(raw, raw_length)
if hex_out:
stdio.printf("Hex: %s\n", hex_out)
stdlib.free(hex_out)
testcheck.ok("BINASCII b2a_hex completed")
crc_val: t.CUnsignedInt = binascii.crc32(raw, raw_length, 0)
stdio.printf("CRC32: %u\n", crc_val)
testcheck.ok("BINASCII crc32 completed")
b64_out2: str = binascii.b2a_base64(raw, raw_length)
if b64_out2:
stdio.printf("Base64: %s\n", b64_out2)
stdlib.free(b64_out2)
testcheck.ok("BINASCII b2a_base64 completed")
uu_out: str = binascii.b2a_uu(raw, raw_length)
if uu_out:
stdio.printf("UU: %s\n", uu_out)
stdlib.free(uu_out)
testcheck.ok("BINASCII b2a_uu completed")
hqx_in: t.CArray[t.CChar, 4] = ['A', 'B', 'C', '\0']
hqx_crc: t.CUnsignedShort = 0
hqx_out: str
unhqx: str
hqx_out, hqx_crc = binascii.b2a_hqx(hqx_in, 3)
unhqx, hqx_crc = binascii.a2b_hqx(hqx_out)
stdio.printf("HQX Test: ABC -> %s -> %s (CRC:%u)\n", hqx_out, unhqx, hqx_crc)
stdlib.free(hqx_out); stdlib.free(unhqx)
testcheck.ok("BINASCII hqx completed")
adler_val: t.CUnsignedInt = binascii.adler32(raw, raw_length, 1)
stdio.printf("Adler32: %u\n", adler_val)
testcheck.ok("BINASCII adler32 completed")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "HashLibTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "HashLibTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+210
View File
@@ -0,0 +1,210 @@
from stdint import *
import w32.win32console
import t, c
from t import CInt, CExport
import stdio
import stdlib
import string
import memhub
import hashtable
import testcheck
def main() -> CInt | CExport:
w32.win32console.SetConsoleCP(65001)
w32.win32console.SetConsoleOutputCP(65001)
testcheck.begin("HashTableTest: 开放寻址哈希表测试")
# 分配内存竞技场
arena: bytes = stdlib.malloc(65536)
bd: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 65536)
# === Test 1: 基本插入和查找 ===
testcheck.section("Test 1: 基本插入和查找 (set_int)")
ht: hashtable.HashTable = hashtable.HashTable(bd)
ht.set_int("alpha", 10)
ht.set_int("beta", 20)
ht.set_int("gamma", 30)
n: t.CSizeT = len(ht)
stdio.printf("len=%lu\n", n)
testcheck.check(n == 3, "ht len OK (3)", "ht len FAILED")
# 哈希表的 int 值按 int(i32)写入(见 hashtable.vp set_int 的 int_ptr),读回
# 须给出有元素类型的指针:c.Deref 的宽度只认 pointee 类型,i8*(t.CPtr)恒读
# 1 字节,不再按赋值目标注解反推 4 字节。
p1: t.CPtr = ht["alpha"]
v1: int = c.Deref((int | t.CPtr)(p1))
p2: t.CPtr = ht["beta"]
v2: int = c.Deref((int | t.CPtr)(p2))
p3: t.CPtr = ht["gamma"]
v3: int = c.Deref((int | t.CPtr)(p3))
stdio.printf("alpha=%d beta=%d gamma=%d\n", v1, v2, v3)
testcheck.check(v1 == 10, "ht[alpha]==10 OK", "ht[alpha] FAILED")
testcheck.check(v2 == 20, "ht[beta]==20 OK", "ht[beta] FAILED")
testcheck.check(v3 == 30, "ht[gamma]==30 OK", "ht[gamma] FAILED")
# === Test 2: 更新已有键 ===
testcheck.section("Test 2: 更新已有键")
ht.set_int("beta", 99)
p2b: t.CPtr = ht["beta"]
v2b: int = c.Deref((int | t.CPtr)(p2b))
stdio.printf("beta(updated)=%d\n", v2b)
testcheck.check(v2b == 99, "ht update OK", "ht update FAILED")
testcheck.check(len(ht) == 3, "ht len still 3 OK", "ht len changed FAILED")
# === Test 3: get with default ===
testcheck.section("Test 3: get with default")
gv: t.CPtr = ht.get("missing", None)
testcheck.check(gv == None, "ht get missing OK (None)", "ht get missing FAILED")
gp: t.CPtr = ht.get("alpha", None)
ga: int = c.Deref((int | t.CPtr)(gp))
stdio.printf("get(alpha)=%d\n", ga)
testcheck.check(ga == 10, "ht get existing OK", "ht get existing FAILED")
# === Test 4: contains ===
testcheck.section("Test 4: contains (in)")
has_alpha: t.CInt = "alpha" in ht
has_missing: t.CInt = "missing" in ht
stdio.printf("contains(alpha)=%d contains(missing)=%d\n", has_alpha, has_missing)
testcheck.check(has_alpha == 1, "contains alpha OK", "contains alpha FAILED")
testcheck.check(has_missing == 0, "not contains missing OK", "contains missing FAILED")
# === Test 5: 删除 ===
testcheck.section("Test 5: 删除 (del)")
deleted: t.CInt = ht.__delitem__("beta")
stdio.printf("del beta=%d\n", deleted)
testcheck.check(deleted == 1, "del beta OK", "del beta FAILED")
testcheck.check(len(ht) == 2, "ht len 2 after del OK", "ht len after del FAILED")
has_beta: t.CInt = "beta" in ht
testcheck.check(has_beta == 0, "beta gone OK", "beta still exists FAILED")
# 删除不存在的 key
del_missing: t.CInt = ht.__delitem__("nokey")
testcheck.check(del_missing == 0, "del missing returns 0 OK", "del missing FAILED")
# === Test 6: 删除后重新插入 ===
testcheck.section("Test 6: 删除后重新插入")
ht.set_int("beta", 555)
p2c: t.CPtr = ht["beta"]
v2c: int = c.Deref((int | t.CPtr)(p2c))
stdio.printf("beta(re-inserted)=%d\n", v2c)
testcheck.check(v2c == 555, "ht re-insert beta OK", "ht re-insert beta FAILED")
testcheck.check(len(ht) == 3, "ht len 3 after re-insert OK", "ht len after re-insert FAILED")
# === Test 7: 迭代器 ===
testcheck.section("Test 7: 迭代器 for key in ht")
iter_count: int = 0
for key in ht:
kp: t.CPtr = ht[key]
val: int = c.Deref((int | t.CPtr)(kp))
stdio.printf("ht[%s]=%d\n", key, val)
iter_count += 1
testcheck.check(iter_count == 3, "ht iter OK (3)", "ht iter FAILED")
# === Test 8: 字符串值 ===
testcheck.section("Test 8: 字符串值 (set_str)")
ht2: hashtable.HashTable = hashtable.HashTable(bd)
ht2.set_str("name", "Alice")
ht2.set_str("city", "Beijing")
ht2.set_str("lang", "TransPyC")
n2: t.CSizeT = len(ht2)
stdio.printf("ht2 len=%lu\n", n2)
testcheck.check(n2 == 3, "ht set_str len OK (3)", "ht set_str len FAILED")
name_p: t.CPtr = ht2["name"]
city_p: t.CPtr = ht2["city"]
lang_p: t.CPtr = ht2["lang"]
name: str = name_p
city: str = city_p
lang: str = lang_p
stdio.printf("name=%s city=%s lang=%s\n", name, city, lang)
# i8* == 是指针地址比较(C-Like 语义),内容比较需显式 strcmp
testcheck.check(string.strcmp(name, "Alice") == 0, "ht str name OK", "ht str name FAILED")
testcheck.check(string.strcmp(city, "Beijing") == 0, "ht str city OK", "ht str city FAILED")
testcheck.check(string.strcmp(lang, "TransPyC") == 0, "ht str lang OK", "ht str lang FAILED")
# === Test 9: 扩容测试 ===
testcheck.section("Test 9: 扩容测试 (>16 个元素)")
ht3: hashtable.HashTable = hashtable.HashTable(bd)
i: int = 0
while i < 50:
key_buf: str = stdlib.malloc(16)
stdio.sprintf(key_buf, "key%d", i)
ht3.set_int(key_buf, i * 100)
i += 1
n3: t.CSizeT = len(ht3)
stdio.printf("ht3 len=%lu (after 50 inserts)\n", n3)
testcheck.check(n3 == 50, "ht expand OK (50)", "ht expand FAILED")
# 验证几个值
k5: str = stdlib.malloc(16)
stdio.sprintf(k5, "key5")
p5: t.CPtr = ht3[k5]
v5: int = c.Deref((int | t.CPtr)(p5))
stdio.printf("ht3[key5]=%d\n", v5)
testcheck.check(v5 == 500, "ht expand key5 OK", "ht expand key5 FAILED")
k25: str = stdlib.malloc(16)
stdio.sprintf(k25, "key25")
p25: t.CPtr = ht3[k25]
v25: int = c.Deref((int | t.CPtr)(p25))
stdio.printf("ht3[key25]=%d\n", v25)
testcheck.check(v25 == 2500, "ht expand key25 OK", "ht expand key25 FAILED")
k49: str = stdlib.malloc(16)
stdio.sprintf(k49, "key49")
p49: t.CPtr = ht3[k49]
v49: int = c.Deref((int | t.CPtr)(p49))
stdio.printf("ht3[key49]=%d\n", v49)
testcheck.check(v49 == 4900, "ht expand key49 OK", "ht expand key49 FAILED")
# === Test 10: 扩容后迭代 ===
testcheck.section("Test 10: 扩容后迭代")
iter_count3: int = 0
for k in ht3:
iter_count3 += 1
stdio.printf("ht3 iter count=%d\n", iter_count3)
testcheck.check(iter_count3 == 50, "ht expand iter OK (50)", "ht expand iter FAILED")
# === Test 11: 删除后扩容 ===
testcheck.section("Test 11: 批量删除后操作")
j: int = 0
while j < 25:
del_buf: str = stdlib.malloc(16)
stdio.sprintf(del_buf, "key%d", j)
del ht3[del_buf]
j += 1
n3b: t.CSizeT = len(ht3)
stdio.printf("ht3 len=%lu (after 25 deletes)\n", n3b)
testcheck.check(n3b == 25, "ht after del OK (25)", "ht after del FAILED")
# 验证剩余的值
k30: str = stdlib.malloc(16)
stdio.sprintf(k30, "key30")
p30: t.CPtr = ht3[k30]
v30: int = c.Deref((int | t.CPtr)(p30))
stdio.printf("ht3[key30]=%d\n", v30)
testcheck.check(v30 == 3000, "ht key30 after del OK", "ht key30 after del FAILED")
# 验证已删除的 key 不存在
k0: str = stdlib.malloc(16)
stdio.sprintf(k0, "key0")
has_k0: t.CInt = k0 in ht3
testcheck.check(has_k0 == 0, "ht key0 deleted OK", "ht key0 still exists FAILED")
# === Test 12: 空表操作 ===
testcheck.section("Test 12: 空表操作")
ht4: hashtable.HashTable = hashtable.HashTable(bd)
testcheck.check(len(ht4) == 0, "empty ht len 0 OK", "empty ht len FAILED")
empty_get: t.CPtr = ht4.get("none", None)
testcheck.check(empty_get == None, "empty ht get OK", "empty ht get FAILED")
has_none: t.CInt = "none" in ht4
testcheck.check(has_none == 0, "empty ht contains OK", "empty ht contains FAILED")
empty_iter: int = 0
for ek in ht4:
empty_iter += 1
testcheck.check(empty_iter == 0, "empty ht iter OK (0)", "empty ht iter FAILED")
stdlib.free(arena)
return testcheck.end()
+29
View File
@@ -0,0 +1,29 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "HashTableTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"],
"output": "HashTableTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+43
View File
@@ -0,0 +1,43 @@
import t
from t import CInt
# ============================================================
# 跨模块 isinstance 测试库
#
# 供 main.vp import 使用:验证 isinstance 对"定义在其他模块
# 的类"也能正确比较(对象 vtable 指针跨 obj 链接解析)。
# ============================================================
@t.CVTable
class Shape:
def area(self) -> CInt:
return 0
@t.CVTable
class Circle(Shape):
r: CInt
def __init__(self, r: CInt):
self.r = r
def area(self) -> CInt:
return self.r
@t.CVTable
class Square(Shape):
s: CInt
def __init__(self, s: CInt):
self.s = s
def area(self) -> CInt:
return self.s
@t.NoVTable
class PlainShape:
tag: CInt
+153
View File
@@ -0,0 +1,153 @@
from stdint import *
import t, c
import testcheck
import geom_lib
from t import CInt, CPtr, CExport
# ============================================================
# isinstance 内建函数测试(运行时 vtable 继承链比较)
#
# 场景覆盖:
# 1. CVTable 自身/子类→基类
# 2. 运行时多态(基类指针指向子类对象)
# 3. 元组 (A, B)
# 4. 多继承(AB 同时是 A 和 B 的实例)
# 5. NoVTable 类(编译时静态判断)
# ============================================================
# ========== CVTable 继承 ==========
@t.CVTable
class Animal:
Name: str
def __init__(self, name: str):
self.Name = name
def speak(self) -> str:
return "..."
@t.CVTable
class Dog(Animal):
def __init__(self, name: str):
self.Name = name
def speak(self) -> str:
return "Woof"
@t.CVTable
class Cat(Animal):
def speak(self) -> str:
return "Meow"
# ========== 多继承 ==========
@t.CVTable
class A:
a: CInt
def get_a(self) -> CInt:
return self.a
@t.CVTable
class B:
b: CInt
def get_b(self) -> CInt:
return self.b
@t.CVTable
class AB(A, B):
def __init__(self, a: CInt, b: CInt):
self.a = a
self.b = b
# ========== NoVTable(编译时判断) ==========
@t.NoVTable
class Plain:
v: CInt
def main() -> CInt | CExport:
testcheck.begin("IsinstanceTest: isinstance 内建函数测试")
# --- 1. 自身类型 + 子类→基类 ---
d: Dog | CPtr = Dog("dog")
testcheck.check(isinstance(d, Dog) == 1, "isinstance(d, Dog) 自身 OK",
"isinstance(d, Dog) FAILED")
testcheck.check(isinstance(d, Animal) == 1, "isinstance(d, Animal) 子类→基类 OK",
"isinstance(d, Animal) FAILED")
testcheck.check(isinstance(d, Cat) == 0, "isinstance(d, Cat) 不匹配 OK",
"isinstance(d, Cat) FAILED")
# --- 2. 运行时多态:基类指针指向子类对象 ---
a: Animal | CPtr = (Animal | CPtr)(d)
testcheck.check(isinstance(a, Dog) == 1,
"isinstance(Animal*, Dog 对象) 运行时多态 OK",
"isinstance(Animal*, Dog) FAILED")
testcheck.check(isinstance(a, Animal) == 1,
"isinstance(Animal*, Animal) 基类自身 OK",
"isinstance(Animal*, Animal) FAILED")
testcheck.check(isinstance(a, Cat) == 0,
"isinstance(Animal*, Cat) 运行时 False OK",
"isinstance(Animal*, Cat) FAILED")
# --- 3. 元组 ---
testcheck.check(isinstance(d, (Cat, Dog)) == 1, "isinstance 元组命中 OK",
"isinstance 元组 FAILED")
testcheck.check(isinstance(d, (Cat, A)) == 0, "isinstance 元组未命中 OK",
"isinstance 元组未命中 FAILED")
# --- 4. 多继承 ---
ab: AB | CPtr = AB(1, 2)
testcheck.check(isinstance(ab, A) == 1, "isinstance(AB, A) 多继承 OK",
"isinstance(AB, A) FAILED")
testcheck.check(isinstance(ab, B) == 1, "isinstance(AB, B) 多继承 OK",
"isinstance(AB, B) FAILED")
testcheck.check(isinstance(ab, Animal) == 0, "isinstance(AB, Animal) False OK",
"isinstance(AB, Animal) FAILED")
testcheck.check(ab.get_a() == 1 and ab.get_b() == 2, "AB 字段/方法正常 OK",
"AB 字段/方法 FAILED")
# --- 5. NoVTable(编译时静态判断) ---
p: Plain | CPtr = Plain()
p.v = 42
testcheck.check(isinstance(p, Plain) == 1, "isinstance NoVTable 编译时 OK",
"isinstance NoVTable FAILED")
testcheck.check(p.v == 42, "NoVTable 字段正常 OK", "NoVTable 字段 FAILED")
# --- 6. 跨模块 isinstance(vtable 跨 obj 链接解析) ---
cc: geom_lib.Circle | CPtr = geom_lib.Circle(5)
testcheck.check(isinstance(cc, geom_lib.Circle) == 1,
"跨模块 isinstance 自身 OK", "跨模块 isinstance 自身 FAILED")
testcheck.check(isinstance(cc, geom_lib.Shape) == 1,
"跨模块 isinstance 子类→基类 OK", "跨模块 isinstance 子类→基类 FAILED")
testcheck.check(isinstance(cc, geom_lib.Square) == 0,
"跨模块 isinstance 不匹配 OK", "跨模块 isinstance 不匹配 FAILED")
sq: geom_lib.Square | CPtr = geom_lib.Square(3)
testcheck.check(isinstance(sq, geom_lib.Shape) == 1,
"跨模块 Square→Shape OK", "跨模块 Square→Shape FAILED")
testcheck.check(isinstance(sq, geom_lib.Circle) == 0,
"跨模块 Square vs Circle OK", "跨模块 Square vs Circle FAILED")
shp: geom_lib.Shape | CPtr = (geom_lib.Shape | CPtr)(cc)
testcheck.check(isinstance(shp, geom_lib.Circle) == 1,
"跨模块运行时多态 OK", "跨模块运行时多态 FAILED")
testcheck.check(shp.area() == 5, "跨模块虚方法分派 OK", "跨模块虚方法分派 FAILED")
testcheck.check(cc.area() == 5, "跨模块 Circle.area OK", "跨模块 Circle.area FAILED")
# --- 7. NoVTable 跨模块静态判断 ---
ps: geom_lib.PlainShape | CPtr = geom_lib.PlainShape()
testcheck.check(isinstance(ps, geom_lib.PlainShape) == 1,
"跨模块 NoVTable 静态 OK", "跨模块 NoVTable 静态 FAILED")
testcheck.ok("isinstance 全部测试完成")
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "IsinstanceTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "IsinstanceTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128"
},
"options": {
"slice_level": 3,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+52
View File
@@ -0,0 +1,52 @@
import t
import stdio
import string
import testcheck
def test_for_in_string():
testcheck.section("Test 1: for-in string iteration")
s: t.CChar | t.CPtr = "Hello"
result: t.CInt = 0
for ch in s:
result += ch
# H=72, e=101, l=108, l=108, o=111 => 500
testcheck.check(result == 500, "for-in string (sum=500)", "for-in string (sum expect 500)")
def test_for_in_char_ptr():
testcheck.section("Test 2: for-in char* iteration")
s: t.CChar | t.CPtr = "ABC"
chars: t.CArray[t.CInt, 4] = [0]
idx: t.CInt = 0
for ch in s:
if idx < 3:
chars[idx] = ch
idx += 1
testcheck.check(chars[0] == 65 and chars[1] == 66 and chars[2] == 67, "for-in char* (A=65 B=66 C=67)", "for-in char* (expect A=65 B=66 C=67)")
def test_strcpy_for_in():
testcheck.section("Test 3: strcpy using for-in")
src: t.CChar | t.CPtr = "test"
# 手动实现 strcpy 用 for-in
import w32.win32memory
buf: t.CChar | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 12288, 4)
if t.CUInt64T(buf) == 0:
stdio.printf("SKIP: VirtualAlloc returned NULL\n")
return
string.memset(buf, 0, 64)
# 用 for-in 复制
p: t.CChar | t.CPtr = buf
for ch in src:
p[0] = ch
p += 1
p[0] = 0
# i8* == 是指针地址比较(C-Like 语义),字符串内容比较需显式 strcmp
testcheck.check(string.strcmp(buf, "test") == 0, "strcpy for-in (result=test)", "strcpy for-in (cmp mismatch)")
import w32.win32memory
def main() -> t.CInt:
testcheck.begin("IterTest: 指针迭代测试")
test_for_in_string()
test_for_in_char_ptr()
test_strcpy_for_in()
return testcheck.end()
+40
View File
@@ -0,0 +1,40 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "IterTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "IterTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
+309
View File
@@ -0,0 +1,309 @@
import t, c
from stdint import *
from stdio import printf
import memhub
import json
import string
import w32.win32memory as win32mem
import testcheck
# ============================================================
# 测试 1:构造 JSON 值(使用 mpool)
# ============================================================
def test_construct(pool: memhub.MemPool | t.CPtr):
testcheck.section("Construct JsonValue (with mpool)")
# null
v1: json.JsonValue | t.CPtr = json.null(pool)
testcheck.check(v1.is_null(), "null is_null", "null is_null")
# bool
v2: json.JsonValue | t.CPtr = json.bool_val(pool, True)
testcheck.check(v2.is_bool(), "bool true is_bool", "bool true is_bool")
testcheck.check(v2.as_bool(), "bool true as_bool", "bool true as_bool")
v3: json.JsonValue | t.CPtr = json.bool_val(pool, False)
testcheck.check(not v3.as_bool(), "bool false !as_bool", "bool false !as_bool")
# int
v4: json.JsonValue | t.CPtr = json.int_val(pool, 42)
testcheck.check(v4.is_int(), "int is_int", "int is_int")
testcheck.check(v4.as_int() == 42, "int 42 == 42", "int 42 == 42")
v5: json.JsonValue | t.CPtr = json.int_val(pool, -100)
testcheck.check(v5.as_int() == -100, "int -100 == -100", "int -100 == -100")
# float
v6: json.JsonValue | t.CPtr = json.float_val(pool, 3.14)
testcheck.check(v6.is_float(), "float is_float", "float is_float")
testcheck.check(v6.as_float() > 3.13 and v6.as_float() < 3.15, "float 3.14 ~= 3.14", "float 3.14 ~= 3.14")
# string
v7: json.JsonValue | t.CPtr = json.string_val(pool, "hello")
testcheck.check(v7.is_string(), "string is_string", "string is_string")
testcheck.check(string.strcmp(v7.as_string(), "hello") == 0, "string == hello", "string == hello")
# array
v8: json.JsonValue | t.CPtr = json.array(pool)
testcheck.check(v8.is_array(), "array is_array", "array is_array")
testcheck.check(len(v8) == 0, "array empty len()==0", "array empty len()==0")
# object
v9: json.JsonValue | t.CPtr = json.object(pool)
testcheck.check(v9.is_object(), "object is_object", "object is_object")
testcheck.check(len(v9) == 0, "object empty len()==0", "object empty len()==0")
# ============================================================
# 测试 2:构造数组和对象(Python风格API)
# ============================================================
def test_build_structures(pool: memhub.MemPool | t.CPtr):
testcheck.section("Build Arrays and Objects (Pythonic API)")
# 构建数组 [1, 2, 3]
arr: json.JsonValue | t.CPtr = json.array(pool)
json.array_append(pool, arr, json.int_val(pool, 1))
json.array_append(pool, arr, json.int_val(pool, 2))
json.array_append(pool, arr, json.int_val(pool, 3))
testcheck.check(len(arr) == 3, "array [1,2,3] len()==3", "array [1,2,3] len()==3")
testcheck.check(arr.get_item(0).as_int() == 1, "array get_item(0)==1", "array get_item(0)==1")
testcheck.check(arr.get_item(1).as_int() == 2, "array get_item(1)==2", "array get_item(1)==2")
testcheck.check(arr.get_item(2).as_int() == 3, "array get_item(2)==3", "array get_item(2)==3")
# 构建对象 {"name": "Viper", "version": 1}
obj: json.JsonValue | t.CPtr = json.object(pool)
json.object_set(pool, obj, "name", json.string_val(pool, "Viper"))
json.object_set(pool, obj, "version", json.int_val(pool, 1))
testcheck.check(len(obj) == 2, "object len()==2", "object len()==2")
# Python风格取值:obj["key"]
name_val: json.JsonValue | t.CPtr = obj["name"]
testcheck.check(name_val != None and string.strcmp(name_val.as_string(), "Viper") == 0, "obj['name']==Viper", "obj['name']==Viper")
ver_val: json.JsonValue | t.CPtr = obj["version"]
testcheck.check(ver_val != None and ver_val.as_int() == 1, "obj['version']==1", "obj['version']==1")
missing: json.JsonValue | t.CPtr = obj["missing"]
testcheck.check(missing == None, "obj['missing']==None", "obj['missing']==None")
# ============================================================
# 测试 3:JSON 解析
# ============================================================
def test_parse(pool: memhub.MemPool | t.CPtr):
testcheck.section("Parse JSON")
# 解析整数
v1: json.JsonValue | t.CPtr = json.parse(pool, "42")
testcheck.check(v1.is_int(), "parse int is_int", "parse int is_int")
testcheck.check(v1.as_int() == 42, "parse int == 42", "parse int == 42")
# 解析负数
v2: json.JsonValue | t.CPtr = json.parse(pool, "-7")
testcheck.check(v2.as_int() == -7, "parse neg int == -7", "parse neg int == -7")
# 解析浮点数
v3: json.JsonValue | t.CPtr = json.parse(pool, "3.14")
testcheck.check(v3.is_float(), "parse float is_float", "parse float is_float")
testcheck.check(v3.as_float() > 3.13 and v3.as_float() < 3.15, "parse float ~= 3.14", "parse float ~= 3.14")
# 解析字符串
v4: json.JsonValue | t.CPtr = json.parse(pool, '"hello world"')
testcheck.check(v4.is_string(), "parse string is_string", "parse string is_string")
testcheck.check(string.strcmp(v4.as_string(), "hello world") == 0, "parse string == hello world", "parse string == hello world")
# 解析布尔
v5: json.JsonValue | t.CPtr = json.parse(pool, "true")
testcheck.check(v5.is_bool(), "parse true is_bool", "parse true is_bool")
testcheck.check(v5.as_bool(), "parse true as_bool", "parse true as_bool")
v6: json.JsonValue | t.CPtr = json.parse(pool, "false")
testcheck.check(not v6.as_bool(), "parse false !as_bool", "parse false !as_bool")
# 解析 null
v7: json.JsonValue | t.CPtr = json.parse(pool, "null")
testcheck.check(v7.is_null(), "parse null is_null", "parse null is_null")
# 解析数组
v8: json.JsonValue | t.CPtr = json.parse(pool, "[1, 2, 3]")
testcheck.check(v8.is_array(), "parse array is_array", "parse array is_array")
testcheck.check(len(v8) == 3, "parse array len()==3", "parse array len()==3")
testcheck.check(v8.get_item(0).as_int() == 1, "parse array get_item(0)==1", "parse array get_item(0)==1")
testcheck.check(v8.get_item(2).as_int() == 3, "parse array get_item(2)==3", "parse array get_item(2)==3")
# 解析对象(Python风格取值)
v9: json.JsonValue | t.CPtr = json.parse(pool, '{"x": 10, "y": 20}')
testcheck.check(v9.is_object(), "parse object is_object", "parse object is_object")
testcheck.check(len(v9) == 2, "parse object len()==2", "parse object len()==2")
x_val: json.JsonValue | t.CPtr = v9["x"]
testcheck.check(x_val != None and x_val.as_int() == 10, "parse obj['x']==10", "parse obj['x']==10")
y_val: json.JsonValue | t.CPtr = v9["y"]
testcheck.check(y_val != None and y_val.as_int() == 20, "parse obj['y']==20", "parse obj['y']==20")
# ============================================================
# 测试 4:JSON 序列化
# ============================================================
def test_write(pool: memhub.MemPool | t.CPtr):
testcheck.section("Write JSON")
# 写整数
v1: json.JsonValue | t.CPtr = json.int_val(pool, 42)
s1: t.CChar | t.CPtr = json.write(pool, v1, False)
testcheck.check(string.strcmp(s1, "42") == 0, "write int 42", "write int 42")
# 写字符串
v2: json.JsonValue | t.CPtr = json.string_val(pool, "hello")
s2: t.CChar | t.CPtr = json.write(pool, v2, False)
testcheck.check(string.strcmp(s2, '"hello"') == 0, "write string hello", "write string hello")
# 写布尔
v3: json.JsonValue | t.CPtr = json.bool_val(pool, True)
s3: t.CChar | t.CPtr = json.write(pool, v3, False)
testcheck.check(string.strcmp(s3, "true") == 0, "write bool true", "write bool true")
v4: json.JsonValue | t.CPtr = json.bool_val(pool, False)
s4: t.CChar | t.CPtr = json.write(pool, v4, False)
testcheck.check(string.strcmp(s4, "false") == 0, "write bool false", "write bool false")
# 写 null
v5: json.JsonValue | t.CPtr = json.null(pool)
s5: t.CChar | t.CPtr = json.write(pool, v5, False)
testcheck.check(string.strcmp(s5, "null") == 0, "write null", "write null")
# 写数组
arr: json.JsonValue | t.CPtr = json.array(pool)
json.array_append(pool, arr, json.int_val(pool, 1))
json.array_append(pool, arr, json.int_val(pool, 2))
json.array_append(pool, arr, json.int_val(pool, 3))
s6: t.CChar | t.CPtr = json.write(pool, arr, False)
testcheck.check(string.strcmp(s6, "[1,2,3]") == 0, "write array [1,2,3]", "write array [1,2,3]")
# 写对象
obj: json.JsonValue | t.CPtr = json.object(pool)
json.object_set(pool, obj, "a", json.int_val(pool, 1))
json.object_set(pool, obj, "b", json.string_val(pool, "x"))
s7: t.CChar | t.CPtr = json.write(pool, obj, False)
testcheck.check(s7 != None, "write object non-null", "write object non-null")
# ============================================================
# 测试 5:解析复杂嵌套 JSON(Python风格API)
# ============================================================
def test_nested(pool: memhub.MemPool | t.CPtr):
testcheck.section("Parse Nested JSON (Pythonic API)")
src: t.CChar | t.CPtr = '{"name": "Viper", "version": 1, "features": ["fast", "safe", "portable"], "nested": {"key": "value", "num": 99}}'
root: json.JsonValue | t.CPtr = json.parse(pool, src)
testcheck.check(root.is_object(), "nested is_object", "nested is_object")
testcheck.check(len(root) == 4, "nested len()==4", "nested len()==4")
# Python风格取值:root["name"]
name: json.JsonValue | t.CPtr = root["name"]
testcheck.check(name != None and string.strcmp(name.as_string(), "Viper") == 0, "root['name']==Viper", "root['name']==Viper")
# root["version"]
ver: json.JsonValue | t.CPtr = root["version"]
testcheck.check(ver != None and ver.as_int() == 1, "root['version']==1", "root['version']==1")
# root["features"] 数组
feat: json.JsonValue | t.CPtr = root["features"]
testcheck.check(feat != None and feat.is_array(), "root['features'] is_array", "root['features'] is_array")
testcheck.check(feat != None and len(feat) == 3, "root['features'] len()==3", "root['features'] len()==3")
testcheck.check(feat != None and string.strcmp(feat.get_item(0).as_string(), "fast") == 0, "root['features'][0]==fast", "root['features'][0]==fast")
testcheck.check(feat != None and string.strcmp(feat.get_item(2).as_string(), "portable") == 0, "root['features'][2]==portable", "root['features'][2]==portable")
# root["nested"] 对象
nested: json.JsonValue | t.CPtr = root["nested"]
testcheck.check(nested != None and nested.is_object(), "root['nested'] is_object", "root['nested'] is_object")
nk: json.JsonValue | t.CPtr = nested["key"] if nested != None else None
testcheck.check(nk != None and string.strcmp(nk.as_string(), "value") == 0, "root['nested']['key']==value", "root['nested']['key']==value")
nn: json.JsonValue | t.CPtr = nested["num"] if nested != None else None
testcheck.check(nn != None and nn.as_int() == 99, "root['nested']['num']==99", "root['nested']['num']==99")
# ============================================================
# 测试 6:mpool 重置后重新使用
# ============================================================
def test_mpool_reuse():
testcheck.section("MPool Reuse")
# 分配内存
mem: t.CPtr = win32mem.VirtualAlloc(None, 8192, 0x3000, 0x04)
testcheck.check(mem != None, "VirtualAlloc ok", "VirtualAlloc ok")
pool: memhub.MemPool | t.CPtr = memhub.MemPool(mem, 8192)
# 第一次使用
v1: json.JsonValue | t.CPtr = json.int_val(pool, 100)
testcheck.check(v1.as_int() == 100, "reuse round1 int==100", "reuse round1 int==100")
# 重置 mpool
pool.reset()
# 第二次使用(内存复用)
v2: json.JsonValue | t.CPtr = json.string_val(pool, "reused")
testcheck.check(string.strcmp(v2.as_string(), "reused") == 0, "reuse round2 string==reused", "reuse round2 string==reused")
# 重置后再解析
pool.reset()
v3: json.JsonValue | t.CPtr = json.parse(pool, '{"test": true}')
testcheck.check(v3.is_object(), "reuse round3 parse ok", "reuse round3 parse ok")
tv: json.JsonValue | t.CPtr = v3["test"]
testcheck.check(tv != None and tv.as_bool(), "reuse round3 obj['test']==true", "reuse round3 obj['test']==true")
win32mem.VirtualFree(mem, 0, 0x8000)
# ============================================================
# 测试 7:转义字符解析
# ============================================================
def test_escape(pool: memhub.MemPool | t.CPtr):
testcheck.section("Escape Characters")
# 解析含转义字符的字符串
v1: json.JsonValue | t.CPtr = json.parse(pool, '"hello\\nworld"')
testcheck.check(v1.is_string(), "escape \\n is_string", "escape \\n is_string")
sv1: t.CChar | t.CPtr = v1.as_string()
testcheck.check(sv1 != None and sv1[5] == '\n', "escape \\n contains newline", "escape \\n contains newline")
v2: json.JsonValue | t.CPtr = json.parse(pool, '"tab\\there"')
testcheck.check(v2.is_string(), "escape \\t is_string", "escape \\t is_string")
sv2: t.CChar | t.CPtr = v2.as_string()
testcheck.check(sv2 != None and sv2[3] == '\t', "escape \\t contains tab", "escape \\t contains tab")
v3: json.JsonValue | t.CPtr = json.parse(pool, '"quote\\""')
testcheck.check(v3.is_string(), "escape \\\" is_string", "escape \\\" is_string")
# ============================================================
# 主函数
# ============================================================
def main() -> t.CInt | t.CExport:
testcheck.begin("JSON Library Test (Pythonic API)")
# 使用 mpool 的 bump 分配器
mem: t.CPtr = win32mem.VirtualAlloc(None, 65536, 0x3000, 0x04)
pool: memhub.MemPool | t.CPtr = memhub.MemPool(mem, 65536)
test_construct(pool)
pool.reset()
test_build_structures(pool)
pool.reset()
test_parse(pool)
pool.reset()
test_write(pool)
pool.reset()
test_nested(pool)
pool.reset()
test_escape(pool)
pool.reset()
test_mpool_reuse()
win32mem.VirtualFree(mem, 0, 0x8000)
return testcheck.end()
+39
View File
@@ -0,0 +1,39 @@
{
"name": "JsonTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": [
"-filetype=obj",
"-relocation-model=pic"
]
},
"linker": {
"cmd": "clang++",
"flags": [
"-Wl,--allow-multiple-definition",
"-lmsvcrt",
"-lucrt",
"-lpthread",
"-lmingwex",
"-lkernel32",
"-luser32"
],
"output": "JsonTest.exe"
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
File diff suppressed because it is too large. Load diff
+33
View File
@@ -0,0 +1,33 @@
{
"$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json",
"name": "LLvmLiteTest",
"version": "1.0.0",
"source_dir": "./App",
"build_dir": "./.tpv_build",
"compiler": {
"cmd": "llc",
"flags": ["-filetype=obj", "-relocation-model=pic"]
},
"linker": {
"cmd": "clang++",
"flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"],
"output": "LLvmLiteTest.exe",
"static_libs": [
"D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a",
"D:/msys64/clang64/lib/clang/22/lib/windows/libclang_rt.asan_dynamic_runtime_thunk-x86_64.a"
]
},
"includes": [
"../../includes"
],
"target": {
"triple": "x86_64-pc-windows-gnu",
"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,
"sha1_slice_level": 1,
"target": "llvm",
"strict_mode": true
}
}
Loaded 100 of 196 files, more files were not shown because too many files have changed in this diff. Show more