native_source_map_fixture.py (4457B)
1 #!/usr/bin/env python3 2 """Focused Haskell-only native nested-map staging/build; no compiler source build.""" 3 import argparse 4 import json 5 import shutil 6 from pathlib import Path 7 import re 8 from research_session import ResearchSession, ROOT 9 10 parser = argparse.ArgumentParser(description=__doc__) 11 parser.add_argument('tricu', type=Path) 12 parser.add_argument('generation', type=Path) 13 parser.add_argument('--directory', type=Path, required=True) 14 args = parser.parse_args() 15 generation = args.generation.resolve() 16 status = json.loads((generation / 'status.json').read_text()) 17 if status.get('produced_io_version', 1) != 2: 18 parser.error('current probe requires a v2 generation; use its frozen probe/runtime for v1') 19 if not status['complete']: 20 raise ValueError('incomplete generation') 21 session = ResearchSession(args.tricu, args.directory, [], generation / 'build-stable.arboricx') 22 source_cas = generation / 'cas' 23 pin = (source_cas / 'cache/source-build/source_map').read_text().split('\t')[2] 24 manifest = (source_cas / 'objects' / pin[:3] / pin).read_bytes() 25 from native_library_migration import digest 26 if digest('arboricx.module-manifest.v1', manifest) != pin: 27 raise ValueError('corrupt map manifest') 28 exports = {line.split('\t')[1]: line.split('\t')[3] for line in manifest.decode().splitlines()[1:]} 29 tree = exports['sourceMapStage'] 30 target = session.store / 'objects' / tree[:3] / tree 31 target.parent.mkdir(parents=True, exist_ok=True) 32 if not target.exists(): shutil.copyfile(source_cas / 'objects' / tree[:3] / tree, target) 33 bundle = session.root / 'stage.arboricx' 34 session.run([session.tricu, 'arboricx', 'export', '--store', session.store, 35 '--target', tree, '--name', 'stage', '--output', bundle]) 36 output, _ = session.run([session.tricu, 'arboricx', 'import', '--store', session.store, 37 '--file', bundle]) 38 module = re.search(rb'Created module alias .* -> ([a-f0-9]{64})', output)[1].decode() 39 overlay = session.root / 'overlay' 40 map_bytes = (ROOT / 'demos/source-map/map.v1').read_text() 41 # Stored IO execution expects the io envelope, not a raw native IO action. 42 io_pin = (source_cas / 'cache/source-build/compiler_io').read_text().split('\t')[2] 43 io_payload = (source_cas / 'objects' / io_pin[:3] / io_pin).read_bytes() 44 if digest('arboricx.module-manifest.v1', io_payload) != io_pin: 45 raise ValueError('corrupt io manifest') 46 for pin in {io_pin, *[line.split('\t')[3] for line in io_payload.decode().splitlines()[1:]]}: 47 target = session.store / 'objects' / pin[:3] / pin 48 target.parent.mkdir(parents=True, exist_ok=True) 49 if not target.exists(): shutil.copyfile(source_cas / 'objects' / pin[:3] / pin, target) 50 driver = session.workspace / 'stage_driver.tri' 51 driver.write_text(f'!import {module} as M\n!import {io_pin} as I\n!export main\n' 52 'main source overlay cas text = I.io (M.stage source overlay cas text)\n') 53 driver_bundle = session.root / 'stage-driver.arboricx' 54 session.compile(driver, ['main'], driver_bundle) 55 output, _ = session.run([session.tricu, 'arboricx', 'import', '--store', session.store, 56 '--file', driver_bundle, '--indexed']) 57 module = re.search(rb'Created module alias .* -> ([a-f0-9]{64})', output)[1].decode() 58 session.run([session.tricu, 'arboricx', 'run', '--store', session.store, '--module', module, 59 '--name', 'main', '--arg', str(ROOT), '--arg', str(overlay), '--arg', str(session.store), 60 '--arg', map_bytes, '--io', '--format', 'decode']) 61 for name, path in [('base', 'demos/source-map/base.tri'), 62 ('prelude', 'demos/source-map/nested/prelude.tri'), 63 ('app', 'demos/source-map/nested/app.tri')]: 64 staged = (overlay / (name + '.tri')).read_bytes() 65 assert staged == (ROOT / path).read_bytes(), (name, 'native staging changed bytes') 66 (session.workspace / (name + '.tri')).write_bytes(staged) 67 app = session.root / 'app.arboricx' 68 session.compile(session.workspace / 'app.tri', ['main'], app) 69 output, _ = session.run([session.tricu, 'arboricx', 'import', '--store', session.store, 70 '--file', app, '--indexed']) 71 module = re.search(rb'Created module alias .* -> ([a-f0-9]{64})', output)[1].decode() 72 output, _ = session.run([session.tricu, 'arboricx', 'run', '--store', session.store, 73 '--module', module, '--name', 'main', '--format', 'number']) 74 assert output == b'42', output 75 print('Native nested map: exact staging bytes; portable main = 42; Haskell only')