143 lines
3.9 KiB
Python
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())
|