tricu

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

auto-interpretation.test.mjs (3803B)


      1 import test from 'node:test';
      2 import assert from 'node:assert/strict';
      3 import {Graph} from '../dist/graph.js';
      4 import {makeLiteral,readableText,valueText,view,outputType,natural,list,DECODED_LIST_LIMIT} from '../dist/codecs.js';
      5 import {autoInterpretation} from '../dist/auto-interpretation.js';
      6 const n=value=>({type:'number',value:String(value)}),s=value=>({type:'string',value});
      7 const auto=literal=>{const g=new Graph(),h=makeLiteral(g,literal);return autoInterpretation(type=>Promise.resolve(view(g,h,type)),()=>false);};
      8 test('Auto chooses readable text, naturals, decoded lists, Boolean and source',async()=>{
      9  for(const text of ['hello','ฮป้›ช๐Ÿ™‚','a\nb\t','๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ'])assert.deepEqual(await auto(s(text)),{type:'string',value:text});
     10  assert.deepEqual(await auto(n(42)),{type:'number',value:'42'});
     11  assert.deepEqual(await auto(s('')),{type:'number',value:'0'});
     12  assert.deepEqual(await auto({type:'bool',value:false}),{type:'number',value:'0'});
     13  assert.deepEqual(await auto({type:'bool',value:true}),{type:'bool',value:true});
     14  assert.deepEqual(await auto({type:'list',value:[s('hello'),n(42),n(2n**100n),s('')]}),{type:'values',value:[s('hello'),n(42),n(2n**100n),n(0)]});
     15  const bytes=Array(33).fill(128);assert.deepEqual(await auto({type:'bytes',value:bytes}),{type:'values',value:bytes.map(n)});
     16  assert.equal((await auto({type:'tree',value:'21100'})).type,'tricu');
     17 });
     18 test('readability is a preference, not a claim about types; explicit Text stays available',async()=>{
     19  for(const text of ['', '\0', '\x01', '\u202e', '\ue000','\u0378'])assert.equal(readableText(text),false,JSON.stringify(text));
     20  // The same list admits Unicode, byte and number-list views. Prefer readable text.
     21  assert.deepEqual(await auto({type:'list',value:[n(65),n(66)]}),{type:'string',value:'AB'});
     22  const g=new Graph(),h=makeLiteral(g,s('\0'));assert.deepEqual(view(g,h,'string'),s('\0'));
     23  assert.notEqual((await auto(s('\0'))).type,'string');
     24 });
     25 test('decoded lists preserve large natural values and fail closed on unsupported items/bounds',()=>{
     26  const g=new Graph();
     27  const h=makeLiteral(g,{type:'list',value:[s('a'),n(2n**100n)]});
     28  assert.equal(valueText(view(g,h,'values')),`["a" ${2n**100n}]`);
     29  assert.throws(()=>view(g,makeLiteral(g,{type:'list',value:[{type:'bool',value:true}]}),'values'),/number/);
     30  const boundary=list(g,Array(DECODED_LIST_LIMIT).fill(natural(g,42n)));
     31  assert.equal(view(g,boundary,'values').value.length,4096);
     32  assert.throws(()=>view(g,g.fork(g.leaf,boundary),'values'),/limit/);
     33  assert.throws(()=>view(g,boundary,'list'),/limit/); // Tiny graph previews stay bounded.
     34  assert.throws(()=>view(g,list(g,[list(g,Array(4097).fill(natural(g,65n)))]),'values'),/number bit/);
     35  assert.throws(()=>outputType('record'),/Unsupported/);
     36 });
     37 test('Auto stops on fatal errors, falls back once, and does not hide a failed tree observation',async()=>{
     38  const calls=[],fatal=Error('disposed');
     39  await assert.rejects(autoInterpretation(async type=>{calls.push(type);throw fatal;},()=>true),/disposed/);
     40  assert.deepEqual(calls,['string']);
     41  const attempted=[];
     42  await assert.rejects(autoInterpretation(async type=>{attempted.push(type);throw Error('observation failed');},()=>false),/observation failed/);
     43  assert.deepEqual(attempted,['string','number','values','bool','bytes','tricu']);
     44 });
     45 
     46 test('100 mixed FizzBuzz results decode explicitly and through Auto',async()=>{
     47  const expected=Array.from({length:100},(_,i)=>{const n=i+1;return n%15===0?s('fizzbuzz'):n%5===0?s('buzz'):n%3===0?s('fizz'):{type:'number',value:String(n)};});
     48  const literal={type:'list',value:expected},g=new Graph(),root=makeLiteral(g,literal);
     49  assert.deepEqual(view(g,root,'values'),{type:'values',value:expected});
     50  assert.deepEqual(await auto(literal),{type:'values',value:expected});
     51 });