tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

binding_stable_integration.py (5063B)


      1 #!/usr/bin/env python3
      2 """Build the source-owned stable binding pass and screen a self-rebuild.
      3 
      4 This is artifact preparation/testing, NOT an accepted compiler generation pair.
      5 Only the stable source candidate changes; shipped bundles and generation selection stay pinned.
      6 """
      7 import argparse,hashlib,json,time
      8 from pathlib import Path
      9 from bootstrap_generations import source_map
     10 from binding_substitution import ROOT,tree_bytes
     11 from bundle_dag import read,Intern
     12 from float_multiply import Runner,sha
     13 
     14 
     15 def main():
     16     p=argparse.ArgumentParser(description=__doc__)
     17     p.add_argument('tricu',type=Path);p.add_argument('--directory',type=Path,required=True)
     18     args=p.parse_args();root=args.directory.resolve()
     19     mapping=ROOT/'bootstrap/compiler-source-map.v1'
     20     text,entries,required=source_map(mapping,ROOT,'source_build')
     21     meta=json.loads((ROOT/'bootstrap/stable-compiler.json').read_text())
     22     assert sha(ROOT/meta['bundle'])==meta['sha256']
     23     for row in meta['sources']:
     24         if row['alias']!='source_stable':assert sha(ROOT/row['path'])==row['sha256'],('unexpected-source-drift',row['path'])
     25     certificates=json.loads((ROOT/'bootstrap/binding-certificates.json').read_text())
     26     assert sha(ROOT/certificates['source'])==certificates['source_sha256']
     27     root.mkdir(parents=True,exist_ok=False);workspace=root/'workspace';workspace.mkdir()
     28     for alias,(_,path,_) in entries.items():(workspace/(alias+'.tri')).write_bytes((ROOT/path).read_bytes())
     29     (root/'source-map.v1').write_text(text)
     30     (workspace/'driver.tri').write_text('!import source_build as B\n!export sourceBuildGraph\nsourceBuildGraph = B.sourceBuildGraphStable\n')
     31     runner=Runner(args.tricu,root,1800,memory_mib=8192)
     32     report=dict(complete=False,accepted=False,generation_pair=False,backend='stable',
     33                 profile='source-module.stable.v1',harness_sha256=sha(Path(__file__)),
     34                 runtime_sha256=sha(args.tricu),accepted_compiler_sha256=meta['sha256'],map_sha256=sha(mapping),
     35                 certificate_manifest_sha256=sha(ROOT/'bootstrap/binding-certificates.json'),
     36                 sources={alias:sha(workspace/(alias+'.tri')) for alias in entries},stages=[])
     37     try:
     38         tool=runner.imported(ROOT/meta['bundle'],'accepted')
     39         for stage in range(2):
     40             store=root/f'stage-{stage}-store';bundle=root/f'stage-{stage}.arboricx';start=time.monotonic()
     41             runner.run(f'build-{stage}',['compile','--file',workspace/'driver.tri','--toolchain',tool,
     42                        '--tool-store',runner.store,'--store',store,'--output',bundle,'--compile-timeout','720'],750)
     43             record=dict(stage=stage,selected_compiler=tool,bundle_sha256=sha(bundle),seconds=time.monotonic()-start,
     44                         modules={},certificates={})
     45             report['stages'].append(record)
     46             for alias in ['source_binding_support','source_binding','source_stable','source_unit']:
     47                 manifest=(store/'cache/source-build'/alias).read_text().split('\t')[2]
     48                 out=root/f'stage-{stage}-{alias}.arboricx'
     49                 runner.run(f'export-{stage}-{alias}',['export','--store',store,'--module',manifest,'--output',out])
     50                 record['modules'][alias]=dict(manifest=manifest,bundle_sha256=sha(out))
     51             _,_,nodes,exports,_=read(root/f'stage-{stage}-source_binding_support.arboricx')
     52             for name,contract in certificates['contracts'].items():
     53                 digest=hashlib.sha256(tree_bytes(nodes,exports[name])).hexdigest()
     54                 assert digest==contract['tree_sha256'],('certificate identity changed',stage,name)
     55                 record['certificates'][name]=digest
     56             # Keep original stable lowering, not the old experimental patched
     57             # stable module. Only the separately selected backend uses the pass.
     58             intern=Intern();fixture=read(ROOT/'test/fixtures/compiler-library.arboricx')
     59             stable=read(root/f'stage-{stage}-source_stable.arboricx')
     60             fi=intern.graph(fixture[2]);si=intern.graph(stable[2])
     61             for name,index in stable[3].items():
     62                 if name not in ['stableCompileCore','sourceCompileStableDefinition','sourceCompileStableDefinitionWith']:
     63                     assert si[index]==fi[fixture[3]['source_stable.'+name]],('unexpected stable export change',stage,name)
     64             record['stable_lowering_and_other_exports_unchanged']=True
     65             tool=runner.imported(bundle,f'candidate-{stage}')
     66         report['exact_self_rebuild']=((root/'stage-0.arboricx').read_bytes()==(root/'stage-1.arboricx').read_bytes())
     67         for alias in report['stages'][0]['modules']:
     68             report['stages'][1]['modules'][alias]['same_as_stage_0']=((root/f'stage-0-{alias}.arboricx').read_bytes()==(root/f'stage-1-{alias}.arboricx').read_bytes())
     69         report['complete']=True
     70         print('BUILT stable binding candidate; exact self-rebuild:',report['exact_self_rebuild'])
     71     finally:(root/'report.json').write_text(json.dumps(report,indent=2)+'\n')
     72 
     73 
     74 if __name__=='__main__':main()