tree-session.mjs (1867B)
1 // Private implementation shared by today's two tree adapters, not a requirement 2 // on other backends. Runtime handles and checkpoints never leave this closure. 3 import {compiledDefinitions} from '../demo-site/dist/compiler.js'; 4 export function treeSession(g, root, adapter) { 5 let definitions=new Map(), disposed=false; 6 const active=()=>{if(disposed)throw new Error('Session disposed');}; 7 const definition=name=>{const h=definitions.get(name);if(h===undefined)throw new Error('Missing definition');return h;}; 8 const scoped=fn=>{active();return adapter.scope(fn);}; 9 return { 10 runText(value) {return scoped(()=>adapter.toText(g.app(root,adapter.ofText(value))));}, 11 compile(source) { 12 const next=scoped(({keep})=>{ 13 const input=adapter.ofText(source,16384); 14 const defs=compiledDefinitions(g,g.apply(root,[g.leaf,input])); 15 for(const h of defs.values())keep(h); 16 return defs; 17 }); 18 for(const h of definitions.values())adapter.release(h); 19 definitions=next; 20 return [...definitions.keys()]; 21 }, 22 inspect(name,args) {return scoped(()=>g.toTernary(g.apply(definition(name),args.map(x=>g.fromTernary(x)))));}, 23 preview(name,limit) {active();return g.preview(definition(name),limit);}, 24 // Bounded tree inputs are a harness operation, not source compilation. 25 // Worker termination is the deadline for divergent evaluation. 26 runTree(program,args) {return scoped(()=>{ 27 const applied=g.apply(g.fromTernary(program),args.map(x=>g.fromTernary(x))); 28 return g.toTernary(g.force(applied,0x7fffffffffffffffn)); 29 });}, 30 collect() {active();adapter.collect([root,...definitions.values()]);}, 31 stats() {active();return adapter.stats();}, 32 dispose() {if(disposed)return;disposed=true;definitions.clear();try{adapter.dispose();}finally{g=undefined;adapter=undefined;}}, 33 }; 34 }