Files
TransPyC/_test_vast_c_diff.py
T
2026-08-22 02:35:30 +08:00

143 lines
3.9 KiB
Python

"""vast_c vs vast 差分测试:验证 C 解析器输出与纯 Python vast 完全一致。
用法:python _test_vast_c_diff.py [--verbose]
退出码:0=全部通过,1=有失败。
"""
import sys
sys.path.insert(0, r'd:\Users\TermiNexus\Desktop\TransPyC')
sys.path.insert(0, r'd:\Users\TermiNexus\Desktop\TransPyC\lib')
import vast
import vast_c
CASES = [
# ---- 表达式 ----
'x = 1',
'x = 1 + 2 * 3',
'x = (1 + 2) * 3',
'x = 2 ** 3',
'x = -2 ** 2',
'x = 2 ** -1',
'x = 1.5e10',
'x = 0x1F + 0b101 + 1_000_000',
'x = a if b else c',
'x = a < b < c',
'x = a is not b',
'x = c not in d',
'x = a and b or not c',
'x = a | b & c ^ d',
'x = a << 2 >> 1',
'x = a.b.c',
'x = a.b.c[0].d(1, 2, k=3)',
'x = f(a, *args, b=1, **kw)',
'x = a[1:2]',
'y = a[::2]',
'z = a[1, 2]',
'x = (1, 2)',
'x = [1, 2, 3]',
'x = {"a": 1, "b": [1, 2]}',
'x = {1, 2, 3}',
'l = [x for x in range(10) if x % 2 == 0]',
'g = (x * 2 for x in range(5))',
'd = {k: v for k, v in pairs}',
'f = lambda x, y=1: x + y',
'x = (y := 5)',
'x = True',
'x = None',
'x = ...',
'x = "a" "b" "c"',
'x = f"{name} is {age} years old"',
'x = f"{x!r} {y:>10}"',
'x = b"bytes"',
'x = r"raw\\nstring"',
'x = await f()',
'x = -5',
'y = ~x',
'z = +3',
# ---- 语句 ----
'x = 1',
'y',
'a = b = c',
'x: int = 5',
'y: list[int]',
'z: str | None = None',
'x += 1',
'def foo(a, b=2):\n return a + b',
'def foo(a: int, b: float = 2.5) -> str:\n return str(a)',
'def f(x, *args, y=1, **kwargs):\n pass',
'def f() -> None:\n return None',
'@decorator\ndef foo():\n pass',
'@t.NoVTable\nclass Foo:\n pass',
'class Foo:\n x: int = 1\n def __init__(self):\n pass',
'class Foo(Bar, Baz):\n pass',
'if x > 0:\n y = 1\nelif x < 0:\n y = -1\nelse:\n y = 0',
'for i in range(10):\n print(i)',
'while x < 10:\n x += 1',
'try:\n pass\nexcept Exception as e:\n raise\nexcept:\n pass\nfinally:\n pass',
'with open("f") as f:\n data = f.read()',
'import os',
'from sys import argv, exit as e',
'import a.b.c as abc',
'global x',
'nonlocal y',
'del x[0], y',
'assert x == 1, "msg"',
'raise ValueError("bad")',
'match x:\n case 1:\n pass\n case _:\n pass',
'async def g():\n await f()',
'async for i in stream:\n pass',
'async with lock:\n pass',
'fn foo():\n return 1',
'func bar(x):\n return x',
'extern def A(x: int) -> int: pass',
'extern A(x: int) -> int',
'extern def B(x: int) -> int',
'export def C(x: int) -> int: pass',
'export C(x: int) -> int: pass',
'extern D() -> None: pass',
'extern def E[T](x: T) -> T: pass',
]
def compare(src):
try:
ref = vast.dump(vast.parse(src), indent=2)
ref_ok = True
except Exception as e:
ref = f'<{type(e).__name__}: {e}>'
ref_ok = False
try:
got = vast_c.parse(src)
got_dump = vast.dump(got, indent=2)
got_ok = True
except Exception as e:
got_dump = f'<{type(e).__name__}: {e}>'
got_ok = False
if ref == got_dump:
return True, ref
return False, (ref, got_dump, ref_ok, got_ok)
def main():
verbose = '--verbose' in sys.argv
fails = 0
for src in CASES:
ok, res = compare(src)
if not ok:
fails += 1
ref, got, ref_ok, got_ok = res
print('FAIL', repr(src[:60]))
print(' ref:', ref[:400] if ref_ok else ref)
print(' got:', got[:400] if got_ok else got)
elif verbose:
print('OK ', repr(src[:60]))
total = len(CASES)
print('=' * 40)
print(f'PASS: {total - fails}/{total} FAIL: {fails}')
return 0 if fails == 0 else 1
if __name__ == '__main__':
sys.exit(main())