tricu

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

source-probe-helpers.mjs (3148B)


      1 // Source edits and definition inspection through the mounted editor.
      2 export const el=id=>document.getElementById(id);
      3 const {editorFor}=await import(new URL('./probe-api.js',document.querySelector('script[type=module][src]').src));
      4 export const sourceEditor=editorFor(el('source-editor'));
      5 globalThis.__sourceEditor=sourceEditor;
      6 export const input=(id,value)=>{if(id==='source-editor'){sourceEditor.replaceSource(value,true);return;}el(id).value=value;el(id).dispatchEvent(new Event('input'));};
      7 export const change=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('change'));};
      8 export const pause=ms=>new Promise(r=>setTimeout(r,ms));
      9 export async function wait(check,label='page state'){
     10  for(let i=0;i<3600;i++){if(check())return;await pause(25);}
     11  throw Error('Timeout '+label+' / '+el('status').textContent+' / '+el('compile-diagnostic').textContent+' / '+el('operation-diagnostic').textContent);
     12 }
     13 export const status=value=>wait(()=>el('status').textContent===value,value);
     14 export const card=()=>document.querySelector('.definition-card');
     15 export const result=()=>card().querySelector('pre').textContent;
     16 export const description=()=>card().querySelector('[role=status]').textContent;
     17 export async function inspect(name,format='auto'){
     18  const title=card().querySelector('.definition-card-controls strong');
     19  if(card().hidden||title.textContent!==name||description().startsWith('Runtime stopped.')){
     20   let button=document.querySelector(`[aria-label="Inspect compiled definition ${name}"]`)
     21    ??[...el('package-definition-list').querySelectorAll('button')].find(button=>button.textContent===name);
     22   if(!button&&!sourceEditor.dom.hidden&&sourceEditor.revealDefinition(name)){await wait(()=>document.querySelector(`[aria-label="Inspect compiled definition ${name}"]`),'visible definition '+name);button=document.querySelector(`[aria-label="Inspect compiled definition ${name}"]`);}
     23   if(!button)throw Error('Missing real definition '+name);button.click();await pause(0);
     24  }
     25  await wait(()=>!card().hidden&&!card().querySelector('select').disabled,'inspect '+name);
     26  const select=card().querySelector('select');
     27  if(select.value!==format){select.value=format;select.dispatchEvent(new Event('change'));await pause(0);await wait(()=>!select.disabled,'interpret '+name);}
     28  return result();
     29 }
     30 export async function evaluateSource(expression,format='number'){
     31  const direct=/^[A-Za-z_][\w?]*$/.test(expression) && (document.querySelector(`[aria-label="Inspect compiled definition ${expression}"]`)
     32   ??[...el('package-definition-list').querySelectorAll('button')].find(button=>button.textContent===expression));
     33  if(/^[A-Za-z_][\w?]*$/.test(expression)&&direct)return inspect(expression,format);
     34  if(el('source-editor').hidden)throw Error('Test must import source-free functions explicitly, not synthesize an evaluator');
     35  const source=sourceEditor.getSource().replace(/\n-- browser probe binding\nprobeResult =[\s\S]*$/,'');
     36  input('source-editor',source+'\n-- browser probe binding\nprobeResult = (\n'+expression.split('\n').map(line=>'  '+line).join('\n')+'\n)');
     37  await status('Compiled');return inspect('probeResult',format);
     38 }