tricu

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

prepare-compiler.mjs (3227B)


      1 // Trusted benchmark transport only. Authenticate and validate the site's bundle
      2 // before converting to a compact DAG; this is not a public bundle loader.
      3 import {readFile, writeFile, mkdir} from 'node:fs/promises';
      4 import {createHash} from 'node:crypto';
      5 import assert from 'node:assert/strict';
      6 import {pathToFileURL} from 'node:url';
      7 import path from 'node:path';
      8 const [site, output] = process.argv.slice(2);
      9 const {decodeBundle, COMPILER_BUNDLE_LIMIT} = await import(pathToFileURL(path.resolve(site,'dist/bundle.js')));
     10 const {CONTRACT_BINDINGS} = await import(pathToFileURL(path.resolve(site,'dist/contracts.js')));
     11 const descriptor = JSON.parse(await readFile(path.join(site,'compiler.json')));
     12 const vectors = JSON.parse(await readFile(path.join(site,'test/compiler-conformance.json')));
     13 const bytes = await readFile(path.join(site,'bundles',descriptor.hash+'.arboricx'));
     14 assert.equal(createHash('sha256').update(bytes).digest('hex'), descriptor.hash);
     15 assert.equal(descriptor.hash,vectors.compilerBundleSha256);
     16 assert.equal(descriptor.export,vectors.export);
     17 const bundle = decodeBundle(bytes,COMPILER_BUNDLE_LIMIT);
     18 const exports = new Map(bundle.exports.map(e=>[e.name,e.root]));
     19 const root = exports.get(descriptor.export); assert.notEqual(root,undefined);
     20 for (const name of ['sourceModuleHeaderStage','sourceModuleUseShape','sourceModuleExportShape','sourceModuleQualified']) {
     21   assert.ok(exports.has('source_module.'+name), 'Missing native module compiler helper: '+name);
     22 }
     23 await mkdir(output,{recursive:true});
     24 const dag = Buffer.alloc(8+bundle.nodes.length*9);
     25 dag.writeUInt32LE(bundle.nodes.length,0); dag.writeUInt32LE(root,4);
     26 for (const [i,n] of bundle.nodes.entries()) {
     27   const at=8+i*9;
     28   dag[at]=n.kind==='leaf'?0:n.kind==='stem'?1:2;
     29   dag.writeUInt32LE(n.kind==='stem'?n.child:n.kind==='fork'?n.left:0,at+1);
     30   dag.writeUInt32LE(n.kind==='fork'?n.right:0,at+5);
     31 }
     32 await writeFile(path.join(output,'compiler.dag'),dag);
     33 await writeFile(path.join(output,'compiler-exports.tsv'), [...exports].map(([name,root])=>`${name}\t${root}`).join('\n')+'\n');
     34 await writeFile(path.join(output,'environment.tsv'),Object.entries(CONTRACT_BINDINGS).map(([name,exported])=>{
     35   assert.ok(exports.has(exported)); return name+'\t'+exports.get(exported);
     36 }).join('\n')+'\n');
     37 const cases=[];
     38 for (const [id,c] of vectors.cases.entries()) {
     39   if(c.mode==='io')continue; // IO is a separate host-driver experiment.
     40   const dir=path.join(output,String(id)); await mkdir(dir);
     41   await writeFile(path.join(dir,'source'),c.source);
     42   await writeFile(path.join(dir,'expected'),c.diagnostic ? 'error\n'+c.diagnostic+'\n' :
     43     'ok\n'+Object.entries(c.definitions).map(([name,tree])=>name+'\t'+tree).join('\n')+'\n');
     44   await writeFile(path.join(dir,'run'),c.diagnostic?'': [c.export,c.result,...c.arguments].join('\n')+'\n');
     45   cases.push({id,source:c.source,diagnostic:c.diagnostic??null,extended:c.extended??false});
     46 }
     47 await writeFile(path.join(output,'manifest.json'),JSON.stringify({compilerSha256:descriptor.hash,
     48   goldenSha256:createHash('sha256').update(await readFile(path.join(site,'test/compiler-conformance.json'))).digest('hex'),
     49   dagSha256:createHash('sha256').update(dag).digest('hex'),cases},null,2)+'\n');