tricu

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

live-ux-probe.mjs (5084B)


      1 import {el,input,change,status,wait,pause,inspect,result,card} from './source-probe-helpers.mjs';
      2 const assert=(condition,message)=>{if(!condition)throw Error(message);};
      3 export async function run(control,backend='haskell-wasm'){
      4  await status('Ready');
      5  change('program-picker','demo:language-reference');await status('Ready');assert(await inspect('answer','number')==='42','Initial published value');
      6  const NativeWorker=globalThis.Worker,held=[],submitted=[];let hold=true;
      7  // Delay real native replies to make late-completion ordering deterministic.
      8  globalThis.Worker=class extends NativeWorker{
      9   postMessage(message,...args){if(message.type==='compile')submitted.push(message.source);super.postMessage(message,...args);}
     10   set onmessage(handler){super.onmessage=event=>{if(hold&&['compiled','error'].includes(event.data.type))held.push(()=>handler(event));else handler(event);};}
     11  };
     12  try{
     13   const original=globalThis.__sourceEditor.getSource();
     14   input('source-editor',original.replace('first 42 7','first 43 7'));
     15   assert(card().querySelector('select').disabled&&result()==='','Edits invalidate old inline output immediately');
     16   await status('Compiling');assert(!globalThis.__sourceEditor.isDisabled,'Editing continues during compilation');
     17   input('source-editor',original.replace('first 42 7','first 44 7'));input('source-editor',original.replace('first 42 7','first 45 7'));
     18   await wait(()=>held.length>0,'held compilation');assert(submitted.length===1,'Keystrokes do not restart current compile');
     19   hold=false;held.shift()();await status('Compiled');assert(submitted.length===2&&submitted[1].includes('first 45 7'),'Only newest queued revision compiles');
     20   assert(await inspect('answer','number')==='45','No stale compiled value');
     21   hold=true;input('source-editor','answer = missingStaleName');await wait(()=>held.length>0,'held diagnostic');input('source-editor','answer = 45');
     22   hold=false;held.shift()();await status('Compiled');assert(el('compile-diagnostic').hidden,'Stale diagnostics discarded');
     23   input('source-editor','answer = missingLatestName');await status('Compilation failed');assert(!el('compile-diagnostic').hidden&&card().querySelector('select').disabled&&result()==='','Latest diagnostic invalidates old inspection');
     24   input('source-editor','identity value = value\nanswer =\n  identity\n  46');await status('Compiled');assert(await inspect('answer','number')==='46','Indented continuation');
     25   el('stop').click();el('compile').click();await status('Compiled');assert(await inspect('answer','number')==='46','Runtime restart rebuilds source');
     26   el('stop').click();el('compile').click();await status('Compiled');
     27   input('source-editor','answer = 47');el('stop').click();await pause(900);assert(el('status').textContent==='Stopped','Stop suppresses queued compilation');
     28   input('source-editor','answer = 48');await status('Compiled');assert(await inspect('answer','number')==='48','Source edits recover after Stop');
     29   el('source-editor').dispatchEvent(new CompositionEvent('compositionstart'));input('source-editor','answer = 49');await pause(900);assert(el('status').textContent==='Changes pending','IME does not compile mid-composition');
     30   el('source-editor').dispatchEvent(new CompositionEvent('compositionend'));await status('Compiled');assert(await inspect('answer','number')==='49','IME completion compiles');
     31   input('source-editor','answer = 50');change('program-picker','demo:language-reference');await status('Ready');await pause(900);assert(el('status').textContent==='Ready','Package change cancels queued compilation');
     32   document.querySelector('[data-compiler-example=input]').click();await status('Compiled');assert(!el('input-form')&&el('terminal-io').textContent==='','Compilation never runs IO');
     33   await inspect('io');assert(!el('terminal-io').querySelector('form'),'Recognition never runs IO');el('io-return-format').value='string';el('run-io').click();await wait(()=>el('terminal-io').querySelector('form input'),'structured input');
     34   assert(globalThis.__sourceEditor.isDisabled&&el('reset').disabled,'Active IO cannot be replaced by background edits or Clear');el('terminal-io').querySelector('form input').value='hello λ🙂';el('terminal-io').querySelector('form').requestSubmit();await status('Finished');assert(result()==='hello λ🙂','Inline IO return');
     35   input('source-editor','id x = x\nanswer = id 51\nbomb = (x : x x) (x : x x)');await status('Compiled');assert(await inspect('answer','number')==='51','Unused divergent binding is not forced');
     36   document.querySelector('[aria-label="Inspect compiled definition bomb"]').click();await wait(()=>el('status').textContent==='Inspecting bomb','divergent observation');await pause(150);el('stop').click();await status('Stopped');
     37  }finally{globalThis.Worker=NativeWorker;}
     38  return {userAgent:navigator.userAgent,backend,checks:['real native delayed completion; revision invalidation; stale-error rejection; compile coalescing; editable compilation; Stop suppresses queued work; IME; runtime rebuilding; no implicit IO; unused divergence; CPU-bound Stop']};
     39 }