tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

workspace_compile.py (4031B)


      1 #!/usr/bin/env python3
      2 """Haskell-only real-compiler workspace acceptance; no retained build artifacts.
      3 Usage: python3 test/workspace_compile.py /absolute/path/to/tricu
      4 """
      5 from pathlib import Path
      6 import re
      7 import shutil
      8 import subprocess
      9 import sys
     10 import tempfile
     11 
     12 
     13 def main():
     14     host = str(Path(sys.argv[1]).resolve())
     15     with tempfile.TemporaryDirectory(prefix="tricu-workspace-acceptance-") as tmp:
     16         root = Path(tmp)
     17         project = root / "project"
     18         app = project / "apps"
     19         lib = project / "lib"
     20         app.mkdir(parents=True)
     21         lib.mkdir()
     22         entry = app / "main.tri"
     23         entry.write_text("!import facade as F\n!export main\nmain = F.answer\n")
     24         (lib / "facade-source.tri").write_text("!export * from numbers\n")
     25         (lib / "numbers-source.tri").write_text("!export answer\nanswer = 42\n")
     26         declaration = project / "tricu.workspace"
     27         declaration.write_text("tricu.workspace.v1\nfacade\tlib/facade-source.tri\nnumbers\tlib/numbers-source.tri\n")
     28 
     29         def run(*args, success=True):
     30             p = subprocess.run([host, *map(str, args), "+RTS", "-N1", "-RTS"],
     31                                cwd=root, text=True, capture_output=True, timeout=180)
     32             assert (p.returncode == 0) == success, (args, p.stdout, p.stderr)
     33             return p.stdout
     34 
     35         store = root / "store"
     36         assert run("eval", entry, "--store", store, "--format", "number").strip() == "42"
     37         mapped_bundle = root / "mapped.arboricx"
     38         run("arboricx", "compile", "--file", entry, "--store", store, "--output", mapped_bundle)
     39         flat = root / "flat"
     40         flat.mkdir()
     41         shutil.copyfile(entry, flat / "main.tri")
     42         shutil.copyfile(lib / "facade-source.tri", flat / "facade.tri")
     43         shutil.copyfile(lib / "numbers-source.tri", flat / "numbers.tri")
     44         flat_bundle = root / "flat.arboricx"
     45         run("arboricx", "compile", "--file", flat / "main.tri", "--store", root / "flat-store", "--output", flat_bundle)
     46         assert mapped_bundle.read_bytes() == flat_bundle.read_bytes(), "location changed bundle identity"
     47         # Capture shares the location resolver; replay is isolated even under a
     48         # parent declaration that would otherwise conflict with retained sources.
     49         tools = root / "tools"
     50         shipped = Path(__file__).resolve().parent.parent / "bootstrap/build-stable.arboricx"
     51         imported = run("arboricx", "import", "--file", shipped, "--store", tools)
     52         compiler = re.search(r"Created module alias .* -> ([0-9a-f]{64})", imported)[1]
     53         run("arboricx", "compile", "--file", entry, "--store", store,
     54             "--toolchain", compiler, "--tool-store", tools, "--output", mapped_bundle)
     55         pack = root / "inputs"
     56         captured = run("provenance", "capture", "--file", entry, "--store", store,
     57                        "--toolchain", compiler, "--tool-store", tools, "--output", pack)
     58         pin = re.search(r"Retained build inputs: ([0-9a-f]{64})", captured)[1]
     59         run("provenance", "rebuild", "--pack", pack, "--pin", pin,
     60             "--trust-compiler", compiler, "--output", project / "replayed")
     61         # Cache must observe source edits, not just declaration paths.
     62         (lib / "numbers-source.tri").write_text("!export answer\nanswer = 7\n")
     63         assert run("eval", entry, "--store", store, "--format", "number").strip() == "7"
     64         # Ordinary compiler controls remain in force through the mapped route.
     65         (lib / "numbers-source.tri").write_text("!import facade as F\n!export answer\nanswer = F.answer\n")
     66         run("eval", entry, "--store", store, success=False)
     67         (lib / "numbers-source.tri").write_text("!import absent as A\n!export answer\nanswer = A.answer\n")
     68         run("eval", entry, "--store", store, success=False)
     69         (app / "facade.tri").write_text("!export answer\nanswer = 99\n")
     70         run("eval", entry, "--store", store, success=False)
     71     print("workspace compile acceptance passed")
     72 
     73 
     74 if __name__ == "__main__":
     75     main()