@dallaylaen/ski-interpreter 2.3.2 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- "use strict";(()=>{var k=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports);var Z=k((Ee,pt)=>{var O=class{constructor(...t){let e="$|(\\s+)|"+t.map(s=>"(?:"+s+")").sort((s,n)=>n.length-s.length).join("|");this.rex=new RegExp(e,"gys")}split(t){this.rex.lastIndex=0;let e=[...t.matchAll(this.rex)],n=e.pop()?.index??0;if(n!==t.length)throw new Error("Unknown tokens at pos "+n+"/"+t.length+" starting with "+t.substring(n));return e.filter(r=>r[1]===void 0).map(r=>r[0])}},Vt=new O("[-=+]","[A-Z]","\\b[a-z_][a-z_0-9]*\\b");function Bt(i,t){if(!t)return i;let e=new Set([...i]),s={"=":r=>{e=new Set([r]),n="+"},"+":r=>{e.add(r)},"-":r=>{e.delete(r)}},n="=";for(let r of Vt.split(t))s[r]?n=r:s[n](r);return e}var U=class{constructor(t,e){this.value=t,this.decoration=e}};function Qt(i){return i instanceof U?[i.value??void 0,i.decoration]:[i??void 0,void 0]}function Dt(i){let t=e=>new U(e,t);return t.label=i,t.toString=()=>"TraverseControl::"+i,t}pt.exports={Tokenizer:O,restrict:Bt,unwrap:Qt,prepareWrapper:Dt}});var J=k((qe,wt)=>{"use strict";var{unwrap:y,prepareWrapper:H}=Z(),W={max:1e3,maxArgs:32},Zt={"leftmost-outermost":"LO","leftmost-innermost":"LI",LO:"LO",LI:"LI"},f={descend:H("descend"),prune:H("prune"),redo:H("redo"),stop:H("stop")},T={},g=class i{_setup(t={}){if(t.fancy!==void 0&&(this.fancyName=t.fancyName),t.note!==void 0&&(this.note=t.note),t.arity!==void 0&&(this.arity=t.arity),t.canonize){let e=this.infer(t);e.normal&&(this.arity=this.arity??e.arity,this.note=this.note??e.expr.format({html:!0,lambda:[""," &mapsto; ",""]}),delete e.steps,this.props=e)}return this}apply(...t){let e=this;for(let s of t)e=new x(e,s);return e}expand(){return this.traverse(t=>{if(t instanceof A)return t.impl.expand()})??this}freeOnly(){return!this.any(t=>!(t instanceof v||t instanceof x))}traverse(t,e){typeof t=="function"&&(e=t,t={});let s=Zt[t.order??"LO"];if(s===void 0)throw new Error("Unknown traversal order: "+t.order);let[n,r]=y(this._traverse_redo({order:s},e));return n}_traverse_redo(t,e){let s,n=this,r;do{r=n;let o=t.order==="LI"?n._traverse_descend(t,e)??e(n):e(n)??n._traverse_descend(t,e);[n,s]=y(o)}while(n&&s===f.redo);return!n&&r!==this&&(n=r),s?s(n):n}_traverse_descend(t,e){return null}any(t){return t(this)}fold(t,e){let[s,n]=y(this._fold(t,e));return s??t}_fold(t,e){return e(t,this)}weight(){return 1}infer(t={}){return this._infer({max:t.max??W.max,maxArgs:t.maxArgs??W.maxArgs},0)}_infer(t,e){let s=[],n=0,r=this;t:for(let o=0;o<t.maxArgs;o++){let a=r.run({max:t.max-n});if(n+=a.steps,!a.final)break;if(Jt(a.expr)){if(r=a.expr,!r.any(l=>!(l instanceof v||l instanceof x)))return dt(s,r,{steps:n});let u=r.unroll(),p=!1,w=!1,d=[];for(let l=1;l<u.length;l++){let m=u[l]._infer({maxArgs:t.maxArgs-e,max:t.max-n},e+o);if(n+=m.steps,!m.expr)break t;m.discard&&(p=!0),m.duplicate&&(w=!0),d.push(m.expr)}return dt(s,u[0].apply(...d),{discard:p,duplicate:w,steps:n})}let h=Yt(e+o);s.push(h),r=a.expr.apply(h)}return{normal:!1,proper:!1,steps:n}}unroll(){return[this]}*toLambda(t={}){let e=this.traverse(r=>{if(r instanceof v||r instanceof x||r instanceof b||r instanceof A)return null;let o=r.infer({max:t.max,maxArgs:t.maxArgs});if(!o.normal)throw new Error("Failed to infer an equivalent lambda term for "+r);return o.expr})??this,s=new Set,n=0;for(;e;){let r=e.traverse({order:"LI"},o=>{if(s.has(o))return null;if(o instanceof x&&o.fun instanceof b){let a=o.infer({max:t.max,maxArgs:t.maxArgs});return n+=a.steps,a.normal?f.stop(a.expr):(s.add(o),null)}});yield{expr:e,steps:n},e=r}}*toSKI(t={}){let e=this.traverse(n=>n instanceof v||n instanceof x||n instanceof b||n instanceof A?null:n.infer().expr)??this,s=0;for(;e;){let n=e.traverse({order:"LI"},r=>{if(!(r instanceof b)||r.impl instanceof b)return null;if(r.impl===r.arg)return f.stop(T.I);if(!r.impl.any(o=>o===r.arg))return f.stop(T.K.apply(r.impl));if(!(r.impl instanceof x))throw new Error("toSKI: assert failed: lambda body is of unexpected type "+r.impl.constructor.name);return r.impl.arg===r.arg&&!r.impl.fun.any(o=>o===r.arg)?f.stop(r.impl.fun):f.stop(T.S.apply(new b(r.arg,r.impl.fun),new b(r.arg,r.impl.arg)))});yield{expr:e,steps:s,final:!n},s++,e=n}}subst(t,e){return this===t?e:null}invoke(t){return null}step(){return{expr:this,steps:0,changed:!1}}run(t={},...e){t instanceof i&&(e.unshift(t),t={});let s=e?this.apply(...e):this,n=t.steps??0,r=Math.max(t.max??W.max,1)+n,o=!1;for(;n<r;){let a=s.step();if(!a.changed){o=!0;break}n+=a.steps,s=a.expr}if(t.throw&&!o)throw new Error("Failed to compute expression in "+r+" steps");return{final:o,steps:n,expr:s}}*walk(t={}){let e=t.max??1/0,s=0,n=this,r=!1;for(;s<e;){let o=n.step();if(o.changed||(r=!0),yield{expr:n,steps:s,final:r},r)break;s+=o.steps,n=o.expr}}equals(t){return!this.diff(t)}diff(t,e=!1){return this===t?null:t instanceof A?t.impl.diff(this,!e):e?"["+t+" != "+this+"]":"["+this+" != "+t+"]"}expect(t,e=""){if(e=e?e+": ":"",!(t instanceof i))throw new Error(e+"Expected a combinator but found "+(t?.constructor?.name??typeof t));let s=this.diff(t);if(!s)return;let n=new Error(e+s);throw n.expected=this.diag(),n.actual=t.diag(),n}toString(){return this.format()}_braced(t){return!1}_unspaced(t){return this._braced(!0)}format(t={}){let e=t.html?{brackets:["(",")"],space:" ",var:["<var>","</var>"],lambda:["","-&gt;",""],around:["",""],redex:["",""]}:{brackets:["(",")"],space:" ",var:["",""],lambda:["","->",""],around:["",""],redex:["",""]};return this._format({terse:t.terse??!0,brackets:t.brackets??e.brackets,space:t.space??e.space,var:t.var??e.var,lambda:t.lambda??e.lambda,around:t.around??e.around,redex:t.redex??e.redex,inventory:t.inventory,html:t.html??!1},0)}_format(t,e){throw new Error("No _format() method defined in class "+this.constructor.name)}diag(){let t=(s,n)=>s instanceof x?[n+"App:",...s.unroll().flatMap(r=>t(r,n+" "))]:s instanceof b?[`${n}Lambda (${s.arg}[${s.arg.id}]):`,...t(s.impl,n+" ")]:s instanceof A?[`${n}Alias (${s.name}): \\`,...t(s.impl,n)]:s instanceof v?[`${n}FreeVar: ${s.name}[${s.id}]`]:[`${n}${s.constructor.name}: ${s}`];return t(this,"").join(`
2
- `)}toJSON(){return this.format()}},x=class i extends g{constructor(t,e){super(),this.arg=e,this.fun=t}weight(){return this.fun.weight()+this.arg.weight()}_traverse_descend(t,e){let[s,n]=y(this.fun._traverse_redo(t,e));if(n===f.stop)return f.stop(s?s.apply(this.arg):null);let[r,o]=y(this.arg._traverse_redo(t,e)),a=s||r?(s??this.fun).apply(r??this.arg):null;return o===f.stop?f.stop(a):a}any(t){return t(this)||this.fun.any(t)||this.arg.any(t)}_fold(t,e){let[s=t,n="descend"]=y(e(t,this));if(n===f.prune)return s;if(n===f.stop)return f.stop(s);let[r=s,o="descend"]=y(this.fun._fold(s,e));if(o===f.stop)return f.stop(r);let[a=r,h="descend"]=y(this.arg._fold(r,e));return h===f.stop?f.stop(a):a}subst(t,e){let s=this.fun.subst(t,e),n=this.arg.subst(t,e);return s||n?(s??this.fun).apply(n??this.arg):null}step(){if(!this.final){let t=this.fun.invoke(this.arg);if(t instanceof g)return{expr:t,steps:1,changed:!0};typeof t=="function"&&(this.invoke=t);let e=this.fun.step();if(e.changed)return{expr:e.expr.apply(this.arg),steps:e.steps,changed:!0};let s=this.arg.step();if(s.changed)return{expr:this.fun.apply(s.expr),steps:s.steps,changed:!0};this.final=!0}return{expr:this,steps:0,changed:!1}}invoke(t){let e=this.fun.invoke(this.arg);return e instanceof g?e.apply(t):typeof e=="function"?(this.invoke=e,e(t)):(this.invoke=s=>null,null)}unroll(){return[...this.fun.unroll(),this.arg]}diff(t,e=!1){if(!(t instanceof i))return super.diff(t,e);let s=this.fun.diff(t.fun,e);if(s)return s+"(...)";let n=this.arg.diff(t.arg,e);return n?this.fun+"("+n+")":null}_braced(t){return!t}_format(t,e){let s=this.fun._format(t,e+1),n=this.arg._format(t,0),r=e?["",""]:t.around;return t.terse&&!this.arg._braced(!1)?r[0]+s+(this.fun._unspaced(this.arg)?"":t.space)+n+r[1]:r[0]+s+t.brackets[0]+n+t.brackets[1]+r[1]}_unspaced(t){return this.arg._braced(!1)?!0:this.arg._unspaced(t)}},E=class i extends g{constructor(t){if(super(),typeof t!="string"||t.length===0)throw new Error("Attempt to create a named term with improper name");this.name=t}_unspaced(t){return!!(t instanceof i&&(this.name.match(/^[A-Z+]$/)&&t.name.match(/^[a-z+]/i)||this.name.match(/^[a-z+]/i)&&t.name.match(/^[A-Z+]$/)))}_format(t,e){let s=t.html?this.fancyName??this.name:this.name;return this.arity>0&&this.arity<=e?t.redex[0]+s+t.redex[1]:s}},Wt=0,v=class i extends E{constructor(t,e){super(t),this.id=++Wt,this.scope=e===void 0?this:e}weight(){return 0}diff(t,e=!1){if(!(t instanceof i))return super.diff(t,e);if(this.name===t.name&&this.scope===t.scope)return null;let s=this.name+"["+this.id+"]",n=t.name+"["+t.id+"]";return e?"["+n+" != "+s+"]":"["+s+" != "+n+"]"}subst(t,e){return t instanceof i&&t.name===this.name&&t.scope===this.scope?e:null}_format(t,e){let s=t.html?this.fancyName??this.name:this.name;return t.var[0]+s+t.var[1]}};v.global=["global"];var K=class extends E{constructor(t,e,s={}){super(t),this.invoke=e,this._setup({canonize:!0,...s})}},b=class i extends g{constructor(t,e){if(Array.isArray(t)){if(t.length===0)throw new Error("empty argument list in lambda constructor");let[n,...r]=t,o=new Set([n.name]);for(;r.length>0;){let a=r.pop();if(o.has(a.name))throw new Error("Duplicate free var name "+a+" in lambda expression");o.add(a.name),e=new i(a,e)}t=n}super();let s=new v(t.name,this);this.arg=s,this.impl=e.subst(t,s)??e,this.arity=1}weight(){return this.impl.weight()+1}invoke(t){return this.impl.subst(this.arg,t)??this.impl}_traverse_descend(t,e){let[s,n]=y(this.impl._traverse_redo(t,e)),r=s?new i(this.arg,s):null;return n===f.stop?f.stop(r):r}any(t){return t(this)||this.impl.any(t)}_fold(t,e){let[s=t,n="descend"]=y(e(t,this));if(n===f.prune)return s;if(n===f.stop)return f.stop(s);let[r,o]=y(this.impl._fold(s,e));return o===f.stop?f.stop(r):r??s}subst(t,e){if(t===this.arg)return null;let s=this.impl.subst(t,e);return s?new i(this.arg,s):null}diff(t,e=!1){if(!(t instanceof i))return super.diff(t,e);let s=new v("t"),n=this.invoke(s).diff(t.invoke(s),e);return n?"(t->"+n+")":null}_format(t,e){return(e>0?t.brackets[0]:"")+t.lambda[0]+this.arg._format(t,0)+t.lambda[1]+this.impl._format(t,0)+t.lambda[2]+(e>0?t.brackets[1]:"")}_braced(t){return!0}},j=class i extends g{constructor(t){if(t=Number.parseInt(t),!(t>=0))throw new Error("Church number must be a non-negative integer");super(),this.invoke=e=>s=>{let n=s;for(let r=t;r-- >0;)n=e.apply(n);return n},this.n=t,this.arity=2}diff(t,e=!1){return t instanceof i?this.n===t.n?null:e?"["+t.n+" != "+this.n+"]":"["+this.n+" != "+t.n+"]":super.diff(t,e)}_unspaced(t){return!1}_format(t,e){return e>=2?t.redex[0]+this.n+t.redex[1]:this.n+""}};function mt(i,t){return e=>t<=1?i.apply(e):mt(i.apply(e),t-1)}var A=class extends E{constructor(t,e,s={}){if(super(t),!(e instanceof g))throw new Error("Attempt to create an alias for a non-expression: "+e);this.impl=e,this._setup(s),this.terminal=s.terminal??this.props?.proper,this.invoke=mt(e,this.arity??0)}weight(){return this.terminal?1:this.impl.weight()}_traverse_descend(t,e){return this.impl._traverse_redo(t,e)}any(t){return t(this)||this.impl.any(t)}_fold(t,e){let[s=t,n]=y(e(t,this));if(n===f.prune)return s;if(n===f.stop)return f.stop(s);let[r,o]=y(this.impl._fold(s,e));return o===f.stop?f.stop(r):r??s}subst(t,e){return this===t?e:this.impl.subst(t,e)}step(){return this.arity>0?{expr:this,steps:0,changed:!1}:{expr:this.impl,steps:0,changed:!0}}diff(t,e=!1){return this===t?null:t.diff(this.impl,!e)}_braced(t){return this.outdated?this.impl._braced(t):!1}_format(t,e){return(t.inventory?t.inventory[this.name]!==this:this.outdated)?this.impl._format(t,e):super._format(t,e)}};function L(i,t,e){T[i]=new K(i,t,e)}L("I",i=>i);L("K",i=>t=>i);L("S",i=>t=>e=>i.apply(e,t.apply(e)));L("B",i=>t=>e=>i.apply(t.apply(e)));L("C",i=>t=>e=>i.apply(e).apply(t));L("W",i=>t=>i.apply(t).apply(t));L("+",i=>i instanceof j?new j(i.n+1):t=>e=>t.apply(i.apply(t,e)),{note:"Increase a Church numeral argument by 1, otherwise n => f => x => f(n f x)"});function Jt(i){for(;i instanceof x;)i=i.fun;return i instanceof v}function dt(i,t,e={}){let s=new Array(i.length).fill(0),n=!0;t.traverse(a=>{if(a instanceof v){let h=i.findIndex(u=>u.name===a.name);if(h>=0){s[h]++;return}}a instanceof x||(n=!1)});let r=new Set,o=new Set;for(let a=0;a<i.length;a++)s[a]===0?r.add(a):s[a]>1&&o.add(a);return{normal:!0,steps:e.steps,expr:i.length?new b(i,t):t,arity:i.length,...r.size?{skip:r}:{},...o.size?{dup:o}:{},duplicate:!!o.size||e.duplicate||!1,discard:!!r.size||e.discard||!1,proper:n}}function Yt(i){return new v("abcdefgh"[i]??"x"+i)}function Gt(i,t){if(i instanceof g&&(i=[i]),t)i||(i=Object.keys(t).sort().map(r=>t[r]));else{if(!i)return[];if(!t){t={};for(let r of i)if(r instanceof E){if(t[r.name])throw new Error("duplicate name "+r);t[r.name]=r}}}let e=[],s=new Set,n=r=>{s.has(r)||(r.fold(null,(o,a)=>{if(a!==r&&a instanceof E&&t[a.name]===a)return n(a),g.control.prune(null)}),e.push(r),s.add(r))};for(let r of i)n(r);return{list:e,env:t}}g.native=T;g.control=f;g.extras={toposort:Gt};wt.exports={Expr:g,App:x,Named:E,FreeVar:v,Lambda:b,Native:K,Alias:A,Church:j}});var X=k((Ie,yt)=>{"use strict";var{Tokenizer:Xt,restrict:Y}=Z(),vt=J(),{Expr:C,Named:Le,Native:te,Alias:_,FreeVar:I,Lambda:ee,Church:xt}=vt,{native:M}=C,$=class extends C{apply(...t){return t.length?t.shift().apply(...t):this}postParse(){throw new Error("Attempt to use empty expression () as a term")}},G=class i extends ${constructor(t,e={}){if(super(),this.impl=new $,t instanceof I)this.terms=[t];else if(t instanceof i){if(!(t.impl instanceof I))throw new Error("Expected FreeVar->...->FreeVar->Expr");this.terms=[...t.terms,t.impl]}else throw new Error("Expected FreeVar or PartialLambda")}apply(t,...e){if(t===null||e.length!==0)throw new Error("bad syntax in partial lambda expr");return this.impl=this.impl.apply(t),this}postParse(){return new ee(this.terms,this.impl)}};function gt(i){return i.postParse?i.postParse():i}var se=new Xt("[()]","[A-Z]","[a-z_][a-z_0-9]*","\\b[0-9]+\\b","->","\\+"),S=class{constructor(t={}){if(this.annotate=t.annotate??!1,this.known={...M},this.hasNumbers=!0,this.hasLambdas=!0,this.allow=new Set(Object.keys(this.known)),Array.isArray(t.terms))this.bulkAdd(t.terms);else if(t.terms)for(let e in t.terms)t.terms[e].match(/^Native:/)||this.add(e,t.terms[e]);this.hasNumbers=t.numbers??!0,this.hasLambdas=t.lambdas??!0,t.allow&&this.restrict(t.allow)}add(t,e,s){return t=this._named(t,e),typeof s=="string"&&(s={note:s,canonize:!1}),t._setup({canonize:this.annotate,...s}),this.known[t.name]&&(this.known[t.name].outdated=!0),this.known[t.name]=t,this.allow.add(t.name),this}_named(t,e){if(t instanceof _)return new _(t.name,t.impl,{canonize:!0});if(typeof t!="string")throw new Error("add(): term must be an Alias or a string");if(e===void 0)throw new Error("add(): impl must be provided when term is a string");if(typeof e=="string")return new _(t,this.parse(e),{canonize:!0});if(e instanceof C)return new _(t,e,{canonize:!0});if(typeof e=="function")return new te(t,e);throw new Error("add(): impl must be an Expr, a string, or a function with a signature Expr => ... => Expr")}maybeAdd(t,e){return this.known[t]?this.allow.add(t):this.add(t,e),this}bulkAdd(t){for(let e of t){let s=e.match(/^([A-Z]|[a-z][a-z_0-9]*)\s*=\s*(.*)$/s);if(!s)throw new Error("bulkAdd: invalid declaration: "+e);s[2]===""?this.remove(s[1]):this.add(s[1],this.parse(s[2]))}return this}restrict(t){return this.allow=Y(this.allow,t),this}showRestrict(t="+"){let e=[],s=!0;for(let n of[...Y(this.allow,t)].sort()){let r=n.match(/^[A-Z]$/);e.length&&!(s&&r)&&e.push(" "),e.push(n),s=r}return e.join("")}remove(t){return this.known[t].outdated=!0,delete this.known[t],this.allow.delete(t),this}getTerms(){let t={};for(let e of Object.keys(this.known))this.allow.has(e)&&(t[e]=this.known[e]);return t}declare(){let t=this.getTerms();for(let a in t)t[a]instanceof _||delete t[a];let e={},s=1;for(let a in M){if(!(t[a]instanceof _))continue;for(;"tmp"+s in t;)s++;let h=new _("tmp"+s,t[a]);e[h]=t[a],t[h]=h,delete t[a]}let n=C.extras.toposort(void 0,t).list,r=new Map;if(Object.keys(e).length){let a=h=>h.traverse(u=>{if(!(u instanceof _))return null;let p=r.get(u);return p||new _(u.name,a(u.impl))})??h;for(let h=0;h<n.length;h++)n[h]=a(n[h],r),r.set(e[n[h].name],n[h]),t[n[h].name]=n[h],console.log(`list[${h}] = ${n[h].name}=${n[h].impl};`);console.log("detour:",r)}let o=n.map(a=>e[a]?a.name+"="+e[a].name+"="+a.impl.format({inventory:t}):a.name+"="+a.impl.format({inventory:t}));for(let[a,h]of r)o.push(a+"="+h,h+"=");return o}parse(t,e={}){if(typeof t!="string")throw new Error("parse: source must be a string, got "+typeof t);let s=t.replace(/\/\/[^\n]*$/gm," ").replace(/\/\*.*?\*\//gs," ").trim().split(/\s*;[\s;]*/).filter(o=>o.match(/\S/)),n={...e.env},r=new $;for(let o of s){r instanceof _&&(r.outdated=!0);let a=o.match(/^([A-Z]|[a-z][a-z_0-9]*)\s*=(.*)$/s);if(a&&a[2]===""?r=new I(a[1],e.scope??I.global):r=this.parseLine(o,n,e),a){if(n[a[1]]!==void 0)throw new Error("Attempt to redefine a known term: "+a[1]);n[a[1]]=r}}return r.context={env:{...this.getTerms(),...n},scope:e.scope,src:t,parser:this},r}parseLine(t,e={},s={}){let n=t.match(/^\s*([A-Z]|[a-z][a-z_0-9]*)\s*=\s*(.*)$/s);if(n)return new _(n[1],this.parseLine(n[2],e,s));let r={numbers:s.numbers??this.hasNumbers,lambdas:s.lambdas??this.hasLambdas,allow:Y(this.allow,s.allow)};r.numbers?r.allow.add("+"):r.allow.delete("+");let o=se.split(t),a=new $,h=[a],u=s.scope||I.global;for(let p of o)if(p==="(")h.push(a);else if(p===")"){if(h.length<2)throw new Error("unbalanced input: extra closing parenthesis"+t);let w=gt(h.pop()),d=h.pop();h.push(d.apply(w))}else if(p==="->"){if(!r.lambdas)throw new Error("Lambdas not supported, allow them explicitly");h.push(new G(h.pop(),e))}else if(p.match(/^[0-9]+$/)){if(!r.numbers)throw new Error("Church numbers not supported, allow them explicitly");let w=h.pop();h.push(w.apply(new xt(p)))}else{let w=h.pop();if(!e[p]&&this.known[p]&&!r.allow.has(p))throw new Error("Term '"+p+"' is not in the restricted set "+[...r.allow].sort().join(" "));let d=e[p]??this.known[p]??(e[p]=new I(p,u));h.push(w.apply(d))}if(h.length!==1)throw new Error("unbalanced input: missing "+(h.length-1)+" closing parenthesis:"+t);return gt(h.pop())}toJSON(){return{version:"1.1.1",allow:this.showRestrict("+"),numbers:this.hasNumbers,lambdas:this.hasLambdas,annotate:this.annotate,terms:this.declare()}}};S.vars=function(i={}){let t={};return new Proxy({},{get:(e,s)=>(s in t||(t[s]=new I(s,i)),t[s])})};S.church=i=>new xt(i);for(let i in M)S[i]=M[i];S.classes=vt;S.native=M;S.control=C.control;yt.exports={SKI:S}});var rt=k((Fe,St)=>{var{SKI:q}=X(),{Expr:ze,FreeVar:ne,Alias:bt,Lambda:$e}=q.classes,z=class{constructor(t){let{input:e,cases:s,allow:n,numbers:r,lambdas:o,engine:a,engineFull:h,...u}=t,p=t.env??t.vars;this.engine=a??new q,this.engineFull=h??new q,this.restrict={allow:n,numbers:r??!1,lambdas:o??!1},this.env={};let w={};for(let d of p??[]){let l=this.engineFull.parse(d,{env:w,scope:this});if(l instanceof q.classes.Alias)this.env[l.name]=new bt(l.name,l.impl,{terminal:!0,canonize:!1});else if(l instanceof q.classes.FreeVar)this.env[l.name]=l;else throw new Error("Unsupported given variable type: "+d)}this.input=[];for(let d of Array.isArray(e)?e:[e])this.addInput(d);if(!this.input.length)throw new Error("Quest needs at least one input placeholder");this.envFull={...this.env,...w};for(let d of this.input){if(d.name in this.envFull)throw new Error("input placeholder name is duplicated or clashes with env: "+d.name);this.envFull[d.name]=d.placeholder}this.cases=[],this.name=u.name??u.title,u.intro=kt(u.intro??u.descr),this.intro=u.intro,this.id=u.id,this.meta=u;for(let d of s??[])this.add(...d)}allowed(){let t=this.restrict.allow??"",e=Object.keys(this.env).sort();return t?this.engine.showRestrict(t+"+"+e.join(" ")):e.map(s=>"+"+s).join(" ")}addInput(t){if(typeof t!="object"&&(t={name:t}),typeof t.name!="string")throw new Error("quest 'input' field must be a string or a {name: string, ...} object");t.placeholder=new q.classes.FreeVar(t.name),this.input.push(t)}add(t,...e){typeof t=="string"?(e.unshift(t),t={}):t={...t},t.engine=t.engine??this.engineFull,t.env=t.env??this.envFull;let s=this.input.map(n=>n.placeholder);return this.cases.push(t.caps?new et(s,t,e):new tt(s,t,e)),this}prepare(...t){if(t.length!==this.input.length)throw new Error("Solutions provided "+t.length+" terms where "+this.input.length+" are expected");let e=0,s=[],n={...this.env};for(let r=0;r<t.length;r++){let o=this.input[r],a=this.engine.parse(t[r],{env:n,allow:o.allow??this.restrict.allow,numbers:o.numbers??this.restrict.numbers,lambdas:o.lambdas??this.restrict.lambdas}),h={...this.engine.getTerms(),...n};e+=a.fold(0,(p,w)=>{if(w instanceof q.classes.Named&&h[w.name]===w)return q.control.prune(p+1)});let u=a instanceof ne?a:new bt(o.fancy??o.name,a,{terminal:!0,canonize:!1});n[o.name]=u,s.push(u)}return{prepared:s,weight:e}}check(...t){try{let{prepared:e,weight:s}=this.prepare(...t),n=this.cases.map(a=>a.check(...e)),r=n.reduce((a,h)=>a&&h.pass,!0),o=n.reduce((a,h)=>a+h.steps,0);return{expr:e[0],input:e,pass:r,steps:o,details:n,weight:s}}catch(e){return{pass:!1,details:[],exception:e,steps:0,input:t}}}verify(t){let e=this.verifyMeta(t);if(t.solutions){let s=this.verifySolutions(t.solutions);s&&(e.solutions=s)}return t.seen&&(this.id||(e.seen="No id in quest "+(this.name??"(unnamed)")),t.seen.has(this.id)&&(e.seen="Duplicate quest id "+this.id),t.seen.add(this.id)),Object.keys(e).length?e:null}verifySolutions(t){if(typeof t=="object"&&!Array.isArray(t?.accepted)&&!Array.isArray(t?.rejected)&&(!this.id||!t[this.id]))return null;let{accepted:e=[],rejected:s=[]}=t[this.id]??t,n={shouldPass:[],shouldFail:[]};for(let r of e){let o=this.check(...r);o.pass||n.shouldPass.push({input:r,result:o})}for(let r of s){let o=this.check(...r);o.pass&&n.shouldFail.push({input:r,result:o})}return n.shouldFail.length+n.shouldPass.length?n:null}verifyMeta(t={}){let e={};for(let s of["name","intro"]){let n=_t(this[s]);n&&(e[s]=n)}if(t.date){let s=new Date(this.meta.created_at);isNaN(s)?e.date="invalid date format: "+this.meta.created_at:(s<new Date("2024-07-15")||s>new Date)&&(e.date="date out of range: "+this.meta.created_at)}return e}show(){return[...this.cases]}},N=class{constructor(t,e){this.max=e.max??1e3,this.note=e.note,this.env={...e.env??{}},this.input=t,this.engine=e.engine}parse(t){return new st(this.engine.parse(t,{env:this.env,scope:this}),this.input)}check(...t){throw new Error("not implemented")}},tt=class extends N{constructor(t,e,s){if(s.length!==2)throw new Error("Case accepts exactly 2 strings");super(t,e),[this.e1,this.e2]=s.map(n=>this.parse(n))}check(...t){let e=this.e1.apply(t),s=e.run({max:this.max}),r=this.e2.apply(t).run({max:this.max}),o=null;return!s.final||!r.final?o="failed to reach normal form in "+this.max+" steps":o=s.expr.diff(r.expr),{pass:!o,reason:o,steps:s.steps,start:e,found:s.expr,expected:r.expr,note:this.note,args:t,case:this}}},re={normal:!0,proper:!0,discard:!0,duplicate:!0,linear:!0,affine:!0,arity:!0},et=class extends N{constructor(t,e,s){if(super(t,e),s.length>1)throw new Error("PropertyCase accepts exactly 1 string");if(!e.caps||typeof e.caps!="object"||!Object.keys(e.caps).length)throw new Error("PropertyCase requires a caps object with at least one capability");let n=Object.keys(e.caps).filter(r=>!re[r]);if(n.length)throw new Error("PropertyCase: don't know how to test these capabilities: "+n.join(", "));this.expr=this.parse(s[0]),this.caps=e.caps,this.caps.linear&&(delete this.caps.linear,this.caps.duplicate=!1,this.caps.discard=!1,this.caps.normal=!0),this.caps.affine&&(delete this.caps.affine,this.caps.normal=!0,this.caps.duplicate=!1)}check(...t){let e=this.expr.apply(t),s=e.run({max:this.max}),n=s.expr.infer({max:this.max}),r=[];for(let o in this.caps)n[o]!==this.caps[o]&&r.push("expected property "+o+" to be "+this.caps[o]+", found "+n[o]);return{pass:!r.length,reason:r?r.join(`
3
- `):null,steps:s.steps,start:e,found:s.expr,case:this,note:this.note,args:t}}},st=class{constructor(t,e){this.expr=t,this.env=e}apply(t){if(t.length!==this.env.length)throw new Error("Subst: expected "+this.env.length+" terms, got "+t.length);let e=this.expr;for(let s=0;s<this.env.length;s++)e=e.subst(this.env[s],t[s])??e;return e}},nt=class{constructor(t){this.name=t.name,this.intro=kt(t.intro),this.id=t.id,t.content&&(this.content=t.content.map(e=>e instanceof z?e:new z(e)))}verify(t){let e={},s=ie(this.id,t.seen);s&&(e[this.id]=s);for(let n of["name","intro"]){let r=_t(this[n]);r&&(e[n]=r)}return e.content=this.content.map(n=>n.verify(t)),e}};function kt(i){return i===void 0||typeof i=="string"?i:Array.isArray(i)?i.join(" "):""+i}function ie(i,t){if(i===void 0)return"missing";if(typeof i!="string"&&typeof i!="number")return"is a "+typeof i;if(t){if(t.has(i))return"duplicate id "+i;t.add(i)}}function _t(i){if(i===void 0)return"missing";if(typeof i!="string")return"not a string but "+typeof i;let t=[],e=/<\/?([a-z]+)(?:\s[^>]*)?>/gi,s;for(;(s=e.exec(i))!==null;){let[n,r]=s;if(n.startsWith("</")){if(t.length===0||t.pop()!==r)return`Unmatched closing tag: </${r}>`}else t.push(r)}return t.length>0?`Unclosed tags: ${t.join(", ")}`:null}z.Group=nt;z.Case=N;St.exports={Quest:z}});var It=k((Te,Lt)=>{"use strict";var{Expr:Et,Alias:ae,FreeVar:oe}=J(),{Quest:At}=rt();function he(i,t,e){let{depth:s=16,infer:n=!0,progressInterval:r=1e3}=t,o=n&&!t.noskip,a=[[]],h=0,u=0,p={},w=l=>{h++;let m=n?l.infer({max:t.max,maxArgs:t.maxArgs}):null;if(o&&m.expr){if(p[m.expr])return{res:-1};p[m.expr]=!0}return u++,{res:e(l,m),props:m}};for(let l of i){let{res:m}=w(l);if(m>0)return{expr:l,total:h,probed:u,gen:1};if(m<0)continue;a[0].push(l)}let d;for(let l=1;l<s;l++){t.progress&&(t.progress({gen:l,total:h,probed:u,step:!0}),d=h);for(let m=0;m<l;m++)for(let ut of a[l-m-1]||[])for(let Rt of a[m]||[]){if(h>=t.tries)return{total:h,probed:u,gen:l,...t.retain?{cache:a}:{}};t.progress&&h-d>=r&&(t.progress({gen:l,total:h,probed:u,step:!1}),d=h);let B=ut.apply(Rt),{res:ft,props:Q}=w(B);if(ft>0)return{expr:B,total:h,probed:u,gen:l,...t.retain?{cache:a}:{}};if(ft<0)continue;let D=n?(Q.expr?0:3)+(Q.dup?1:0)+(Q.proper?0:1):0;a[l+D]||(a[l+D]=[]),a[l+D].push(B)}}return{total:h,probed:u,gen:s,...t.retain?{cache:a}:{}}}function it(i,t={}){if(i instanceof Et)return i.format(t);if(i instanceof At)return"Quest("+i.name+")";if(i instanceof At.Case)return"Quest.Case";if(Array.isArray(i))return i.map(it);if(typeof i!="object"||i===null||i.constructor!==Object)return i;let e={};for(let s in i)e[s]=it(i[s]);return e}function ce(i,t){let e=Et.extras.toposort([i],t);return e.list.map(s=>s instanceof ae?s.name+"="+s.impl.format({inventory:e.env}):s instanceof oe?s.name+"=":s.format({inventory:e.env})).join("; ")}function qt(i,t){let[e,...s]=i.unroll();return t(e,s.map(n=>qt(n,t)))}Lt.exports={search:he,deepFormat:it,declare:ce,foldr:qt}});var Ft=k((je,$t)=>{var{SKI:F}=X(),{Quest:zt}=rt(),le=It();F.Quest=zt;F.extras={...le,...F.classes.Expr.extras};typeof process=="object"&&process.env.SKI_REPL&&typeof global<"u"&&(global.SKI=F,console.log("SKI_REPL activated, try `new SKI();`"));typeof window<"u"&&(window.SKI=F);$t.exports={SKI:F,Quest:zt}});var jt=k((Ce,Tt)=>{var at=class{constructor(t){this.ns=t+":"}save(t,e){window.localStorage.setItem(this.ns+t,JSON.stringify(e))}load(t){return JSON.parse(window.localStorage.getItem(this.ns+t))}scan(){let t=window.localStorage,e=[];for(let s=0;s<t.length;s++){let n=t.key(s);n.startsWith(this.ns)&&e.push(n.substring(this.ns.length))}return e}delete(t){window.localStorage.removeItem(this.ns+t)}};Tt.exports={Store:at}});var ot=k((Me,Mt)=>{"use strict";function ue(...i){let t={};for(let e of i){let s=e.replace(/[A-Z]/g,n=>"-"+n.toLowerCase());if(t[e]=document.getElementById(s),!t[e])throw new Error(`View element not found: ${s}`)}return t}function fe(i,t,e={},s=null){let n=document.createElement(t);return e.class&&n.classList.add(...e.class),e.content!==void 0&&(n.innerHTML=""+e.content),e.hidden&&(n.hidden=!0),e.color&&(n.style.color=e.color),i&&i.appendChild(n),s&&s(n),n}function Ct(i,t){t(i);for(let e of i.childNodes)Ct(e,t)}function pe(i){typeof i!="string"&&(i=""+i);let t={"<":"&lt;",">":"&gt;","&":"&amp;"};return i.replace(/[<>&]/g,e=>t[e])}function de(i){let t={"(":"%28",")":"%29"};return encodeURIComponent(i).replace(/[()]/g,e=>t[e]).replace(/%20/g,"+")}function me(i){return decodeURIComponent((""+i).replace(/\+/g," "))}Mt.exports={append:fe,decode:me,encode:de,grabView:ue,sanitize:pe,traverse:Ct}});var Pt=k((Ne,Nt)=>{"use strict";var{append:ht}=ot(),ct=class{constructor(t={}){this.options=t,this.height=t.height??5,this.running=!1,this.delay=t.delay??0,this.maxSteps=t.max??1/0,this.onStart=t.onStart??(()=>{}),this.onStop=t.onStop??(()=>{}),this.onStep=t.onStep??(()=>{}),this.engine=t.engine,this.format=t.format??{html:!0},this.generator=t.generator??(e=>e.walk()),this.set(t.expr),this.view={},this.view.parent=t.parent,this.view.scroll=t.scroll??t.parent,this.view.main=ht(t.parent,"ol",{class:["ski-eval-box"]})}set(t){if(typeof t=="string")this.src=t,this.expr=this.engine.parse(t);else if(Array.isArray(t)&&t.length===2)this.src=t[0],this.expr=t[1];else if(!t)this.expr=null,this.src=null;else if(typeof t=="object"&&typeof t.format=="function")this.expr=t,this.src=t.format();else throw new Error("EvalBox.set() expects a string, Expr, or [string, Expr]");return this}start(t){this.running&&this.stop();try{t!==void 0&&this.set(t),this.seq=this.generator(this.expr)}catch(e){return console.error(e),this.stop(e.message)}return this.view.main.innerHTML="",this.onStart(),this.running=!0,this.tick(),this}stop(t){this.running=!1,this.timer&&(clearTimeout(this.timer),this.timer=null),t&&this.print(t,{class:["ski-eval-error"],line:""}),this.onStop()}resume(){this.running||!this.seq||(this.running=!0,this.onStart(),this.tick())}tick(){if(!this.running)return;let{value:t,done:e}=this.seq.next();if(t&&this.print(t.expr.format(this.format),{line:t.steps}),this.onStep(t,e||t.final),e||t.final)return this.view.last&&this.view.last.classList.add("ski-eval-success"),this.seq=null,this.stop();if(t.steps>=this.maxSteps)return this.stop("Max steps reached: "+this.maxSteps);this.timer=setTimeout(()=>this.tick(),this.delay)}remove(){this.view.parent&&(this.view.parent.removeChild(this.view.main),this.view.parent=null)}clear(){this.stop(),this.view.main.innerHTML=""}setHeight(t){this.height=t}print(t,e={}){let s=ht(this.view.main,"li",e);if(e.line!==0&&!e.line?s.style["list-style"]="none":(this.view.main.style["padding-left"]=(""+e.line).length+2.5+"ch",s.value=e.line),this.view.last=s,e.raw)s.innerHTML=t;else for(ht(s,"span",{class:e.class??["ski-eval-line"],color:e.color,content:t});this.view.main.children.length>this.height;)this.view.main.removeChild(this.view.main.firstChild);return this.view.scroll&&(this.view.scroll.scrollTop=s.offsetTop),s}};Nt.exports={EvalBox:ct}});var Kt=k((Pe,Ht)=>{"use strict";var{SKI:P}=Ft(),{Store:we}=jt(),{EvalBox:ge}=Pt(),{append:c}=ot(),lt=class{constructor(t){if(this.view={},this.root=t.baseUrl??".",!t.store&&!t.storePrefix)throw new Error("No storePrefix provided");this.store=t.store??new we(t.storePrefix),this.engine=t.engine??new P(this.store.load("engine")??{annotate:!0,allow:"SKI"}),t.inventoryBox&&(this.view.inventory=t.inventoryBox,this.showKnown()),this.view.content=t.contentBox,t.indexBox&&(this.view.index=c(t.indexBox,"div",{class:["ski-quest-nav"]})),this._onSolved=t.onSolved,this._onFailed=t.onFailed,this._onUnlock=t.onUnlock,this.chapters=[]}loadFromIndex(t,e,s){fetch(this.mkLink(t)).then(n=>n.json()).then(n=>this.loadChapters(n)).then(n=>{if(s&&s(n),e){let r=document.getElementById(e);r&&r.scrollIntoView()}})}async loadChapters(t){let e=0;this.chapters=[];let s=[];for(let n of t){let r=new V({number:++e,link:this.mkLink(n),engine:this.engine,store:this.store,onUnlock:o=>this.onUnlock(o),onSolved:o=>this._onSolved(o),onFailed:o=>this._onFailed(o)});this.chapters.push(r),r.attach(this.view.content,{placeholder:"loading chapter"+r.number+"..."}),this.view.index&&r.addLink(this.view.index),s.push(r.fetch().then(o=>{o.draw()}))}return Promise.all(s).then(()=>this)}mkLink(t){return t.match(/^\w+:\/\//)||t.match(/^[/.]/)?t:this.root+"/"+t}onUnlock(t){this.engine.maybeAdd(t.name,t.impl),this.store&&this.store.save("engine",this.engine),this.showKnown(),this._onUnlock&&this._onUnlock(t)}showKnown(){if(!this.view.inventory)return;this.view.inventory.innerHTML="";let t=c(this.view.inventory,"ul",{class:["ski-quest-inventory"]}),e=this.engine.getTerms();for(let s of Object.keys(e).sort().map(n=>[n,e[n]])){let n=c(t,"li",{},r=>{r.dataset.skiTerm=s[0]});c(n,"span",{content:s[0],class:["ski-quest-term-name"]}),c(n,"span",{content:": "}),c(n,"span",{content:ye(s[1]),class:["ski-quest-term-def"]})}}demolish(){for(let t of this.store.scan())this.store.delete(t)}},R=class{constructor(t,e){let s=e.engine??e.chapter?.engine;if(!s)throw new Error("QuestBox requires an engine: SKI in either options or chapter");let n=e.store??e.chapter?.store;if(!n)throw new Error("QuestBox requires a store: Store in either options or chapter");this.impl=new P.Quest({...t,engine:s}),this.name=this.impl.id?"quest-"+this.impl.id:"",this.chapter=e.chapter,this.chapter&&e.number&&(this.number=this.chapter.number+"."+e.number),this.store=n,this.engine=s,this.view={},this.input=[]}load(){let t=this.store.load(this.name)??{};return this.status={solved:t.solved??!1,steps:t.steps??0,attempts:t.attempts??0,weight:t.weight??0,total:t.total??0},this.status.solved&&this.onSolved(),this}save(){return this.store.save(this.name,this.status),this}update(t){this.status.solved||(this.status.attempts++,this.status.total+=t.steps,this.status.steps=t.steps,this.status.weight=t.weight,t.pass&&(this.status.solved=!0,this.onSolved(t)),this.save(),this.showStatus())}onSolved(t){if(this.impl.meta.unlock&&t){let e=new P.classes.Alias(this.impl.meta.unlock,t.expr.expand());this.chapter?.onUnlock(e)}this.chapter&&this.chapter.addSolved(this.impl.id)}check(){this.view.display&&(this.view.display.innerHTML="running...");let t=this.input.map(s=>s.value),e=this.impl.check(...t);this.showResult(e),this.update(e)}draw(t){this.view.frame=c(t,"div",{class:["ski-quest-box"]}),this.view.frame.id=this.name;let e=c(this.view.frame,"h3"),s=c(this.view.frame,"div"),n=c(e,"a",{content:this.number?"#"+this.number:"Quest"});n.href="#"+this.name,n.onclick=()=>Ut(s,!0),c(e,"span",{content:" "+this.impl.name});let r=this.impl.allowed();r&&c(e,"span",{content:" ["+r+"]"}),this.view.stat=c(e,"span",{class:["ski-quest-float-right"]});let o=c(s,"div");c(o,"div",{content:Ot(this.impl.intro),class:["ski-quest-intro"]}),this.impl.meta.hint&&ve(o," Hint:..."," Hint: "+this.impl.meta.hint),this.view.display=c(s,"div",{class:["ski-quest-display"],content:"....."}),this.view.solution=c(s,"div",{class:["ski-quest-input"]}),this.drawInput(this.view.solution),this.showStatus()}drawInput(t){let e=this.impl.input,s=e.length!==1;for(let r of e){if(s){let a=c(t,"div",{class:["ski-quest-label"]});c(a,"b",{content:r.name}),r.note&&c(a,"span",{content:" // "+r.note,class:["ski-quest-comment"]})}let o=c(t,"input");o.type="text",o.onkeydown=a=>{a.key==="Enter"&&(a.preventDefault(),this.check())},this.input.push(o),c(t,"br")}let n=c(t,"button",{content:"solve!"});n.onclick=()=>this.check()}showStatus(){if(this.view.stat&&this.status.attempts){let t="in "+this.status.attempts+(this.status.attempts===1?" try":" tries"),e=this.status.solved?"&check; "+this.status.steps+" steps/"+this.status.weight+" terms ":this.status.total+" total steps ";this.view.stat.innerHTML=e+" "+t}}showResult(t){if(!this.view.display)return;this.view.display.innerHTML="";let e=c(this.view.display,"div");c(e,"span",{content:"Your solution: "+xe(t.expr)+" "}),t.exception&&c(this.view.display,"div",{class:["ski-quest-error"],content:"Execution failed: "+t.exception});for(let s of t.details){let n=c(this.view.display,"div",{class:s.pass?["ski-quest-success"]:["ski-quest-error"]});c(n,"span",{content:s.pass?"&check; ":"&cross; "}),c(n,"span",{content:`${s.start} &rarr; ${s.found} `});let r=c(n,"a",{content:`in ${s.steps} steps`,class:["ski-quest-control"]});c(n,"span",{content:" "});let o=c(n,"a",{content:" (hide)",class:["ski-quest-control"],hidden:!0});s.pass||(c(n,"br"),s.expected!==void 0&&(c(n,"span",{content:"&nbsp;&nbsp;expected: "+s.expected}),c(n,"br")),s.reason&&(c(n,"span",{content:"&nbsp;&nbsp;"+s.reason}),c(n,"br")));let a=c(n,"div",{});r.onclick=()=>{a.innerHTML="",o.hidden=!1,new ge({parent:a,engine:this.engine,height:1/0,max:s.steps+2,headless:!0}).start(s.start)},o.onclick=()=>{a.innerHTML="",o.hidden=!0}}}},V=class{constructor(t){this.options=t,this.quests=[],this.solved=new Set,this.view={},this.number=t.number??0,this.engine=t.engine,this.store=t.store,this.onUnlock=t.onUnlock??(()=>{}),this.updateMeta()}updateMeta(t={}){this.options={...this.options,...t},this.id="chapter-"+(t.id??this.number),this.view.frame&&(this.view.frame.id=this.id),this.view.link&&(this.view.link.href="#"+this.id),this.options.name&&this.view.linkText&&(this.view.linkText.innerHTML="Chapter "+this.number+": "+this.options.name)}fetch(){return fetch(this.options.link).then(t=>t.json()).then(t=>{if(Array.isArray(t)&&(t={content:t}),!Array.isArray(t.content))throw new Error("Invalid quest list in "+this.options.link);this.updateMeta(t);let e=0;for(let s of t.content)this.quests.push(new R(s,{chapter:this,number:++e}));return this})}addSolved(t){this.solved.has(t)||(this.solved.add(t),this.showStatus())}getProgress(){return{total:this.quests.length,solved:this.solved.size,complete:this.solved.size===this.quests.length,percentage:Math.round(this.solved.size/this.quests.length*100)}}attach(t,e){return this.view.frame=c(t,"div",{class:["ski-quest-chapter"]}),this.view.frame.id=this.id,e.placeholder&&(this.view.placeholder=c(this.view.frame,"div",{content:e.placeholder})),this}draw(){this.visible=!0,this.view.placeholder?.remove();let t=c(this.view.frame,"h2"),e=c(this.view.frame,"div");c(t,"span",{content:"Chapter "+this.number+": "+this.options.name}),this.view.stat=c(t,"span",{class:["ski-quest-float-right"]}),t.onclick=()=>{Ut(e,this.visible=!this.visible)},this.view.intro=c(e,"div",{content:Ot(this.options.intro),class:["ski-quest-note","ski-quest-chapter-intro"]}),this.view.content=c(e,"div",{class:["ski-quest-chapter-content"]});for(let s of this.quests)s.load(),s.draw(this.view.content);this.showStatus()}showStatus(){if(!this.view.stat)return;let t=this.getProgress();this.view.stat.innerHTML="Progress: "+t.solved+"/"+t.total+" ("+t.percentage+"%)",t.complete&&this.view.stat.classList.add("success"),this.view.progressbar&&(this.view.progressbar.style.paddingRight=t.percentage+"%",this.view.progressbar.style.marginRight=-t.percentage+"%")}addLink(t){let e=c(t,"div",{class:["ski-quest-nav-item"]}),s=c(e,"a",{},n=>{n.style.display="flex"});s.href="#"+this.id,this.view.link=s,this.view.progressbar=c(s,"span",{class:["ski-quest-progressbar"]}),this.view.linkText=c(s,"span",{content:"Chapter "+this.number+"..."})}};function ve(i,t,e){let s=c(i,"span",{}),n=c(s,"span",{content:t,class:["ski-quest-hint"]});n.onclick=()=>{n.remove(),c(s,"span",{content:e})}}function Ot(i){return Array.isArray(i)?i.join(" "):""+i}function xe(i){return i instanceof P.classes.Expr?i instanceof P.classes.Alias?i.name+" = "+i.expand():""+i.expand():""+i}function Ut(i,t){t===void 0&&(t=i.hidden),i.hidden=!t}function ye(i){return i.note??(i.impl??i).format({html:!0,lambda:[""," &mapsto; ",""]})}Ht.exports={QuestPage:lt,QuestChapter:V,QuestBox:R}});var Se=k(()=>{var{QuestBox:be,QuestChapter:ke,QuestPage:_e}=Kt();typeof window<"u"&&(window.QuestBox=be,window.QuestChapter=ke,window.QuestPage=_e)});Se();})();
1
+ "use strict";(()=>{var X=Object.defineProperty;var Be=Object.getOwnPropertyDescriptor;var He=Object.getOwnPropertyNames;var Ze=Object.prototype.hasOwnProperty;var V=(i,e)=>()=>(i&&(e=i(i=0)),e);var C=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),P=(i,e)=>{for(var t in e)X(i,t,{get:e[t],enumerable:!0})},We=(i,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of He(e))!Ze.call(i,n)&&n!==t&&X(i,n,{get:()=>e[n],enumerable:!(s=Be(e,n))||s.enumerable});return i};var j=i=>We(X({},"__esModule",{value:!0}),i);function B(i,e){if(!e)return i;let t=new Set([...i]),s={"=":r=>{t=new Set([r]),n="+"},"+":r=>{t.add(r)},"-":r=>{t.delete(r)}},n="=";for(let r of Je.split(e))s[r]?n=r:s[n](r);return t}function k(i){return i instanceof U?[i.value??void 0,i.decoration]:[i??void 0,void 0]}function z(i){let e=t=>new U(t,e);return e.label=i,e.toString=()=>"TraverseControl::"+i,e}var N,Je,U,ee=V(()=>{"use strict";N=class{constructor(...e){let t="$|(\\s+)|"+e.map(s=>"(?:"+s+")").sort((s,n)=>n.length-s.length).join("|");this.rex=new RegExp(t,"gys")}split(e){this.rex.lastIndex=0;let t=[...e.matchAll(this.rex)],n=t.pop()?.index??0;if(n!==e.length)throw new Error("Unknown tokens at pos "+n+"/"+e.length+" starting with "+e.substring(n));return t.filter(r=>r[1]===void 0).map(r=>r[0])}},Je=new N("[-=+]","[A-Z]","\\b[a-z_][a-z_0-9]*\\b");U=class{constructor(e,t){this.value=e,this.decoration=t}}});var ke={};P(ke,{Alias:()=>f,App:()=>T,Church:()=>I,Expr:()=>b,FreeVar:()=>d,Lambda:()=>y,Named:()=>E,Native:()=>O,classes:()=>et,control:()=>u,native:()=>_});function ye(i,e){return t=>e<=1?i.apply(t):ye(i.apply(t),e-1)}function F(i,e,t={}){_[i]=new O(i,e,t)}function Xe(i){for(;i instanceof T;)i=i.fun;return i instanceof d}function be(i,e,t){let s=new Array(i.length).fill(0),n=!0;e.traverse(a=>{if(a instanceof d){let l=i.findIndex(p=>p.name===a.name);if(l>=0){s[l]++;return}}a instanceof T||(n=!1)});let r=new Set,o=new Set;for(let a=0;a<i.length;a++)s[a]===0?r.add(a):s[a]>1&&o.add(a);for(let a=i.length;a-- >0;)e=new y(i[a],e);return{normal:!0,steps:t.steps,expr:e,arity:i.length,...r.size?{skip:r}:{},...o.size?{dup:o}:{},duplicate:!!o.size||t.duplicate||!1,discard:!!r.size||t.discard||!1,proper:n}}function ve(i){return new d("abcdefgh"[i]??"x"+i)}var te,Ge,u,_,b,T,E,Ye,d,O,y,I,f,et,q=V(()=>{"use strict";ee();te={max:1e3,maxArgs:32},Ge={"leftmost-outermost":"LO","leftmost-innermost":"LI",LO:"LO",LI:"LI"},u={descend:z("descend"),prune:z("prune"),redo:z("redo"),stop:z("stop")},_={},b=class i{static{this.control=u}static{this.native=_}_setup(e={}){if(e.fancy!==void 0&&this instanceof E&&(this.fancyName=e.fancy),e.note!==void 0&&(this.note=e.note),e.arity!==void 0&&(this.arity=e.arity),e.canonize){let t=this.infer(e);t.normal&&(this.arity=this.arity??t.arity,this.note=this.note??t.expr.format({html:!0,lambda:[""," &mapsto; ",""]}),delete t.steps,this.props=t)}return this}apply(...e){let t=this;for(let s of e)t=new T(t,s);return t}expand(){return this.traverse(e=>{if(e instanceof f)return e.impl.expand()})??this}traverse(e,t){typeof e=="function"&&(t=e,e={});let s=Ge[e.order??"LO"];if(s===void 0)throw new Error("Unknown traversal order: "+e.order);let[n]=k(this._traverse_redo({order:s},t));return n??null}_traverse_redo(e,t){let s,n=this,r;do{r=n;let o=e.order==="LI"?n._traverse_descend(e,t)??t(n):t(n)??n._traverse_descend(e,t);[n,s]=k(o)}while(n&&s===u.redo);return!n&&r!==this&&(n=r),s?s(n):n}_traverse_descend(e,t){return null}any(e){return e(this)}fold(e,t){let[s]=k(this._fold(e,t));return s??e}_fold(e,t){return t(e,this)}foldBottomUp(e){let[t,...s]=this.unroll();return e(t,s.map(n=>n.foldBottomUp(e)))}infer(e={}){let t={};return this.traverse(s=>{s instanceof E&&(t[s.name]=!0)}),this._infer({max:e.max??te.max,maxArgs:e.maxArgs??te.maxArgs,skipNames:t},0)}_infer(e,t){let s=[],n=0,r=this;e:for(let o=0;o<e.maxArgs;o++){let a=r.run({max:e.max-n});if(n+=a.steps,!a.final)break;if(Xe(a.expr)){if(r=a.expr,!r.any(h=>!(h instanceof d||h instanceof T)))return be(s,r,{steps:n});let p=r.unroll(),m=!1,w=!1,g=[];for(let h=1;h<p.length;h++){let x=p[h]._infer({maxArgs:e.maxArgs-t,max:e.max-n,skipNames:e.skipNames},t+o);if(n+=x.steps??0,!x.expr)break e;x.discard&&(m=!0),x.duplicate&&(w=!0),g.push(x.expr)}return be(s,p[0].apply(...g),{discard:m,duplicate:w,steps:n})}for(;e.skipNames[ve(t+o).name];)t++;let l=ve(t+o);s.push(l),r=a.expr.apply(l)}return{normal:!1,proper:!1,steps:n}}unroll(){return[this]}*toLambda(e={}){let t=this.traverse(r=>{if(r instanceof d||r instanceof T||r instanceof y||r instanceof f)return null;let o=r.infer({max:e.max,maxArgs:e.maxArgs});if(!o.normal)throw new Error("Failed to infer an equivalent lambda term for "+r);return o.expr})??this,s=new Set,n=0;for(;t;){let r=t.traverse({order:"LI"},o=>{if(s.has(o))return null;if(o instanceof T&&o.fun instanceof y){let a=o.infer({max:e.max,maxArgs:e.maxArgs});return n+=a.steps??0,a.normal?u.stop(a.expr):(s.add(o),null)}});yield{expr:t,steps:n},t=r}}*toSKI(e={}){let t=this.traverse(n=>n instanceof d||n instanceof T||n instanceof y||n instanceof f?null:n.infer().expr)??this,s=0;for(;t;){let n=t.traverse({order:"LI"},r=>{if(!(r instanceof y)||r.impl instanceof y)return null;if(r.impl===r.arg)return u.stop(_.I);if(!r.impl.any(o=>o===r.arg))return u.stop(_.K.apply(r.impl));if(!(r.impl instanceof T))throw new Error("toSKI: assert failed: lambda body is of unexpected type "+r.impl.constructor.name);return r.impl.arg===r.arg&&!r.impl.fun.any(o=>o===r.arg)?u.stop(r.impl.fun):u.stop(_.S.apply(new y(r.arg,r.impl.fun),new y(r.arg,r.impl.arg)))});yield{expr:t,steps:s,final:!n},s++,t=n}}subst(e,t){return this===e?t:null}invoke(e){return null}step(){return{expr:this,steps:0,changed:!1}}run(e={},...t){e instanceof i&&(t.unshift(e),e={});let s=t?this.apply(...t):this,n=e.steps??0,r=Math.max(e.max??te.max,1)+n,o=!1;for(;n<r;){let a=s.step();if(!a.changed){o=!0;break}n+=a.steps,s=a.expr}if(e.throw&&!o)throw new Error("Failed to compute expression in "+r+" steps");return{final:o,steps:n,expr:s}}*walk(e={}){let t=e.max??1/0,s=0,n=this,r=!1;for(;s<t;){let o=n.step();if(o.changed||(r=!0),yield{expr:n,steps:s,final:r},r)break;s+=o.steps,n=o.expr}}equals(e){return!this.diff(e)}diff(e,t=!1){return this===e?null:e instanceof f?e.impl.diff(this,!t):t?"["+e+" != "+this+"]":"["+this+" != "+e+"]"}expect(e,t=""){if(t=t?t+": ":"",!(e instanceof i))throw new Error(t+"Expected a combinator but found "+(e?.constructor?.name??typeof e));let s=this.diff(e);if(!s)return;let n=new Error(t+s);throw n.expected=this.diag(),n.actual=e.diag(),n}toString(){return this.format()}_braced(e){return!1}_unspaced(e){return this._braced(!0)}format(e={}){let t=e.html?{brackets:["(",")"],space:" ",var:["<var>","</var>"],lambda:["","-&gt;",""],around:["",""],redex:["",""]}:{brackets:["(",")"],space:" ",var:["",""],lambda:["","->",""],around:["",""],redex:["",""]};return this._format({terse:e.terse??!0,brackets:e.brackets??t.brackets,space:e.space??t.space,var:e.var??t.var,lambda:e.lambda??t.lambda,around:e.around??t.around,redex:e.redex??t.redex,inventory:e.inventory,html:e.html??!1},0)}_format(e,t){throw new Error("No _format() method defined in class "+this.constructor.name)}diag(){let e=(s,n)=>s instanceof T?[n+"App:",...s.unroll().flatMap(r=>e(r,n+" "))]:s instanceof y?[`${n}Lambda (${s.arg}[${s.arg.id}]):`,...e(s.impl,n+" ")]:s instanceof f?[`${n}Alias (${s.name}): \\`,...e(s.impl,n)]:s instanceof d?[`${n}FreeVar: ${s.name}[${s.id}]`]:[`${n}${s.constructor.name}: ${s}`];return e(this,"").join(`
2
+ `)}toJSON(){return this.format()}},T=class i extends b{constructor(e,t){super(),this.arg=t,this.fun=e}_traverse_descend(e,t){let[s,n]=k(this.fun._traverse_redo(e,t));if(n===u.stop)return u.stop(s?s.apply(this.arg):null);let[r,o]=k(this.arg._traverse_redo(e,t)),a=s||r?(s??this.fun).apply(r??this.arg):null;return o===u.stop?u.stop(a):a}any(e){return e(this)||this.fun.any(e)||this.arg.any(e)}_fold(e,t){let[s=e,n="descend"]=k(t(e,this));if(n===u.prune)return s;if(n===u.stop)return u.stop(s);let[r=s,o="descend"]=k(this.fun._fold(s,t));if(o===u.stop)return u.stop(r);let[a=r,l="descend"]=k(this.arg._fold(r,t));return l===u.stop?u.stop(a):a}subst(e,t){let s=this.fun.subst(e,t),n=this.arg.subst(e,t);return s||n?(s??this.fun).apply(n??this.arg):null}step(){if(!this.final){let e=this.fun.invoke(this.arg);if(e instanceof b)return{expr:e,steps:1,changed:!0};typeof e=="function"&&(this.invoke=e);let t=this.fun.step();if(t.changed)return{expr:t.expr.apply(this.arg),steps:t.steps,changed:!0};let s=this.arg.step();if(s.changed)return{expr:this.fun.apply(s.expr),steps:s.steps,changed:!0};this.final=!0}return{expr:this,steps:0,changed:!1}}invoke(e){let t=this.fun.invoke(this.arg);return t instanceof b?t.apply(e):typeof t=="function"?(this.invoke=t,t(e)):(this.invoke=s=>null,null)}unroll(){return[...this.fun.unroll(),this.arg]}diff(e,t=!1){if(!(e instanceof i))return super.diff(e,t);let s=this.fun.diff(e.fun,t);if(s)return s+"(...)";let n=this.arg.diff(e.arg,t);return n?this.fun+"("+n+")":null}_braced(e){return!e}_format(e,t){let s=this.fun._format(e,t+1),n=this.arg._format(e,0),r=t?["",""]:e.around;return e.terse&&!this.arg._braced(!1)?r[0]+s+(this.fun._unspaced(this.arg)?"":e.space)+n+r[1]:r[0]+s+e.brackets[0]+n+e.brackets[1]+r[1]}_unspaced(e){return this.arg._braced(!1)?!0:this.arg._unspaced(e)}},E=class i extends b{constructor(e){if(super(),typeof e!="string"||e.length===0)throw new Error("Attempt to create a named term with improper name");this.name=e}_unspaced(e){return!!(e instanceof i&&(this.name.match(/^[A-Z+]$/)&&e.name.match(/^[a-z+]/i)||this.name.match(/^[a-z+]/i)&&e.name.match(/^[A-Z+]$/)))}_format(e,t){let s=e.html?this.fancyName??this.name:this.name;return this.arity!==void 0&&this.arity>0&&this.arity<=t?e.redex[0]+s+e.redex[1]:s}},Ye=0,d=class i extends E{constructor(e,t){super(e),this.id=++Ye,this.scope=t===void 0?this:t}diff(e,t=!1){if(!(e instanceof i))return super.diff(e,t);if(this.name===e.name&&this.scope===e.scope)return null;let s=this.name+"["+this.id+"]",n=e.name+"["+e.id+"]";return t?"["+n+" != "+s+"]":"["+s+" != "+n+"]"}subst(e,t){return e instanceof i&&e.name===this.name&&e.scope===this.scope?t:null}_format(e,t){let s=e.html?this.fancyName??this.name:this.name;return e.var[0]+s+e.var[1]}static{this.global=["global"]}},O=class extends E{constructor(e,t,s={}){super(e),this.invoke=t,this._setup({canonize:!0,...s})}},y=class i extends b{constructor(e,t){if(super(),!(e instanceof d))throw new Error("Lambda argument must be a FreeVar");let s=new d(e.name,this);this.arg=s,this.impl=t.subst(e,s)??t,this.arity=1}invoke(e){return this.impl.subst(this.arg,e)??this.impl}_traverse_descend(e,t){let[s,n]=k(this.impl._traverse_redo(e,t)),r=s?new i(this.arg,s):null;return n===u.stop?u.stop(r):r}any(e){return e(this)||this.impl.any(e)}_fold(e,t){let[s=e,n="descend"]=k(t(e,this));if(n===u.prune)return s;if(n===u.stop)return u.stop(s);let[r,o]=k(this.impl._fold(s,t));return o===u.stop?u.stop(r):r??s}subst(e,t){if(e===this.arg)return null;let s=this.impl.subst(e,t);return s?new i(this.arg,s):null}diff(e,t=!1){if(!(e instanceof i))return super.diff(e,t);let s=new d("t"),n=this.invoke(s).diff(e.invoke(s),t);return n?"(t->"+n+")":null}_format(e,t){return(t>0?e.brackets[0]:"")+e.lambda[0]+this.arg._format(e,0)+e.lambda[1]+this.impl._format(e,0)+e.lambda[2]+(t>0?e.brackets[1]:"")}_braced(e){return!0}},I=class i extends b{constructor(e){if(e=Number.parseInt(String(e)),!(e>=0))throw new Error("Church number must be a non-negative integer");super(),this.invoke=t=>s=>{let n=s;for(let r=e;r-- >0;)n=t.apply(n);return n},this.n=e,this.arity=2}diff(e,t=!1){return e instanceof i?this.n===e.n?null:t?"["+e.n+" != "+this.n+"]":"["+this.n+" != "+e.n+"]":super.diff(e,t)}_unspaced(e){return!1}_format(e,t){return t>=2?e.redex[0]+this.n+e.redex[1]:this.n+""}};f=class extends E{constructor(e,t,s={}){if(super(e),!(t instanceof b))throw new Error("Attempt to create an alias for a non-expression: "+t);this.impl=t,this._setup(s),this.terminal=s.terminal??this.props?.proper,this.invoke=ye(t,this.arity??0)}_traverse_descend(e,t){return this.impl._traverse_redo(e,t)}any(e){return e(this)||this.impl.any(e)}_fold(e,t){let[s=e,n]=k(t(e,this));if(n===u.prune)return s;if(n===u.stop)return u.stop(s);let[r,o]=k(this.impl._fold(s,t));return o===u.stop?u.stop(r):r??s}subst(e,t){return this===e?t:this.impl.subst(e,t)}step(){return(this.arity??0)>0?{expr:this,steps:0,changed:!1}:{expr:this.impl,steps:0,changed:!0}}diff(e,t=!1){return this===e?null:e.diff(this.impl,!t)}_braced(e){return this.outdated?this.impl._braced(e):!1}_format(e,t){return(e.inventory?e.inventory[this.name]!==this:this.outdated)?this.impl._format(e,t):super._format(e,t)}};F("I",i=>i);F("K",i=>e=>i);F("S",i=>e=>t=>i.apply(t,e.apply(t)));F("B",i=>e=>t=>i.apply(e.apply(t)));F("C",i=>e=>t=>i.apply(t).apply(e));F("W",i=>e=>i.apply(e).apply(e));F("+",i=>i instanceof I?new I(i.n+1):e=>t=>e.apply(i.apply(e,t)),{note:"Increase a Church numeral argument by 1, otherwise n => f => x => f(n f x)"});et={Expr:b,App:T,Named:E,FreeVar:d,Native:O,Lambda:y,Church:I,Alias:f}});var Ee={};P(Ee,{toposort:()=>L});function L(i,e){if(i instanceof b&&(i=[i]),e)i||(i=Object.keys(e).sort().map(r=>e[r]));else{if(!i)return{list:[],env:{}};e={};for(let r of i)if(r instanceof E){if(e[r.name])throw new Error("duplicate name "+r);e[r.name]=r}}let t=[],s=new Set,n=r=>{s.has(r)||(r.fold(!1,(o,a)=>{if(a!==r&&a instanceof E&&e[a.name]===a)return n(a),u.prune(!1)}),t.push(r),s.add(r))};for(let r of i)n(r);return{list:t,env:e}}var H=V(()=>{"use strict";q()});var Se={};P(Se,{Parser:()=>$});function Te(i){return i.postParse?i.postParse():i}var R,se,tt,$,ne=V(()=>{"use strict";ee();q();H();R=class extends b{apply(...e){return e.length>0?e.shift().apply(...e):this}postParse(){throw new Error("Attempt to use empty expression () as a term")}},se=class i extends R{constructor(e,t={}){if(super(),this.impl=new R,e instanceof d)this.terms=[e];else if(e instanceof i){if(!(e.impl instanceof d))throw new Error("Expected FreeVar->...->FreeVar->Expr");this.terms=[...e.terms,e.impl]}else throw new Error("Expected FreeVar or PartialLambda")}apply(e,...t){if(e===null||t.length!==0)throw new Error("bad syntax in partial lambda expr");return this.impl=this.impl.apply(e),this}postParse(){let e=this.impl;for(let t=this.terms.length;t-- >0;)e=new y(this.terms[t],e);return e}};tt=new N("[()]","[A-Z]","[a-z_][a-z_0-9]*","\\b[0-9]+\\b","->","\\+"),$=class{constructor(e={}){if(this.annotate=!!e.annotate,this.known={..._},this.hasNumbers=!0,this.hasLambdas=!0,this.allow=new Set(Object.keys(this.known)),Array.isArray(e.terms))this.bulkAdd(e.terms);else if(e.terms)for(let t in e.terms)(typeof e.terms[t]!="string"||!e.terms[t].match(/^Native:/))&&this.add(t,e.terms[t]);this.hasNumbers=e.numbers??!0,this.hasLambdas=e.lambdas??!0,e.allow&&this.restrict(e.allow)}add(e,t,s){let n=this._named(e,t),r=typeof s=="string"?{note:s,canonize:!1}:s??{};return n._setup({canonize:this.annotate,...r}),this.known[n.name]&&(this.known[n.name].outdated=!0),this.known[n.name]=n,this.allow.add(n.name),this}_named(e,t){if(e instanceof f)return new f(e.name,e.impl,{canonize:!0});if(typeof e!="string")throw new Error("add(): term must be an Alias or a string");if(t===void 0)throw new Error("add(): impl must be provided when term is a string");if(typeof t=="string")return new f(e,this.parse(t),{canonize:!0});if(t instanceof b)return new f(e,t,{canonize:!0});if(typeof t=="function")return new O(e,t);throw new Error("add(): impl must be an Expr, a string, or a function with a signature Expr => ... => Expr")}maybeAdd(e,t){return this.known[e]?this.allow.add(e):this.add(e,t),this}bulkAdd(e){for(let t of e){let s=t.match(/^([A-Z]|[a-z][a-z_0-9]*)\s*=\s*(.*)$/s);if(!s)throw new Error("bulkAdd: invalid declaration: "+t);s[2]===""?this.remove(s[1]):this.add(s[1],this.parse(s[2]))}return this}restrict(e){return this.allow=B(this.allow,e),this}showRestrict(e="+"){let t=[],s=!0;for(let n of[...B(this.allow,e)].sort()){let r=!!n.match(/^[A-Z]$/);t.length&&!(s&&r)&&t.push(" "),t.push(n),s=r}return t.join("")}remove(e){return this.known[e].outdated=!0,delete this.known[e],this.allow.delete(e),this}getTerms(){let e={};for(let t of Object.keys(this.known))this.allow.has(t)&&(e[t]=this.known[t]);return e}declare(){let e={};for(let[a,l]of Object.entries(this.getTerms()))l instanceof f&&(e[a]=l);let t={},s=1;for(let a in _){if(!(e[a]instanceof f))continue;for(;"tmp"+s in e;)s++;let l=new f("tmp"+s,e[a]);t[l.name]=e[a],e[l.name]=l,delete e[a]}let n=L(void 0,e).list,r=new Map;if(Object.keys(t).length){let a=l=>l.traverse(p=>{if(!(p instanceof f))return null;let m=r.get(p);return m||new f(p.name,a(p.impl))})??l;for(let l=0;l<n.length;l++)n[l]=a(n[l]),r.set(t[n[l].name],n[l]),e[n[l].name]=n[l],console.log(`list[${l}] = ${n[l].name}=${n[l].impl};`);console.log("detour:",r)}let o=n.map(a=>t[a.name]?a.name+"="+t[a.name].name+"="+a.impl.format({inventory:e}):a.name+"="+a.impl.format({inventory:e}));for(let[a,l]of r)o.push(a.name+"="+l,l+"=");return o}parse(e,t={}){if(typeof e!="string")throw new Error("parse: source must be a string, got "+typeof e);let s=e.replace(/\/\/[^\n]*$/gm," ").replace(/\/\*.*?\*\//gs," ").trim().split(/\s*;[\s;]*/).filter(o=>o.match(/\S/)),n={...t.env},r=new R;for(let o of s){r instanceof f&&(r.outdated=!0);let a=o.match(/^([A-Z]|[a-z][a-z_0-9]*)\s*=(.*)$/s);if(a&&a[2]===""?r=new d(a[1],t.scope??d.global):r=this.parseLine(o,n,t),a){if(n[a[1]]!==void 0)throw new Error("Attempt to redefine a known term: "+a[1]);n[a[1]]=r}}return r.context={env:{...this.getTerms(),...n},scope:t.scope,src:e,parser:this},r}parseLine(e,t={},s={}){let n=e.match(/^\s*([A-Z]|[a-z][a-z_0-9]*)\s*=\s*(.*)$/s);if(n)return new f(n[1],this.parseLine(n[2],t,s));let r={numbers:s.numbers??this.hasNumbers,lambdas:s.lambdas??this.hasLambdas,allow:B(this.allow,s.allow)};r.numbers?r.allow.add("+"):r.allow.delete("+");let o=tt.split(e),a=new R,l=[a],p=s.scope||d.global;for(let m of o)if(m==="(")l.push(a);else if(m===")"){if(l.length<2)throw new Error("unbalanced input: extra closing parenthesis"+e);let w=Te(l.pop()),g=l.pop();l.push(g.apply(w))}else if(m==="->"){if(!r.lambdas)throw new Error("Lambdas not supported, allow them explicitly");l.push(new se(l.pop()))}else if(m.match(/^[0-9]+$/)){if(!r.numbers)throw new Error("Church numbers not supported, allow them explicitly");let w=l.pop();l.push(w.apply(new I(Number.parseInt(m))))}else{let w=l.pop();if(!t[m]&&this.known[m]&&!r.allow.has(m))throw new Error("Term '"+m+"' is not in the restricted set "+[...r.allow].sort().join(" "));let g=t[m]??this.known[m]??(t[m]=new d(m,p));l.push(w.apply(g))}if(l.length!==1)throw new Error("unbalanced input: missing "+(l.length-1)+" closing parenthesis:"+e);return Te(l.pop())}toJSON(){return{version:"1.1.1",allow:this.showRestrict("+"),numbers:this.hasNumbers,lambdas:this.hasLambdas,annotate:this.annotate,terms:this.declare()}}}});var Ie={};P(Ie,{Quest:()=>A});function Ae(i){return i===void 0||typeof i=="string"?i:Array.isArray(i)?i.join(" "):""+i}function nt(i,e){if(i===void 0)return"missing";if(typeof i!="string"&&typeof i!="number")return"is a "+typeof i;if(e){if(e.has(i))return"duplicate id "+i;e.add(i)}}function _e(i){if(i===void 0)return"missing";if(typeof i!="string")return"not a string but "+typeof i;let e=[],t=/<\/?([a-z]+)(?:\s[^>]*)?>/gi,s;for(;(s=t.exec(i))!==null;){let[n,r]=s;if(n.startsWith("</")){if(e.length===0||e.pop()!==r)return`Unmatched closing tag: </${r}>`}else e.push(r)}return e.length>0?`Unclosed tags: ${e.join(", ")}`:null}var A,M,re,st,ie,ae,oe,le=V(()=>{"use strict";ne();q();A=class{constructor(e){let{input:t,cases:s,allow:n,numbers:r,lambdas:o,engine:a,engineFull:l,...p}=e,m=e.env??[];this.engineFull=l??new $,this.engine=a??this.engineFull,this.restrict={allow:n,numbers:r??!1,lambdas:o??!1},this.env={};let w={};for(let g of m??[]){let h=this.engineFull.parse(g,{env:w,scope:this});if(h instanceof f)this.env[h.name]=new f(h.name,h.impl,{terminal:!0,canonize:!1});else if(h instanceof d)this.env[h.name]=h;else throw new Error("Unsupported given variable type: "+g)}this.input=[];for(let g of Array.isArray(t)?t:[t])this.addInput(g);if(!this.input.length)throw new Error("Quest needs at least one input placeholder");this.envFull={...this.env,...w};for(let g of this.input){if(g.name in this.envFull)throw new Error("input placeholder name is duplicated or clashes with env: "+g.name);this.envFull[g.name]=g.placeholder}this.cases=[],this.name=p.name??p.title,p.intro=Ae(p.intro??p.descr),this.intro=p.intro,this.id=p.id,this.meta=p;for(let g of s??[])this.add(...g)}allowed(){let e=this.restrict.allow??"",t=Object.keys(this.env).sort();return e?this.engine.showRestrict(e+"+"+t.join(" ")):t.map(s=>"+"+s).join(" ")}addInput(e){if(typeof e!="object"&&(e={name:e}),typeof e.name!="string")throw new Error("quest 'input' field must be a string or a {name: string, ...} object");let t=e;t.placeholder=new d(e.name),this.input.push(t)}add(e,...t){let s;typeof e=="string"?(t.unshift(e),s={}):s={...e},s.engine=s.engine??this.engineFull,s.env=s.env??this.envFull;let n=this.input.map(r=>r.placeholder);return this.cases.push(s.caps?new ie(n,s,t):new re(n,s,t)),this}prepare(...e){if(e.length!==this.input.length)throw new Error("Solutions provided "+e.length+" terms where "+this.input.length+" are expected");let t=0,s=[],n={...this.env};for(let r=0;r<e.length;r++){let o=this.input[r],a=this.engine.parse(e[r],{env:n,allow:o.allow??this.restrict.allow,numbers:o.numbers??this.restrict.numbers,lambdas:o.lambdas??this.restrict.lambdas}),l={...this.engine.getTerms(),...n};t+=a.fold(0,(m,w)=>{if(w instanceof E&&l[w.name]===w)return u.prune(m+1)});let p=a instanceof d?a:new f(o.fancy??o.name,a,{terminal:!0,canonize:!1});n[o.name]=p,s.push(p)}return{prepared:s,weight:t}}check(...e){try{let{prepared:t,weight:s}=this.prepare(...e),n=this.cases.map(a=>a.check(...t)),r=n.reduce((a,l)=>a&&l.pass,!0),o=n.reduce((a,l)=>a+l.steps,0);return{expr:t[0],input:t,pass:r,steps:o,details:n,weight:s}}catch(t){return{pass:!1,details:[],exception:t,steps:0,input:e}}}verify(e){let t=this.verifyMeta(e);if(e.solutions){let s=this.verifySolutions(e.solutions);s&&(t.solutions=s)}return e.seen&&(this.id||(t.seen="No id in quest "+(this.name??"(unnamed)")),e.seen.has(this.id)&&(t.seen="Duplicate quest id "+this.id),e.seen.add(this.id)),Object.keys(t).length?t:null}verifySolutions(e){if(typeof e=="object"&&!Array.isArray(e.accepted)&&!Array.isArray(e.rejected)&&(!this.id||!e[this.id]))return null;let t=this.id!==void 0?e[this.id]:void 0,{accepted:s=[],rejected:n=[]}=t??e,r={shouldPass:[],shouldFail:[]};for(let o of s){let a=this.check(...o);a.pass||r.shouldPass.push({input:o,result:a})}for(let o of n){let a=this.check(...o);a.pass&&r.shouldFail.push({input:o,result:a})}return r.shouldFail.length+r.shouldPass.length?r:null}verifyMeta(e={}){let t={};for(let s of["name","intro"]){let n=_e(this[s]);n&&(t[s]=n)}if(e.date){let s=new Date(this.meta?.created_at);isNaN(s.getTime())?t.date="invalid date format: "+this.meta?.created_at:(s.getTime()<new Date("2024-07-15").getTime()||s.getTime()>new Date().getTime())&&(t.date="date out of range: "+this.meta?.created_at)}return t}show(){return[...this.cases]}},M=class{constructor(e,t){this.max=t.max??1e3,this.note=t.note,this.env={...t.env??{}},this.input=e,this.engine=t.engine}parse(e){return new ae(this.engine.parse(e,{env:this.env,scope:this}),this.input)}check(...e){throw new Error("not implemented")}},re=class extends M{constructor(e,t,s){if(s.length!==2)throw new Error("Case accepts exactly 2 strings");super(e,t),[this.e1,this.e2]=s.map(n=>this.parse(n))}check(...e){let t=this.e1.apply(e),s=t.run({max:this.max}),r=this.e2.apply(e).run({max:this.max}),o=null;return!s.final||!r.final?o="failed to reach normal form in "+this.max+" steps":o=s.expr.diff(r.expr),{pass:!o,reason:o??void 0,steps:s.steps,start:t,found:s.expr,expected:r.expr,note:this.note,args:e,case:this}}},st={normal:!0,proper:!0,discard:!0,duplicate:!0,linear:!0,affine:!0,arity:!0},ie=class extends M{constructor(e,t,s){if(super(e,t),s.length>1)throw new Error("PropertyCase accepts exactly 1 string");if(!t.caps||typeof t.caps!="object"||!Object.keys(t.caps).length)throw new Error("PropertyCase requires a caps object with at least one capability");let n=Object.keys(t.caps).filter(r=>!st[r]);if(n.length)throw new Error("PropertyCase: don't know how to test these capabilities: "+n.join(", "));this.expr=this.parse(s[0]),this.caps={...t.caps},this.caps.linear&&(delete this.caps.linear,this.caps.duplicate=!1,this.caps.discard=!1,this.caps.normal=!0),this.caps.affine&&(delete this.caps.affine,this.caps.normal=!0,this.caps.duplicate=!1)}check(...e){let t=this.expr.apply(e),s=t.run({max:this.max}),n=s.expr.infer({max:this.max}),r=[];for(let o in this.caps)n[o]!==this.caps[o]&&r.push("expected property "+o+" to be "+this.caps[o]+", found "+n[o]);return{pass:!r.length,reason:r.length?r.join(`
3
+ `):void 0,steps:s.steps,start:t,found:s.expr,case:this,note:this.note,args:e}}},ae=class{constructor(e,t){this.expr=e,this.env=t}apply(e){if(e.length!==this.env.length)throw new Error("Subst: expected "+this.env.length+" terms, got "+e.length);let t=this.expr;for(let s=0;s<this.env.length;s++)t=t.subst(this.env[s],e[s])??t;return t}},oe=class{constructor(e){this.name=e.name,this.intro=Ae(e.intro),this.id=e.id,e.content&&(this.content=e.content.map(t=>t instanceof A?t:new A(t)))}verify(e){let t={},s=nt(this.id,e.seen);s&&(t.id=s);for(let n of["name","intro"]){let r=_e(this[n]);r&&(t[n]=r)}return t.content=this.content.map(n=>n.verify(e)),t}};A.Group=oe;A.Case=M});var Ce={};P(Ce,{extras:()=>at});function rt(i,e,t){let{depth:s=16,infer:n=!0,progressInterval:r=1e3}=e,o=n&&!e.noskip,a=[[]],l=0,p=0,m={},w=h=>{l++;let x=n?h.infer({max:e.max,maxArgs:e.maxArgs}):null;if(o&&x&&x.expr){let K=String(x.expr);if(m[K])return{res:-1,props:x};m[K]=!0}return p++,{res:t(h,x),props:x}};for(let h of i){let{res:x=0}=w(h);if(x>0)return{expr:h,total:l,probed:p,gen:1};if(x<0)continue;a[0].push(h)}let g=0;for(let h=1;h<s;h++){e.progress&&(e.progress({gen:h,total:l,probed:p,step:!0}),g=l);for(let x=0;x<h;x++)for(let xe of a[h-x-1]||[])for(let K of a[x]||[]){if(l>=(e.tries??1/0))return{total:l,probed:p,gen:h,...e.retain?{cache:a}:{}};e.progress&&l-g>=r&&(e.progress({gen:h,total:l,probed:p,step:!1}),g=l);let G=xe.apply(K),{res:we,props:D}=w(G);if((we??0)>0)return{expr:G,total:l,probed:p,gen:h,...e.retain?{cache:a}:{}};if((we??0)<0)continue;let Y=n&&D?(D.expr?0:3)+(D.dup?1:0)+(D.proper?0:1):0;a[h+Y]||(a[h+Y]=[]),a[h+Y].push(G)}}return{total:l,probed:p,gen:s,...e.retain?{cache:a}:{}}}function ce(i,e={}){if(i instanceof b)return i.format(e);if(i instanceof A)return"Quest("+i.name+")";if(i instanceof A.Case)return"Quest.Case";if(Array.isArray(i))return i.map(s=>ce(s,e));if(typeof i!="object"||i===null||i.constructor!==Object)return i;let t={};for(let s in i)t[s]=ce(i[s],e);return t}function it(i,e={}){let t=L([i],e);return t.list.map(s=>s instanceof f?s.name+"="+s.impl.format({inventory:t.env}):s instanceof d?s.name+"=":s.format({inventory:t.env})).join("; ")}var at,Oe=V(()=>{"use strict";q();le();H();at={search:rt,deepFormat:ce,declare:it,toposort:L}});var qe=C(Z=>{"use strict";var ue;Object.defineProperty(Z,"__esModule",{value:!0});Z.SKI=void 0;var S=(q(),j(ke)),ot=(ne(),j(Se)),lt=(le(),j(Ie)),ct=(H(),j(Ee)),Ve=(Oe(),j(Ce));Ve.extras.toposort=ct.toposort;var v=class extends ot.Parser{static vars(e={}){let t={};return new Proxy(t,{get(s,n){return n in s||(s[n]=new S.FreeVar(n,e)),s[n]}})}static church(e){return new S.Church(e)}};Z.SKI=v;v.native=S.native;v.control=S.control;v.classes=S.classes;v.B=S.native.B;v.C=S.native.C;v.I=S.native.I;v.K=S.native.K;v.S=S.native.S;v.W=S.native.W;v.extras=Ve.extras;v.Quest=lt.Quest;var Fe=globalThis;!((ue=Fe.process)===null||ue===void 0)&&ue.env.SKI_REPL&&(Fe.SKI=v,console.log("SKI_REPL activated, try `new SKI();`"));typeof window<"u"&&(window.SKI=v)});var Re=C((Dt,Le)=>{"use strict";var{SKI:he}=qe();typeof process=="object"&&process.env.SKI_REPL&&typeof global<"u"&&(global.SKI=he,console.log("SKI_REPL activated, try `new SKI();`"));typeof window<"u"&&(window.SKI=he);Le.exports={SKI:he}});var je=C((Ut,Pe)=>{"use strict";var pe=class{constructor(e){this.ns=e+":"}save(e,t){window.localStorage.setItem(this.ns+e,JSON.stringify(t))}load(e){return JSON.parse(window.localStorage.getItem(this.ns+e))}scan(){let e=window.localStorage,t=[];for(let s=0;s<e.length;s++){let n=e.key(s);n.startsWith(this.ns)&&t.push(n.substring(this.ns.length))}return t}delete(e){window.localStorage.removeItem(this.ns+e)}};Pe.exports={Store:pe}});var fe=C((Bt,ze)=>{"use strict";function ut(...i){let e={};for(let t of i){let s=t.replace(/[A-Z]/g,n=>"-"+n.toLowerCase());if(e[t]=document.getElementById(s),!e[t])throw new Error(`View element not found: ${s}`)}return e}function ht(i,e,t={},s=null){let n=document.createElement(e);return t.class&&n.classList.add(...t.class),t.content!==void 0&&(n.innerHTML=""+t.content),t.hidden&&(n.hidden=!0),t.color&&(n.style.color=t.color),i&&i.appendChild(n),s&&s(n),n}function Ne(i,e){e(i);for(let t of i.childNodes)Ne(t,e)}function pt(i){typeof i!="string"&&(i=""+i);let e={"<":"&lt;",">":"&gt;","&":"&amp;"};return i.replace(/[<>&]/g,t=>e[t])}function ft(i){let e={"(":"%28",")":"%29"};return encodeURIComponent(i).replace(/[()]/g,t=>e[t]).replace(/%20/g,"+")}function dt(i){return decodeURIComponent((""+i).replace(/\+/g," "))}ze.exports={append:ht,decode:dt,encode:ft,grabView:ut,sanitize:pt,traverse:Ne}});var Me=C((Ht,$e)=>{"use strict";var{append:de}=fe(),me=class{constructor(e={}){this.options=e,this.height=e.height??5,this.running=!1,this.delay=e.delay??0,this.maxSteps=e.max??1/0,this.onStart=e.onStart??(()=>{}),this.onStop=e.onStop??(()=>{}),this.onStep=e.onStep??(()=>{}),this.engine=e.engine,this.format=e.format??{html:!0},this.generator=e.generator??(t=>t.walk()),this.set(e.expr),this.view={},this.view.parent=e.parent,this.view.scroll=e.scroll??e.parent,this.view.main=de(e.parent,"ol",{class:["ski-eval-box"]})}set(e){if(typeof e=="string")this.src=e,this.expr=this.engine.parse(e);else if(Array.isArray(e)&&e.length===2)this.src=e[0],this.expr=e[1];else if(!e)this.expr=null,this.src=null;else if(typeof e=="object"&&typeof e.format=="function")this.expr=e,this.src=e.format();else throw new Error("EvalBox.set() expects a string, Expr, or [string, Expr]");return this}start(e){this.running&&this.stop();try{e!==void 0&&this.set(e),this.seq=this.generator(this.expr)}catch(t){return console.error(t),this.stop(t.message)}return this.view.main.innerHTML="",this.onStart(),this.running=!0,this.tick(),this}stop(e){this.running=!1,this.timer&&(clearTimeout(this.timer),this.timer=null),e&&this.print(e,{class:["ski-eval-error"],line:""}),this.onStop()}resume(){this.running||!this.seq||(this.running=!0,this.onStart(),this.tick())}tick(){if(!this.running)return;let{value:e,done:t}=this.seq.next();if(e&&this.print(e.expr.format(this.format),{line:e.steps}),this.onStep(e,t||e.final),t||e.final)return this.view.last&&this.view.last.classList.add("ski-eval-success"),this.seq=null,this.stop();if(e.steps>=this.maxSteps)return this.stop("Max steps reached: "+this.maxSteps);this.timer=setTimeout(()=>this.tick(),this.delay)}remove(){this.view.parent&&(this.view.parent.removeChild(this.view.main),this.view.parent=null)}clear(){this.stop(),this.view.main.innerHTML=""}setHeight(e){this.height=e}print(e,t={}){let s=de(this.view.main,"li",t);if(t.line!==0&&!t.line?s.style["list-style"]="none":(this.view.main.style["padding-left"]=(""+t.line).length+2.5+"ch",s.value=t.line),this.view.last=s,t.raw)s.innerHTML=e;else for(de(s,"span",{class:t.class??["ski-eval-line"],color:t.color,content:e});this.view.main.children.length>this.height;)this.view.main.removeChild(this.view.main.firstChild);return this.view.scroll&&(this.view.scroll.scrollTop=s.offsetTop),s}};$e.exports={EvalBox:me}});var Ue=C((Zt,De)=>{"use strict";var{SKI:Q}=Re(),{Store:mt}=je(),{EvalBox:gt}=Me(),{append:c}=fe(),ge=class{constructor(e){if(this.view={},this.root=e.baseUrl??".",!e.store&&!e.storePrefix)throw new Error("No storePrefix provided");this.store=e.store??new mt(e.storePrefix),this.engine=e.engine??new Q(this.store.load("engine")??{annotate:!0,allow:"SKI"}),e.inventoryBox&&(this.view.inventory=e.inventoryBox,this.showKnown()),this.view.content=e.contentBox,e.indexBox&&(this.view.index=c(e.indexBox,"div",{class:["ski-quest-nav"]})),this._onSolved=e.onSolved,this._onFailed=e.onFailed,this._onUnlock=e.onUnlock,this.chapters=[]}loadFromIndex(e,t,s){fetch(this.mkLink(e)).then(n=>n.json()).then(n=>this.loadChapters(n)).then(n=>{if(s&&s(n),t){let r=document.getElementById(t);r&&r.scrollIntoView()}})}async loadChapters(e){let t=0;this.chapters=[];let s=[];for(let n of e){let r=new J({number:++t,link:this.mkLink(n),engine:this.engine,store:this.store,onUnlock:o=>this.onUnlock(o),onSolved:o=>this._onSolved(o),onFailed:o=>this._onFailed(o)});this.chapters.push(r),r.attach(this.view.content,{placeholder:"loading chapter"+r.number+"..."}),this.view.index&&r.addLink(this.view.index),s.push(r.fetch().then(o=>{o.draw()}))}return Promise.all(s).then(()=>this)}mkLink(e){return e.match(/^\w+:\/\//)||e.match(/^[/.]/)?e:this.root+"/"+e}onUnlock(e){this.engine.maybeAdd(e.name,e.impl),this.store&&this.store.save("engine",this.engine),this.showKnown(),this._onUnlock&&this._onUnlock(e)}showKnown(){if(!this.view.inventory)return;this.view.inventory.innerHTML="";let e=c(this.view.inventory,"ul",{class:["ski-quest-inventory"]}),t=this.engine.getTerms();for(let s of Object.keys(t).sort().map(n=>[n,t[n]])){let n=c(e,"li",{},r=>{r.dataset.skiTerm=s[0]});c(n,"span",{content:s[0],class:["ski-quest-term-name"]}),c(n,"span",{content:": "}),c(n,"span",{content:bt(s[1]),class:["ski-quest-term-def"]})}}demolish(){for(let e of this.store.scan())this.store.delete(e)}},W=class{constructor(e,t){let s=t.engine??t.chapter?.engine;if(!s)throw new Error("QuestBox requires an engine: SKI in either options or chapter");let n=t.store??t.chapter?.store;if(!n)throw new Error("QuestBox requires a store: Store in either options or chapter");this.impl=new Q.Quest({...e,engine:s}),this.name=this.impl.id?"quest-"+this.impl.id:"",this.chapter=t.chapter,this.chapter&&t.number&&(this.number=this.chapter.number+"."+t.number),this.store=n,this.engine=s,this.view={},this.input=[]}load(){let e=this.store.load(this.name)??{};return this.status={solved:e.solved??!1,steps:e.steps??0,attempts:e.attempts??0,weight:e.weight??0,total:e.total??0},this.status.solved&&this.onSolved(),this}save(){return this.store.save(this.name,this.status),this}update(e){this.status.solved||(this.status.attempts++,this.status.total+=e.steps,this.status.steps=e.steps,this.status.weight=e.weight,e.pass&&(this.status.solved=!0,this.onSolved(e)),this.save(),this.showStatus())}onSolved(e){if(this.impl.meta.unlock&&e){let t=new Q.classes.Alias(this.impl.meta.unlock,e.expr.expand());this.chapter?.onUnlock(t)}this.chapter&&this.chapter.addSolved(this.impl.id)}check(){this.view.display&&(this.view.display.innerHTML="running...");let e=this.input.map(s=>s.value),t=this.impl.check(...e);this.showResult(t),this.update(t)}draw(e){this.view.frame=c(e,"div",{class:["ski-quest-box"]}),this.view.frame.id=this.name;let t=c(this.view.frame,"h3"),s=c(this.view.frame,"div"),n=c(t,"a",{content:this.number?"#"+this.number:"Quest"});n.href="#"+this.name,n.onclick=()=>Ke(s,!0),c(t,"span",{content:" "+this.impl.name});let r=this.impl.allowed();r&&c(t,"span",{content:" ["+r+"]"}),this.view.stat=c(t,"span",{class:["ski-quest-float-right"]});let o=c(s,"div");c(o,"div",{content:Qe(this.impl.intro),class:["ski-quest-intro"]}),this.impl.meta.hint&&xt(o," Hint:..."," Hint: "+this.impl.meta.hint),this.view.display=c(s,"div",{class:["ski-quest-display"],content:"....."}),this.view.solution=c(s,"div",{class:["ski-quest-input"]}),this.drawInput(this.view.solution),this.showStatus()}drawInput(e){let t=this.impl.input,s=t.length!==1;for(let r of t){if(s){let a=c(e,"div",{class:["ski-quest-label"]});c(a,"b",{content:r.name}),r.note&&c(a,"span",{content:" // "+r.note,class:["ski-quest-comment"]})}let o=c(e,"input");o.type="text",o.onkeydown=a=>{a.key==="Enter"&&(a.preventDefault(),this.check())},this.input.push(o),c(e,"br")}let n=c(e,"button",{content:"solve!"});n.onclick=()=>this.check()}showStatus(){if(this.view.stat&&this.status.attempts){let e="in "+this.status.attempts+(this.status.attempts===1?" try":" tries"),t=this.status.solved?"&check; "+this.status.steps+" steps/"+this.status.weight+" terms ":this.status.total+" total steps ";this.view.stat.innerHTML=t+" "+e}}showResult(e){if(!this.view.display)return;this.view.display.innerHTML="";let t=c(this.view.display,"div");c(t,"span",{content:"Your solution: "+wt(e.expr)+" "}),e.exception&&c(this.view.display,"div",{class:["ski-quest-error"],content:"Execution failed: "+e.exception});for(let s of e.details){let n=c(this.view.display,"div",{class:s.pass?["ski-quest-success"]:["ski-quest-error"]});c(n,"span",{content:s.pass?"&check; ":"&cross; "}),c(n,"span",{content:`${s.start} &rarr; ${s.found} `});let r=c(n,"a",{content:`in ${s.steps} steps`,class:["ski-quest-control"]});c(n,"span",{content:" "});let o=c(n,"a",{content:" (hide)",class:["ski-quest-control"],hidden:!0});s.pass||(c(n,"br"),s.expected!==void 0&&(c(n,"span",{content:"&nbsp;&nbsp;expected: "+s.expected}),c(n,"br")),s.reason&&(c(n,"span",{content:"&nbsp;&nbsp;"+s.reason}),c(n,"br")));let a=c(n,"div",{});r.onclick=()=>{a.innerHTML="",o.hidden=!1,new gt({parent:a,engine:this.engine,height:1/0,max:s.steps+2,headless:!0}).start(s.start)},o.onclick=()=>{a.innerHTML="",o.hidden=!0}}}},J=class{constructor(e){this.options=e,this.quests=[],this.solved=new Set,this.view={},this.number=e.number??0,this.engine=e.engine,this.store=e.store,this.onUnlock=e.onUnlock??(()=>{}),this.updateMeta()}updateMeta(e={}){this.options={...this.options,...e},this.id="chapter-"+(e.id??this.number),this.view.frame&&(this.view.frame.id=this.id),this.view.link&&(this.view.link.href="#"+this.id),this.options.name&&this.view.linkText&&(this.view.linkText.innerHTML="Chapter "+this.number+": "+this.options.name)}fetch(){return fetch(this.options.link).then(e=>e.json()).then(e=>{if(Array.isArray(e)&&(e={content:e}),!Array.isArray(e.content))throw new Error("Invalid quest list in "+this.options.link);this.updateMeta(e);let t=0;for(let s of e.content)this.quests.push(new W(s,{chapter:this,number:++t}));return this})}addSolved(e){this.solved.has(e)||(this.solved.add(e),this.showStatus())}getProgress(){return{total:this.quests.length,solved:this.solved.size,complete:this.solved.size===this.quests.length,percentage:Math.round(this.solved.size/this.quests.length*100)}}attach(e,t){return this.view.frame=c(e,"div",{class:["ski-quest-chapter"]}),this.view.frame.id=this.id,t.placeholder&&(this.view.placeholder=c(this.view.frame,"div",{content:t.placeholder})),this}draw(){this.visible=!0,this.view.placeholder?.remove();let e=c(this.view.frame,"h2"),t=c(this.view.frame,"div");c(e,"span",{content:"Chapter "+this.number+": "+this.options.name}),this.view.stat=c(e,"span",{class:["ski-quest-float-right"]}),e.onclick=()=>{Ke(t,this.visible=!this.visible)},this.view.intro=c(t,"div",{content:Qe(this.options.intro),class:["ski-quest-note","ski-quest-chapter-intro"]}),this.view.content=c(t,"div",{class:["ski-quest-chapter-content"]});for(let s of this.quests)s.load(),s.draw(this.view.content);this.showStatus()}showStatus(){if(!this.view.stat)return;let e=this.getProgress();this.view.stat.innerHTML="Progress: "+e.solved+"/"+e.total+" ("+e.percentage+"%)",e.complete&&this.view.stat.classList.add("success"),this.view.progressbar&&(this.view.progressbar.style.paddingRight=e.percentage+"%",this.view.progressbar.style.marginRight=-e.percentage+"%")}addLink(e){let t=c(e,"div",{class:["ski-quest-nav-item"]}),s=c(t,"a",{},n=>{n.style.display="flex"});s.href="#"+this.id,this.view.link=s,this.view.progressbar=c(s,"span",{class:["ski-quest-progressbar"]}),this.view.linkText=c(s,"span",{content:"Chapter "+this.number+"..."})}};function xt(i,e,t){let s=c(i,"span",{}),n=c(s,"span",{content:e,class:["ski-quest-hint"]});n.onclick=()=>{n.remove(),c(s,"span",{content:t})}}function Qe(i){return Array.isArray(i)?i.join(" "):""+i}function wt(i){return i instanceof Q.classes.Expr?i instanceof Q.classes.Alias?i.name+" = "+i.expand():""+i.expand():""+i}function Ke(i,e){e===void 0&&(e=i.hidden),i.hidden=!e}function bt(i){return i.note??(i.impl??i).format({html:!0,lambda:[""," &mapsto; ",""]})}De.exports={QuestPage:ge,QuestChapter:J,QuestBox:W}});var Et=C(()=>{var{QuestBox:vt,QuestChapter:yt,QuestPage:kt}=Ue();typeof window<"u"&&(window.QuestBox=vt,window.QuestChapter=yt,window.QuestPage=kt)});Et();})();
4
4
  //# sourceMappingURL=ski-quest.min.js.map