tricu

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

ascii_classifiers.py (3650B)


      1 #!/usr/bin/env python3
      2 """Compile current native_math and independently check complete ASCII predicates.
      3 
      4 No reused library dependencies; the packaged stable compiler is authenticated.
      5 This focused source check does not publish or accept a compiler generation.
      6 """
      7 import argparse
      8 import hashlib
      9 import json
     10 from pathlib import Path
     11 import subprocess
     12 
     13 from bundle_dag import merge_bundles
     14 from pattern_lowering import audit
     15 from shipped_compiler import verify as verify_compiler
     16 
     17 ROOT = Path(__file__).resolve().parent.parent
     18 
     19 
     20 def main():
     21     parser = argparse.ArgumentParser(description=__doc__)
     22     parser.add_argument('tricu', type=Path)
     23     parser.add_argument('--directory', type=Path, required=True)
     24     args = parser.parse_args()
     25     root = args.directory.resolve()
     26     root.mkdir(parents=True, exist_ok=False)
     27     workspace = root / 'workspace'
     28     workspace.mkdir()
     29     (workspace / 'tricu.workspace').write_text('tricu.workspace.v1\n')
     30     host = args.tricu.resolve()
     31     compiler = verify_compiler()
     32     source = (ROOT / 'lib/math/native.tri').read_bytes()
     33     (workspace / 'native_math.tri').write_bytes(source)
     34     report = dict(complete=False, compiler_sha256=compiler['sha256'],
     35                   runtime_sha256=hashlib.sha256(host.read_bytes()).hexdigest(),
     36                   source_sha256=hashlib.sha256(source).hexdigest(), commands=[])
     37 
     38     def command(argv, timeout=180, rejection=False):
     39         cmd = list(map(str, argv))
     40         out = subprocess.run(cmd, cwd=ROOT, capture_output=True, text=True, timeout=timeout)
     41         report['commands'].append(dict(argv=cmd, code=out.returncode,
     42                                        stdout=out.stdout, stderr=out.stderr))
     43         (root / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
     44         if rejection:
     45             assert out.returncode != 0 and 'classifier mismatch' in out.stderr, out
     46         elif out.returncode:
     47             raise RuntimeError(out.stdout[-4000:] + out.stderr[-4000:])
     48 
     49     candidate = root / 'native_math.arboricx'
     50     command([host, 'arboricx', 'compile', '--file', workspace / 'native_math.tri',
     51              '--store', root / 'store', '--output', candidate, '--compile-timeout', '150',
     52              '+RTS', '-N1', '-M4096m', '-RTS'])
     53     report['modules'] = audit(workspace, root / 'store', compiler['sha256'], {})
     54     expr = ('let f=builtins.getFlake "git+file://' + str(ROOT) + '";'
     55             'p=f.inputs.nixpkgs.legacyPackages.x86_64-linux;'
     56             'in p.haskellPackages.ghcWithPackages(h:[h.cryptonite h.memory h.base16-bytestring h.vector])')
     57     command(['nix', 'shell', '--impure', '--expr', expr, '--command', 'ghc', '-O2', '-rtsopts',
     58              '-XOverloadedStrings', '-XLambdaCase', '-XMultiWayIf', '-XScopedTypeVariables',
     59              '-isrc', '-outputdir', root / 'objects', ROOT / 'test/AsciiClassifiers.hs',
     60              '-o', root / 'controls'], 300)
     61     command([root / 'controls', candidate, '+RTS', '-M2048m', '-RTS'])
     62     wrong = root / 'wrong.arboricx'
     63     merge_bundles(wrong, [(candidate, [('letter', 'digit'), ('letter', 'letter'),
     64                                       ('lowerHex', 'lowerHex')])], prune_unreachable=True)
     65     command([root / 'controls', wrong, '+RTS', '-M2048m', '-RTS'], rejection=True)
     66     report.update(complete=True, wrong_subject_rejected=True,
     67                   controls_sha256=hashlib.sha256((ROOT / 'test/AsciiClassifiers.hs').read_bytes()).hexdigest())
     68     (root / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
     69     print('PASS ASCII classifiers: canonical naturals, complete Booleans, wrong-subject and provenance controls')
     70 
     71 
     72 if __name__ == '__main__':
     73     main()