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