"""Regression tests against real RoborunPlus-compiled output.

tests/fixtures/ holds a representative subset of the reverse-engineering
corpus (see docs/reverse_engineering.md) -- pairs of .mbs source and the
exact .hex RoborunPlus produced for it. These aren't hand-written
expectations: they're ground truth, captured directly from the real
compiler. If the byte-for-byte comparison ever fails, that means codegen.py
has drifted from confirmed, evidence-backed behavior -- treat it as a real
regression, not a test to "fix" by updating the fixture.
"""

from pathlib import Path

import pytest

from microbasic_compiler.codegen import generate_bytecode
from microbasic_compiler.hexfile import read_intel_hex
from microbasic_compiler.lexer import tokenize
from microbasic_compiler.parser import parse
from microbasic_compiler.preprocessor import expand_macros

FIXTURES_DIR = Path(__file__).parent / "fixtures"
FIXTURE_NAMES = sorted(p.stem for p in FIXTURES_DIR.glob("*.mbs"))


@pytest.mark.parametrize("name", FIXTURE_NAMES)
def test_matches_real_compiler_output(name: str):
    source = (FIXTURES_DIR / f"{name}.mbs").read_text()
    expected = read_intel_hex((FIXTURES_DIR / f"{name}.hex").read_text()).rstrip(b"\xff")

    tokens = expand_macros(tokenize(source))
    program = parse(tokens)
    actual = generate_bytecode(program)

    assert actual == expected, (
        f"{name}: bytecode mismatch\n"
        f"  ours:     {actual.hex(' ')}\n"
        f"  expected: {expected.hex(' ')}"
    )
