tricu

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

tree-result.js (2628B)


      1 import { exportTree } from './tree-export.js';
      2 export const RESULT_NODE_LIMIT = 100_000;
      3 export function isTreeResult(value) {
      4     return ['tricu', 'triangle', 'dag', 'ternary'].includes(value);
      5 }
      6 // Backend snapshots describe physical sharing, not structural hash-consing.
      7 // Reject incomplete/cyclic observations instead of exporting a plausible prefix.
      8 export function snapshotBundle(snapshot) {
      9     if (snapshot.truncated)
     10         throw new Error('Result snapshot exceeds 100,000 nodes; refusing a partial export');
     11     const aliases = new Map(snapshot.aliases.map(a => [a.from, a.to]));
     12     const byId = new Map(snapshot.nodes.map(n => [n.id, n]));
     13     const resolve = (raw) => {
     14         let id = raw;
     15         const seen = new Set();
     16         while (aliases.has(id)) {
     17             if (seen.has(id))
     18                 throw new Error('Snapshot alias cycle');
     19             seen.add(id);
     20             id = aliases.get(id);
     21         }
     22         return id;
     23     };
     24     const nodes = [], mapped = new Map(), active = new Set();
     25     const root = resolve(snapshot.root), stack = [[root, false]];
     26     while (stack.length) {
     27         const [raw, leave] = stack.pop(), id = resolve(raw);
     28         if (mapped.has(id))
     29             continue;
     30         const node = byId.get(id);
     31         if (!node)
     32             throw new Error('Incomplete result snapshot');
     33         const arity = { leaf: 0, stem: 1, fork: 2 }[node.kind];
     34         if (arity === undefined || node.children.length !== arity)
     35             throw new Error('Invalid snapshot constructor');
     36         if (!leave) {
     37             if (active.has(id))
     38                 throw new Error('Cyclic result cannot be exported as a DAG');
     39             active.add(id);
     40             stack.push([id, true]);
     41             for (const child of [...node.children].reverse())
     42                 stack.push([child, false]);
     43         }
     44         else {
     45             active.delete(id);
     46             const cs = node.children.map(c => mapped.get(resolve(c)));
     47             if (cs.some(c => c === undefined))
     48                 throw new Error('Invalid result snapshot order');
     49             mapped.set(id, nodes.length);
     50             nodes.push(node.kind === 'leaf' ? { kind: 'leaf' } : node.kind === 'stem' ? { kind: 'stem', child: cs[0] } : { kind: 'fork', left: cs[0], right: cs[1] });
     51         }
     52     }
     53     return { nodes, roots: [mapped.get(root)], exports: [{ name: 'tree', root: mapped.get(root), kind: 'term', abi: 'arboricx.abi.tree.v1' }], metadata: {} };
     54 }
     55 export function treeResult(snapshot, format) {
     56     const file = exportTree(snapshotBundle(snapshot), 'tree', format);
     57     return { type: format, value: file.text, file };
     58 }