├── .gitignore ├── .gitlab-ci.yml ├── apl.js ├── examples ├── 0-rho-iota.apl ├── 0-rho-iota.out ├── 1-mult.apl ├── 1-mult.out ├── 2-sierpinski.apl ├── 2-sierpinski.out ├── 3-primes.apl ├── 3-primes.out ├── 4-life.apl ├── 4-life.out ├── 5-rule30.apl ├── 5-rule30.out ├── 6-queens.apl ├── 6-queens.out ├── 7-mandelbrot.apl ├── 7-mandelbrot.out └── test ├── icons └── apl-logo.png ├── index.html ├── licence ├── manifest.json ├── ngn-apl-screenshot.png ├── readme.md ├── serviceWorker.js ├── t.apl ├── t.js └── web ├── Apl385.woff ├── index.html ├── index.js └── lb.js /.gitignore: -------------------------------------------------------------------------------- 1 | testing/ 2 | util.sh 3 | 4 | # Created by https://www.toptal.com/developers/gitignore/api/macos 5 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos 6 | 7 | ### macOS ### 8 | # General 9 | .DS_Store 10 | .AppleDouble 11 | .LSOverride 12 | 13 | # Icon must end with two \r 14 | Icon 15 | 16 | 17 | # Thumbnails 18 | ._* 19 | 20 | # Files that might appear in the root of a volume 21 | .DocumentRevisions-V100 22 | .fseventsd 23 | .Spotlight-V100 24 | .TemporaryItems 25 | .Trashes 26 | .VolumeIcon.icns 27 | .com.apple.timemachine.donotpresent 28 | 29 | # Directories potentially created on remote AFP share 30 | .AppleDB 31 | .AppleDesktop 32 | Network Trash Folder 33 | Temporary Items 34 | .apdisk 35 | 36 | ### macOS Patch ### 37 | # iCloud generated files 38 | *.icloud 39 | 40 | # End of https://www.toptal.com/developers/gitignore/api/macos -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | pages: 2 | stage: deploy 3 | script: 4 | - mkdir .public 5 | - cp -r * .public 6 | - mv .public public 7 | artifacts: 8 | paths: 9 | - public 10 | only: 11 | - master 12 | -------------------------------------------------------------------------------- /apl.js: -------------------------------------------------------------------------------- 1 | //usr/bin/env node "$0" $@;exit $? 2 | 'use strict' 3 | const prelude=` 4 | ⍬←() ⋄ ⎕d←'0123456789' ⋄ ⎕a←'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 5 | ~←~⍠{(~⍺∊⍵)/⍺} 6 | _atop←{⍶⍹⍵;⍶⍺⍹⍵} 7 | ↑←{0=⍴⍴⍵:⊃⍵ ⋄ 0=×/⍴⍵:⍵ ⋄ shape←⍴⍵ ⋄ ⍵←,⍵ ⋄ r←⌈/≢¨shapes←⍴¨⍵ ⋄ max←⊃⌈/shapes←(⍴↓(r⍴1)∘,)¨shapes 8 | (shape,max)⍴⊃⍪/shapes{max↑⍺⍴⍵}¨⍵}⍠↑ 9 | ⊃←⊃⍠{;1<⍴⍴⍺:↗'RANK ERROR' ⋄ x←⍵ 10 | {1<⍴⍴⍵:↗'RANK ERROR' ⋄ ⍵←,⍵ ⋄ (⍴⍵)≠⍴⍴x:↗'RANK ERROR' ⋄ ∨/⍵≥⍴x:↗'INDEX ERROR' ⋄ x←⊃⍵⌷x}¨⍺ 11 | x} 12 | ⊂←⊂⍠{1<⍴⍴⍺:↗'RANK ERROR' ⋄ 1≠⍴⍴⍵:↗'NONCE ERROR' ⋄ ⍺←,⍺=0 13 | keep←~1 1⍷⍺ ⋄ sel←keep/⍺ ⋄ dat←keep/⍵ 14 | {1=1↑sel:{sel←1↓sel ⋄ dat←1↓dat}⍬}⍬ 15 | {1=¯1↑sel:{sel←¯1↓sel ⋄ dat←¯1↓dat}⍬}⍬ 16 | sel←(⍴sel),⍨sel/⍳⍴sel ⋄ drop←0 17 | sel{∆←drop↓⍺↑⍵ ⋄ drop←⍺+1 ⋄ ∆}¨⊂dat} 18 | ↓←{0=⍴⍴⍵:⍵ ⋄ ⊂[¯1+⍴⍴⍵]⍵ 19 | ; 20 | 1<⍴⍴⍺:↗'RANK ERROR' ⋄ a←,⍺ ⋄ ⍵←{0=⍴⍴⍵:((⍴a)⍴1)⍴⍵ ⋄ ⍵}⍵ 21 | (⍴a)>⍴⍴⍵:↗'RANK ERROR' ⋄ a←(⍴⍴⍵)↑a ⋄ a←((a>0)×0⌊a-⍴⍵)+(a≤0)×0⌈a+⍴⍵ ⋄ a↑⍵} 22 | ⍪←{(≢⍵)(×/1↓⍴⍵)⍴⍵ ; ⍺,[0]⍵} 23 | ⊢←{⍵} ⋄ ⊣←{⍵;⍺} 24 | ≢←{⍬⍴(⍴⍵),1; ~⍺≡⍵} 25 | ,←{(×/⍴⍵)⍴⍵}⍠, 26 | ⌹←{norm←{(⍵+.×+⍵)*0.5} 27 | QR←{n←(⍴⍵)[1] ⋄ 1≥n:{t←norm,⍵ ⋄ (⍵÷t)(⍪t)}⍵ ⋄ m←⌈n÷2 ⋄ a0←((1↑⍴⍵),m)↑⍵ ⋄ a1←(0,m)↓⍵ ⋄ (q0 r0)←∇a0 28 | c←(+⍉q0)+.×a1 ⋄ (q1 r1)←∇a1-q0+.×c ⋄ (q0,q1)((r0,c)⍪((⌊n÷2),-n)↑r1)} 29 | Rinv←{1=n←1↑⍴⍵:÷⍵ ⋄ m←⌈n÷2 ⋄ ai←∇(m,m)↑⍵ ⋄ di←∇(m,m)↓⍵ ⋄ b←(m,m-n)↑⍵ ⋄ bx←-ai+.×b+.×di ⋄ (ai,bx)⍪((⌊n÷2),-n)↑di} 30 | 0=⍴⍴⍵:÷⍵ ⋄ 1=⍴⍴⍵:,∇⍪⍵ ⋄ 2≠⍴⍴⍵:↗'RANK ERROR' ⋄ 0∊≥/⍴⍵:↗'LENGTH ERROR' ⋄ (Q R)←QR ⍵ ⋄ (Rinv R)+.×+⍉Q 31 | ; 32 | (⌹⍵)+.×⍺} 33 | ⍨←{⍵⍶⍵;⍵⍶⍺} 34 | ≈←{1e¯14>|⍺-⍵} 35 | ` 36 | 37 | ,A=(a,s=[a.length])=>{ 38 | if(a.length&&a instanceof Array){ 39 | let t=1;for(let i=0;i{let r=Array(s.length),u=1;for(let i=r.length-1;i>=0;i--){asrt(isInt(s[i],0));r[i]=u;u*=s[i]};return r} 46 | ,toInt=(x,m,M)=>{let r=unw(x);if(r!==r|0||m!=null&&r{x.s.length>1&&rnkErr();for(let i=0;i!x.s.length&&!x.a[0].isA 49 | ,unw=x=>{x.a.length===1||lenErr();return x.a[0]} // unwrap 50 | ,getProt=x=>!x.a.length||typeof x.a[0]!=='string'?0:' ' // todo 51 | ,asrt=x=>{if(typeof x==='function'){if(!x())throw Error('assertion failed: '+x)} 52 | else {if(!x) throw Error('assertion failed' )}} 53 | ,isInt=(x,m,M)=>x===~~x&&(m==null||m<=x&&(M==null||x{let r=1;for(let i=0;i{for(let k in y)x[k]=y[k];return x} 56 | ,fmtNum=x=>(''+x).replace('Infinity','∞').replace(/-/g,'¯') 57 | ,rpt=(x,n)=>{ 58 | let m=n*x.length;if(!m)return x.slice(0,0) 59 | if(x.set){let r=new(x.constructor)(x.length);r.set(x);while(n{ 63 | let m 64 | if(o&&o.aplCode&&o.offset!=null){ 65 | let a=o.aplCode.slice(0,o.offset).split('\n') 66 | let l=a.length,c=1+(a[a.length-1]||'').length // line and column 67 | m='\n'+(o.file||'-')+':'+l+':'+c+o.aplCode.split('\n')[l-1]+'_'.repeat(c-1)+'^' 68 | } 69 | let e=Error(m);e.name=s;for(let k in o)e[k]=o[k];throw e 70 | } 71 | ,synErr=o=>err('SYNTAX ERROR',o) 72 | ,domErr=o=>err('DOMAIN ERROR',o) 73 | ,lenErr=o=>err('LENGTH ERROR',o) 74 | ,rnkErr=o=>err( 'RANK ERROR',o) 75 | ,idxErr=o=>err( 'INDEX ERROR',o) 76 | ,nyiErr=o=>err( 'NONCE ERROR',o) 77 | ,valErr=o=>err( 'VALUE ERROR',o) 78 | 79 | A.bool=[A.zero=A(new Float64Array([0]),[]), 80 | A.one =A(new Float64Array([1]),[])] 81 | A.zld=A(new Float64Array(),[0]) 82 | A.scal=x=>A([x],[]) 83 | 84 | const Zify=x=>typeof x==='number'?new Z(x,0):x instanceof Z?x:domErr() // complexify 85 | const smplfy=(re,im)=>im===0?re:new Z(re,im) 86 | function Z(re,im){asrt(typeof re==='number');asrt(typeof im==='number'||im==null) 87 | if(re!==re||im!==im)domErr(); this.re=re;this.im=im||0} 88 | Z.prototype.toString=function(){return fmtNum(this.re)+'J'+fmtNum(this.im)} 89 | Z.prototype.repr=function(){return'new Z('+repr(this.re)+','+repr(this.im)+')'} 90 | Z.exp=x=>{x=Zify(x);let r=Math.exp(x.re);return smplfy(r*Math.cos(x.im),r*Math.sin(x.im))} 91 | Z.log=x=>{if(typeof x==='number'&&x>0){return Math.log(x)} 92 | else{x=Zify(x);return smplfy(Math.log(Math.sqrt(x.re*x.re+x.im*x.im)),Z.dir(x))}} 93 | Z.cjg=x=>new Z(x.re,-x.im) 94 | Z.neg=x=>new Z(-x.re,-x.im) 95 | Z.add=(x,y)=>{x=Zify(x);y=Zify(y);return smplfy(x.re+y.re,x.im+y.im)} 96 | Z.sub=(x,y)=>{x=Zify(x);y=Zify(y);return smplfy(x.re-y.re,x.im-y.im)} 97 | Z.mul=(x,y)=>{x=Zify(x);y=Zify(y);return smplfy(x.re*y.re-x.im*y.im,x.re*y.im+x.im*y.re)} 98 | Z.div=(x,y)=>{x=Zify(x);y=Zify(y);const d=y.re*y.re+y.im*y.im 99 | return smplfy((x.re*y.re+x.im*y.im)/d,(y.re*x.im-y.im*x.re)/d)} 100 | Z.it =x=>{x=Zify(x);return smplfy(-x.im,x.re)} // i times 101 | Z.nit=x=>{x=Zify(x);return smplfy(x.im,-x.re)} // -i times 102 | Z.pow=(x,y)=>{ 103 | if(typeof x==='number'&&typeof y==='number'&&(x>=0||isInt(y)))return Math.pow(x,y) 104 | if(typeof y==='number'&&isInt(y,0)){let r=1;while(y){(y&1)&&(r=Z.mul(r,x));x=Z.mul(x,x);y>>=1};return r} 105 | if(typeof x==='number'&&y===.5)return x<0?new Z(0,Math.sqrt(-x)):Math.sqrt(x) 106 | return Z.exp(Z.mul(y,Z.log(x))) 107 | } 108 | Z.sqrt=x=>Z.pow(x,.5) 109 | Z.mag=x=>Math.sqrt(x.re*x.re+x.im*x.im) 110 | Z.dir=x=>Math.atan2(x.im,x.re) 111 | Z.sin=x=>Z.nit(Z.sh(Z.it(x))) 112 | Z.cos=x=>Z.ch(Z.it(x)) 113 | Z.tg =x=>Z.nit(Z.th(Z.it(x))) 114 | Z.asin=x=>{x=Zify(x);return Z.nit(Z.log(Z.add(Z.it(x),Z.sqrt(Z.sub(1,Z.pow(x,2))))))} 115 | Z.acos=x=>{x=Zify(x);const r=Z.nit(Z.log(Z.add(x,Z.sqrt(Z.sub(Z.pow(x,2),1))))) 116 | return r instanceof Z&&(r.re<0||(r.re===0&&r.im<0))?Z.neg(r):r} // dubious? 117 | Z.atg=x=>{x=Zify(x);const ix=Z.it(x);return Z.mul(new Z(0,.5),Z.sub(Z.log(Z.sub(1,ix)),Z.log(Z.add(1,ix))))} 118 | Z.sh=x=>{let a=Z.exp(x);return Z.mul(.5,Z.sub(a,Z.div(1,a)))} 119 | Z.ch=x=>{let a=Z.exp(x);return Z.mul(.5,Z.add(a,Z.div(1,a)))} 120 | Z.th=x=>{let a=Z.exp(x),b=Z.div(1,a);return Z.div(Z.sub(a,b),Z.add(a,b))} 121 | Z.ash=x=>Z.it(Z.asin(Z.nit(x))) 122 | Z.ach=x=>{x=Zify(x);let sign=x.im>0||(!x.im&&x.re<=1)?1:-1;return Z.mul(new Z(0,sign),Z.acos(x))} 123 | Z.ath=x=>Z.it(Z.atg(Z.nit(x))) 124 | Z.floor=x=>{ 125 | if(typeof x==='number')return Math.floor(x) 126 | x=Zify(x) 127 | let re=Math.floor(x.re),im=Math.floor(x.im),r=x.re-re,i=x.im-im 128 | if(r+i>=1)r>=i?re++:im++ 129 | return smplfy(re,im) 130 | } 131 | Z.ceil=x=>{ 132 | if(typeof x==='number')return Math.ceil(x) 133 | x=Zify(x);let re=Math.ceil(x.re),im=Math.ceil(x.im),r=re-x.re,i=im-x.im 134 | if(r+i>=1)r>=i?re--:im-- 135 | return smplfy(re,im) 136 | } 137 | const iszero=x=>!x||(x instanceof Z&&!x.re&&!x.im) 138 | Z.mod=(x,y)=>typeof x==='number'&&typeof y==='number'?(x?y-x*Math.floor(y/x):y) 139 | :iszero(x)?y:Z.sub(y,Z.mul(x,Z.floor(Z.div(y,x)))) 140 | Z.isint=x=>typeof x==='number'?x===Math.floor(x):x.re===Math.floor(x.re)&&x.im===Math.floor(x.im) 141 | Z.gcd=(x,y)=>{ 142 | if(typeof x==='number'&&typeof y==='number'){while(y){let z=y;y=x%y;x=z}return Math.abs(x)} 143 | while(!iszero(y)){let z=y;y=Z.mod(y,x);x=z} 144 | if(typeof x==='number'){return Math.abs(x)} // rotate into first quadrant 145 | else{x.re<0&&(x=Z.neg(x));x.im<0&&(x=Z.it(x));return x.re?x:x.im} 146 | } 147 | Z.lcm=(x,y)=>{let p=Z.mul(x,y);return iszero(p)?p:Z.div(p,Z.gcd(x,y))} 148 | 149 | const LDC=1,VEC=2,GET=3,SET=4,MON=5,DYA=6,LAM=7,RET=8,POP=9,SPL=10,JEQ=11,EMB=12,CON=13 150 | ,Proc=function(b,p,size,h){this.b=b;this.p=p;this.size=size;this.h=h;this.toString=_=>'#procedure'} 151 | ,toFn=f=>(x,y)=>vm(f.b,f.h.concat([[x,f,y,null]]),f.p) 152 | ,vm=(b,h,p=0,t=[])=>{while(1)switch(b[p++]){default:asrt(0) // b:bytecode,h:environment,p:program counter,t:stack 153 | case LDC:t.push(b[p++]);break 154 | case VEC:{let a=t.splice(t.length-b[p++]);for(let i=0;i{t.push(r);vm(b,h,p,t)});return} 161 | t.push(f(x))} 162 | else{let bp=t.length;t.push(b,p,h);b=f.b;p=f.p;h=f.h.concat([[x,f,null,bp]])} 163 | break} 164 | case DYA:{let[y,f,x]=t.splice(-3) 165 | if(typeof f==='function'){if(y instanceof Proc)y=toFn(y) 166 | if(x instanceof Proc)x=toFn(x) 167 | if(f.cps){f(y,x,undefined,r=>{t.push(r);vm(b,h,p,t)});return} 168 | t.push(f(y,x))} 169 | else{let bp=t.length;t.push(b,p,h);b=f.b;p=f.p;h=f.h.concat([[y,f,x,bp]])} 170 | break} 171 | case LAM:{let size=b[p++];t.push(new Proc(b,p,size,h));p+=size;break} 172 | case RET:{if(t.length===1)return t[0];[b,p,h]=t.splice(-4,3);break} 173 | case POP:{t.pop();break} 174 | case SPL:{let n=b[p++],a=t[t.length-1].a.slice().reverse(),a1=Array(a.length) 175 | for(let i=0;ix.slice()),t:t.slice(0,frm[3]),p:frm[1].p+frm[1].size-1} 181 | asrt(b[cont.p]===RET);t.push(r=>{b=cont.b;h=cont.h;t=cont.t;p=cont.p;t.push(r)});break} 182 | }} 183 | const ltr='_A-Za-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶ-ͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮ-ٯٱ-ۓەۥ-ۦۮ-ۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴ-ߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএ-ঐও-নপ-রলশ-হঽৎড়-ঢ়য়-ৡৰ-ৱਅ-ਊਏ-ਐਓ-ਨਪ-ਰਲ-ਲ਼ਵ-ਸ਼ਸ-ਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલ-ળવ-હઽૐૠ-ૡଅ-ଌଏ-ଐଓ-ନପ-ରଲ-ଳଵ-ହଽଡ଼-ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கங-சஜஞ-டண-தந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘ-ౙౠ-ౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠ-ೡೱ-ೲഅ-ഌഎ-ഐഒ-ഺഽൎൠ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะา-ำเ-ๆກ-ຂຄງ-ຈຊຍດ-ທນ-ຟມ-ຣລວສ-ຫອ-ະາ-ຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥ-ၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮ-ᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵ-ᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎↃ-ↄⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲ-ⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々-〆〱-〵〻-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪ-ꘫꙀ-ꙮꙿ-ꚗꚠ-ꛥꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵ-ꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ' 184 | ,td=[['-',/^ +|^[⍝#].*/], // whitespace or comment 185 | ['N',/^¯?(?:\d*\.?\d+(?:e[+¯]?\d+)?|¯|∞)(?:j¯?(?:\d*\.?\d+(?:e[+¯]?\d+)?|¯|∞))?/i], // number 186 | ['S',/^(?:'[^']*')+/], // string 187 | ['.',/^[\(\)\[\]\{\}:;←⋄\n]/], // punctuation 188 | ['J',/^«[^»]*»/], // JS literal 189 | ['X',RegExp('^(?:⎕?['+ltr+']['+ltr+'0-9]*|⍺⍺|⍵⍵|∇∇|[^¯\'":«»])','i')]] // identifier 190 | ,prs=(s,o)=>{ 191 | // tokens are {t:type,v:value,o:offset,s:aplCode} 192 | // "stk" tracks bracket nesting and causes '\n' tokens to be dropped when the latest unclosed bracket is '(' or '[' 193 | let i=0,a=[],stk=['{'],l=s.length // i:offset in s, a:tokens 194 | while(ia[i].t===x?i++:prsErr() 207 | ,prsErr=x=>synErr({file:o.file,offset:a[i].o,aplCode:s}) 208 | ,body=_=>{ 209 | let r=['B'] 210 | while(1){ 211 | while('⋄\n'.includes(a[i].t))i++ 212 | if('$};'.includes(a[i].t))return r 213 | let e=expr();if(a[i].t===':'){i++;e=[':',e,expr()]} 214 | r.push(e) 215 | } 216 | } 217 | ,expr=_=>{ 218 | let r=['.'],x 219 | while(1){ 220 | if('NSXJ'.includes(a[i].t)){x=[a[i].t,a[i].v];i++} 221 | else if(a[i].t==='('){i++;if(a[i].t===')'){i++;x=['⍬']}else{x=expr();dmnd(')')}} 222 | else if(a[i].t==='{'){i++;x=['{',body()];while(a[i].t===';'){i++;x.push(body())}dmnd('}')} 223 | else{prsErr()} 224 | if(a[i].t==='['){ 225 | i++;x=['[',x] 226 | while(1){if(a[i].t===';'){i++;x.push(null)} 227 | else if(a[i].t===']'){x.push(null);break} 228 | else{x.push(expr());if(a[i].t===']'){break}else{dmnd(';')}}} 229 | dmnd(']') 230 | } 231 | if(a[i].t==='←'){i++;return r.concat([['←',x,expr()]])} 232 | r.push(x);if(')]}:;⋄\n$'.includes(a[i].t))return r 233 | } 234 | } 235 | return[body(),dmnd('$')][0] 236 | } 237 | const voc={} 238 | ,perv=(f1,f2)=>{ // pervasive f1:monad, f2:dyad 239 | let g1=!f1?nyiErr:x=>{ 240 | if(x.isA){let r=Array(x.a.length);for(let i=0;i{switch((!x.isA?10:x.a.length===1?20:30)+(!y.isA?1:y.a.length===1?2:3)){ 244 | case 11:{let r=f2(x,y);typeof r==='number'&&r!==r&&domErr();return r} 245 | case 12:case 13:{const n=y.a.length,r=Array(n);for(let i=0;iy.s.length?x.s:y.s) 248 | case 23:{const xi=x.a[0],n=y.a.length,r=Array(n);for(let i=0;ix?g2(x,y):g1(y) 254 | } 255 | ,real=f=>(x,y,h)=>typeof x!=='number'||y!=null&&typeof y!=='number'?domErr():f(x,y,h) 256 | ,numeric=(f,g)=>(x,y,h)=>(typeof x!=='number'||y!=null&&typeof y!=='number'?g(Zify(x),y==null?y:Zify(y),h):f(x,y,h)) 257 | ,match=(x,y)=>{ 258 | if(x.isA){ 259 | if(!y.isA||x.s!=''+y.s)return 0 260 | let r=1,n=x.a.length;for(let i=0;ix===y||Math.abs(x-y)<1e-11 // approximate equality for numbers 269 | ,aprx=(x,y)=>{ // like match(), but approximate 270 | if(x.isA){ 271 | if(!y.isA)return 0 272 | if(x.s.length!==y.s.length)return 0 273 | if(x.s!=''+y.s)return 0 274 | let r=1,n=x.a.length;for(let i=0;i(x&1)!==x?domErr():x 286 | ,withId=(x,f)=>{f.identity=x.isA?x:A.scal(x);return f} 287 | ,adv =f=>{f.adv =1;return f} 288 | ,conj=f=>{f.conj=1;return f} 289 | ,cps =f=>{f.cps =1;return f} 290 | 291 | voc['+']=withId(0,perv( 292 | numeric(x=>x,Z.cjg), 293 | numeric((x,y)=>x+y,Z.add) 294 | )) 295 | voc['-']=withId(0,perv( 296 | numeric(x=>-x,Z.neg), 297 | numeric((x,y)=>x-y,Z.sub) 298 | )) 299 | voc['×']=withId(1,perv( 300 | numeric(x=>(x>0)-(x<0),x=>{let d=Math.sqrt(x.re*x.re+x.im*x.im);return smplfy(x.re/d,x.im/d)}), 301 | numeric((x,y)=>x*y,Z.mul) 302 | )) 303 | voc['÷']=withId(1,perv( 304 | numeric(x=>1/x, 305 | x=>{let d=x.re*x.re+x.im*x.im;return smplfy(x.re/d,-x.im/d)}), 306 | numeric((x,y)=>x/y,Z.div) 307 | )) 308 | voc['*']=withId(1,perv( 309 | numeric(Math.exp,Z.exp), 310 | Z.pow 311 | )) 312 | voc['⍟']=perv( 313 | Z.log, 314 | (x,y)=>typeof x==='number'&&typeof y==='number'&&x>0&&y>0?Math.log(y)/Math.log(x):Z.div(Z.log(y),Z.log(x)) 315 | ) 316 | voc['|']=withId(0,perv( 317 | numeric(x=>Math.abs(x),Z.mag), 318 | Z.mod 319 | )) 320 | voc['⍀']=adv((y,x,h)=>voc['\\'](y,x,h||A.zero)) 321 | voc['\\']=adv((y,x,h)=>{ 322 | if(typeof y==='function'){ 323 | asrt(typeof x==='undefined') 324 | let f=y 325 | return(y,x)=>{ 326 | asrt(x==null) 327 | if(!y.s.length)return y 328 | h=h?toInt(h,0,y.s.length):y.s.length-1 329 | const ni=prd(y.s.slice(0,h)), nj=y.s[h], nk=prd(y.s.slice(h+1)), r=Array(ni*nj*nk) 330 | if(r.length)for(let i=0;i=0;l--){let v=y.a[(i*nj+l)*nk+k];u=f(u,v.isA?v:A.scal(v))} 333 | r[(i*nj+j)*nk+k]=u.s.length?u:unw(u) 334 | } 335 | return A(r,y.s) 336 | } 337 | }else{ 338 | y.s.length||nyiErr() 339 | h=h?toInt(h,0,y.s.length):y.s.length-1 340 | x.s.length>1&&rnkErr() 341 | let b=[],i=0,s=y.s.slice();s[h]=x.a.length 342 | for(let j=0;j0?i++:null)} 343 | i===y.s[h]||lenErr() 344 | let r=[],xd=strides(y.s) 345 | if(s[h]&&y.a.length){ 346 | let filler=getProt(y),p=0,ind=rpt([0],s.length) 347 | while(1){ 348 | r.push(b[ind[h]]==null?filler:y.a[p+b[ind[h]]*xd[h]]) 349 | let i=s.length-1;while(i>=0&&ind[i]+1===s[i]){if(i!==h)p-=xd[i]*ind[i];ind[i--]=0} 350 | if(i<0)break 351 | if(i!==h)p+=xd[i] 352 | ind[i]++ 353 | } 354 | } 355 | return A(r,s) 356 | } 357 | }) 358 | voc['○']=perv( 359 | numeric(x=>Math.PI*x,x=>new Z(Math.PI*x.re,Math.PI*x.im)), 360 | (i,x)=>{ 361 | if(typeof x==='number'){ 362 | switch(i){ 363 | case-12:return Z.exp(smplfy(0,x)) 364 | case-11:return smplfy(0,x) 365 | case-10:return x 366 | case -9:return x 367 | case -8:return smplfy(0,-Math.sqrt(1+x*x)) 368 | case -7:return Z.ath(x) 369 | case -6:return Z.ach(x) 370 | case -5:return Z.ash(x) 371 | case -4:let t=Z.sqrt(x*x-1);return x<-1?-t:t 372 | case -3:return Z.atg(x) 373 | case -2:return Z.acos(x) 374 | case -1:return Z.asin(x) 375 | case 0:return Z.sqrt(1-x*x) 376 | case 1:return Math.sin(x) 377 | case 2:return Math.cos(x) 378 | case 3:return Math.tan(x) 379 | case 4:return Math.sqrt(1+x*x) 380 | case 5:{let a=Math.exp(x),b=1/a;return(a-b)/2} // sh 381 | case 6:{let a=Math.exp(x),b=1/a;return(a+b)/2} // ch 382 | case 7:{let a=Math.exp(x),b=1/a;return(a-b)/(a+b)} // th 383 | case 8:return Z.sqrt(-1-x*x) 384 | case 9:return x 385 | case 10:return Math.abs(x) 386 | case 11:return 0 387 | case 12:return 0 388 | default:domErr() 389 | } 390 | }else if(x instanceof Z){ 391 | switch(i){ 392 | case -12:return Z.exp(smplfy(-x.im,x.re)) 393 | case -11:return Z.it(x) 394 | case -10:return Z.cjg(x) 395 | case -9:return x 396 | case -8:return Z.neg(Z.sqrt(Z.sub(-1,Z.mul(x,x)))) 397 | case -7:return Z.ath(x) 398 | case -6:return Z.ach(x) 399 | case -5:return Z.ash(x) 400 | case -4:if(x.re===-1&&!x.im){return 0}else{let a=Z.add(x,1);return Z.mul(a,Z.sqrt(Z.div(Z.sub(x,1),a)))} 401 | case -3:return Z.atg(x) 402 | case -2:return Z.acos(x) 403 | case -1:return Z.asin(x) 404 | case 0:return Z.sqrt(Z.sub(1,Z.mul(x,x))) 405 | case 1:return Z.sin(x) 406 | case 2:return Z.cos(x) 407 | case 3:return Z.tg(x) 408 | case 4:return Z.sqrt(Z.add(1,Z.mul(x,x))) 409 | case 5:return Z.sh(x) 410 | case 6:return Z.ch(x) 411 | case 7:return Z.th(x) 412 | case 8:return Z.sqrt(Z.sub(-1,Z.mul(x,x))) 413 | case 9:return x.re 414 | case 10:return Z.mag(x) 415 | case 11:return x.im 416 | case 12:return Z.dir(x) 417 | default:domErr() 418 | } 419 | }else{ 420 | domErr() 421 | } 422 | } 423 | ) 424 | voc[',']=(y,x,h)=>{ 425 | x||nyiErr() 426 | let nAxes=Math.max(x.s.length,y.s.length) 427 | if(h){h=unw(h);typeof h!=='number'&&domErr();nAxes&&!(-10;i--)stride[i-1]=stride[i]*s[i] 440 | let d=stride;if(!isInt(h)){d=stride.slice();d.splice(Math.ceil(h),1)} 441 | if(x.a.length){ // p:pointer in result, q:pointer in x.a 442 | let p=0,q=0,i=new Int32Array(x.s.length),xd=strides(x.s) 443 | while(1){ 444 | r[p]=x.a[q] 445 | let a=i.length-1;while(a>=0&&i[a]+1===x.s[a]){q-=i[a]*xd[a];p-=i[a]*d[a];i[a--]=0} 446 | if(a<0)break 447 | q+=xd[a];p+=d[a];i[a]++ 448 | } 449 | } 450 | if(y.a.length){ // p:pointer in result, q:pointer in y.a 451 | let p=isInt(h)?stride[h]*x.s[h]:stride[Math.ceil(h)],q=0,i=new Int32Array(y.s.length),yd=strides(y.s) 452 | while(1){ 453 | r[p]=y.a[q] 454 | let a=i.length-1;while(a>=0&&i[a]+1===y.s[a]){q-=i[a]*yd[a];p-=i[a]*d[a];i[a--]=0} 455 | if(a<0)break 456 | q+=yd[a];p+=d[a];i[a]++ 457 | } 458 | } 459 | return A(r,s) 460 | } 461 | let eq 462 | voc['=']=withId(1,perv(null,eq=(x,y)=>+(x instanceof Z&&y instanceof Z?x.re===y.re&&x.im===y.im:x===y))) 463 | voc['≠']=withId(0,perv(null,(x,y)=>1-eq(y,x))) 464 | voc['<']=withId(0,perv(null,real((x,y)=>+(x< y)))) 465 | voc['>']=withId(0,perv(null,real((x,y)=>+(x> y)))) 466 | voc['≤']=withId(1,perv(null,real((x,y)=>+(x<=y)))) 467 | voc['≥']=withId(1,perv(null,real((x,y)=>+(x>=y)))) 468 | voc['≡']=(y,x)=>x?A.bool[+match(y,x)]:A([depth(y)],[]) 469 | const depth=x=>{if(!x.isA||!x.s.length&&!x.a[0].isA)return 0 470 | let r=0,n=x.a.length;for(let i=0;i{ 472 | if(typeof f==='function'){if(typeof g==='function'){return(y,x)=>f(g(y),x)} // f∘g 473 | else{return(y,x)=>{x==null||synErr();return f(g,y)}}} // f∘B 474 | else{asrt(typeof g==='function');return(y,x)=>{x==null||synErr();return g(y,f)}} // A∘g 475 | }) 476 | voc['∪']=(y,x)=>{ 477 | if(x){ 478 | if(x.s.length>1||y.s.length>1)rnkErr() 479 | let m=x.a.length,n=y.a.length,r=Array(m) 480 | for(let i=0;i1)rnkErr() 485 | let r=[],n=y.a.length;for(let i=0;i{x||nyiErr();if(x.s.length>1||y.s.length>1)rnkErr() 489 | let r=[],n=x.a.length;for(let i=0;i{for(let i=0;i{ 492 | asrt(x) 493 | if(!x.s.length)x=A([unw(x)]) 494 | if(!y.s.length)y=A([unw(y)]) 495 | let lastDimA=x.s[x.s.length-1],firstDimB=y.s[0] 496 | if(lastDimA!==1&&firstDimB!==1&&lastDimA!==firstDimB)lenErr() 497 | let r=[],ni=x.a.length/lastDimA,nj=y.a.length/firstDimB 498 | for(let i=0;if===voc['∘']?oprd(g):iprd(g,f)) 509 | const oprd=f=>{ // outer product 510 | asrt(typeof f==='function') 511 | return(y,x)=>{ 512 | x||synErr() 513 | const m=x.a.length,n=y.a.length,r=Array(m*n) 514 | for(let i=0;i{ // inner product: A f.g B <-> f/¨(⊂[¯1+⍴⍴A]A)∘.g⊂[0]B 523 | let F=voc['¨'](voc['/'](f)),G=oprd(g) 524 | return(y,x)=>{if(!x.s.length)x=A([unw(x)]) 525 | if(!y.s.length)y=A([unw(y)]) 526 | return F(G(voc['⊂'](y,undefined,A([0])), 527 | voc['⊂'](x,undefined,A([x.s.length-1]))))} 528 | } 529 | voc['¨']=adv((f,g)=>{ 530 | asrt(typeof f==='function');asrt(g==null) 531 | return(y,x)=>{ 532 | if(!x){ 533 | const n=y.a.length,r=Array(n) 534 | for(let i=0;i{ 553 | x||synErr() 554 | let s=x.s.concat(y.s),r=Array(prd(s)),n=x.s.length?x.s[0]:1,m=x.a.length/n 555 | for(let i=0;i=0;k--){let u=x.a[k*m+i];r[(k*m+i)*y.a.length+j]=iszero(u)?v:Z.mod(u,v) 558 | v=iszero(u)?0:Z.div(Z.sub(v,Z.mod(u,v)),u)} 559 | } 560 | return A(r,s) 561 | } 562 | voc['∊']=(y,x)=>{ 563 | if(x){ 564 | let r=new Float64Array(x.a.length) 565 | for(let i=0;i{if(x.isA){const n=x.a.length;for(let i=0;i!isInt(x)?Γ(x+1):x<0?domErr():x{ 575 | let r // Neg int? 576 | switch(4*negInt(k)+2*negInt(n)+negInt(n-k)){ // ⍺ ⍵ ⍵-⍺ 577 | case 0:r=Math.exp(lnΓ(n+1)-lnΓ(k+1)-lnΓ(n-k+1)) ;break // 0 0 0 (!⍵)÷(!⍺)×!⍵-⍺ 578 | case 1:r=0 ;break // 0 0 1 0 579 | case 2:r=domErr() ;break // 0 1 0 domain error 580 | case 3:r=Math.pow(-1,k)*Beta(k,k-n-1) ;break // 0 1 1 (¯1*⍺)×⍺!⍺-⍵+1 581 | case 4:r=0 ;break // 1 0 0 0 582 | case 5:asrt(0) ;break // 1 0 1 cannot arise 583 | case 6:r=Math.pow(-1,n-k)*Beta(Math.abs(n+1),Math.abs(k+1));break // 1 1 0 (¯1*⍵-⍺)×(|⍵+1)!(|⍺+1) 584 | case 7:r=0 ;break // 1 1 1 0 585 | } 586 | return isInt(n)&&isInt(k)?Math.round(r):r 587 | }) 588 | )) 589 | const negInt=x=>isInt(x)&&x<0 590 | let smallFactorials=[1];(_=>{let x=1;for(let i=1;i<=25;i++)smallFactorials.push(x*=i)})() 591 | let Γ,lnΓ 592 | ;(_=>{ 593 | const g=7 594 | ,p=[0.99999999999980993,676.5203681218851,-1259.1392167224028,771.32342877765313,-176.61502916214059, 595 | 12.507343278686905,-0.13857109526572012,9.9843695780195716e-6,1.5056327351493116e-7] 596 | ,g_ln=607/128 597 | ,p_ln=[0.99999999999999709182,57.156235665862923517,-59.597960355475491248,14.136097974741747174, 598 | -0.49191381609762019978,0.33994649984811888699e-4,0.46523628927048575665e-4,-0.98374475304879564677e-4, 599 | 0.15808870322491248884e-3,-0.21026444172410488319e-3,0.21743961811521264320e-3,-0.16431810653676389022e-3, 600 | 0.84418223983852743293e-4,-0.26190838401581408670e-4,0.36899182659531622704e-5] 601 | // Spouge approximation (suitable for large arguments) 602 | lnΓ=z=>{ 603 | if(z<0)return NaN 604 | let x=p_ln[0];for(let i=p_ln.length-1;i>0;i--)x+=p_ln[i]/(z+i) 605 | let t=z+g_ln+.5 606 | return.5*Math.log(2*Math.PI)+(z+.5)*Math.log(t)-t+Math.log(x)-Math.log(z) 607 | } 608 | Γ=z=>{ 609 | if(z<.5)return Math.PI/(Math.sin(Math.PI*z)*Γ(1-z)) 610 | if(z>100)return Math.exp(lnΓ(z)) 611 | z--;let x=p[0];for(let i=1;ix?nyiErr():exec(str(y)) 617 | voc['⍷']=(y,x)=>{ 618 | y||nyiErr() 619 | const r=new Float64Array(y.a.length) 620 | if(x.s.length>y.s.length)return A(r,y.s) 621 | if(x.s.length=0&&j[a]+1===x.s[a]){q-=j[a]*d[a];j[a--]=0} 631 | if(a<0)break 632 | q+=d[a];j[a]++ 633 | } 634 | let a=s.length-1;while(a>=0&&i[a]+1===s[a]){p-=i[a]*d[a];i[a--]=0} 635 | if(a<0)break 636 | p+=d[a];i[a]++ 637 | } 638 | return A(r,y.s) 639 | } 640 | voc['⌊']=withId(Infinity,perv( 641 | Z.floor, 642 | real((x,y)=>Math.min(x,y)) 643 | )) 644 | voc['⌈']=withId(-Infinity,perv( 645 | Z.ceil, 646 | real((x,y)=>Math.max(x,y)) 647 | )) 648 | voc._fork1=(h,g)=>{asrt(typeof h==='function');return[h,g]} 649 | voc._fork2=(hg,f)=>{let[h,g]=hg;return(b,a)=>g(h(b,a),f.isA?f:f(b,a))} 650 | voc['⍕']=(y,x)=>{x&&nyiErr();let t=fmt(y);return A(t.join(''),[t.length,t[0].length])} 651 | const fmt=x=>{ // as array of strings 652 | const t=typeof x 653 | if(x===null)return['null'] 654 | if(t==='undefined')return['undefined'] 655 | if(t==='string')return[x] 656 | if(t==='number'){const r=[fmtNum(x)];r.al=1;return r} 657 | if(t==='function')return['#procedure'] 658 | if(!x.isA)return[''+x] 659 | if(!x.a.length)return[''] 660 | if(!x.s.length)return fmt(x.a[0]) 661 | // {t:type(0=chr,1=num,2=nst),w:width,h:height,lm:leftMargin,rm:rightMargin,bm:bottomMargin,al:align(0=lft,1=rgt)} 662 | const nr=prd(x.s.slice(0,-1)),nc=x.s[x.s.length-1],rows=Array(nr),cols=Array(nc) 663 | for(let i=0;i0;d--){step*=x.s[d];for(let i=step-1;i0;h--)t.push(btm) 682 | } 683 | const nk=r.h+r.bm;for(let k=0;kgrd(y,x,1) 688 | voc['⍒']=(y,x)=>grd(y,x,-1) 689 | const grd=(y,x,dir)=>{ 690 | let h={} // maps a character to its index in the collation 691 | if(x){ 692 | x.s.length||rnkErr();let ni=prd(x.s.slice(0,-1)),nj=x.s[x.s.length-1] 693 | for(let i=0;i{ 699 | let p=0,ind=rpt([0],y.s.length) 700 | while(1){ 701 | let u=y.a[p+i*d[0]],ku=typeof u 702 | let v=y.a[p+j*d[0]],kv=typeof v 703 | if(ku!==kv)return dir*(1-2*(ku0&&ind[a]+1===y.s[a]){p-=d[a]*ind[a];ind[a--]=0} 709 | if(a<=0)break 710 | p+=d[a];ind[a]++ 711 | } 712 | return(i>j)-(i{ 716 | if(f.isA){let h=f;f=x;x=h} 717 | asrt(typeof f==='function');asrt(x.isA);x.a.length===1||rnkErr() 718 | if(x.s.length)x=A.scal(unw(x)) 719 | return withId(x,(y,x,h)=>f(y,x,h)) 720 | }) 721 | voc['⍳']=(y,x)=>{ 722 | if(x){ 723 | x.s.length===1||rnkErr() 724 | const m=x.a.length,n=y.a.length,r=new Float64Array(n) 725 | for(let i=0;i{ 738 | asrt(!x) 739 | if(isSimple(y))return y 740 | if(h==null){ 741 | h=[];for(let i=0;iy.s[k]), rd=strides(rs) 751 | let us=h.map(k=>y.s[k]), ud=strides(us), un=prd(us) 752 | let a=Array(prd(rs)),d=strides(y.s) 753 | for(let i=0;i{ 755 | if(k+l>=y.s.length){a[p][q]=y.a[t]} 756 | else if(m[k+l]){for(let i=0;iZ.isint(x)&&Z.isint(y)?Z.gcd(x,y):domErr())) 764 | voc['∧']=withId(1,perv(null,(x,y)=>Z.isint(x)&&Z.isint(y)?Z.lcm(x,y):domErr())) 765 | voc['⍱']=perv(null,real((x,y)=>+!(bool(x)|bool(y)))) 766 | voc['⍲']=perv(null,real((x,y)=>+!(bool(x)&bool(y)))) 767 | voc['~']=perv(x=>+!bool(x)) 768 | voc['⍣']=conj((g,f)=>{ 769 | if(f.isA&&typeof g==='function'){let h=f;f=g;g=h}else{asrt(typeof f==='function')} 770 | if(typeof g==='function'){return(y,x)=>{while(1){let y1=f(y,x);if(toInt(g(y,y1),0,2))return y;y=y1}}} 771 | let n=toInt(g,0);return(y,x)=>{for(let i=0;i{ 774 | if(typeof window!=='undefined'&&typeof window.prompt==='function'){setTimeout(_=>{cb(exec(prompt('⎕:')||''))},0)} 775 | else{process.stdout.write('⎕:\n');readline(' ',x=>cb(exec(str(A(x)))))} 776 | }) 777 | voc['set_⎕']=x=>{ 778 | let s=fmt(x).join('\n')+'\n' 779 | if(typeof window!=='undefined'&&typeof window.alert==='function'){window.alert(s)}else{process.stdout.write(s)} 780 | return x 781 | } 782 | voc['get_⍞']=cps((_,_1,_2,cb)=>{ 783 | if(typeof window!=='undefined'&&typeof window.prompt==='function'){setTimeout(_=>{cb(A(prompt('')||''))},0)} 784 | else{readline('',x=>cb(A(x)))} 785 | }) 786 | voc['set_⍞']=x=>{ 787 | let s=fmt(x).join('\n') 788 | if(typeof window!=='undefined'&&typeof window.alert==='function'){window.alert(s)}else{process.stdout.write(s)} 789 | return x 790 | } 791 | voc['get_⎕IO']=_=>A.zero 792 | voc['set_⎕IO']=x=>match(x,A.zero)?x:domErr() 793 | voc['⎕DL']=cps((y,x,_,cb)=>{let t0=+new Date;setTimeout(_=>{cb(A([new Date-t0]))},unw(y))}) 794 | voc['⎕RE']=(y,x)=>{ 795 | x=str(x),y=str(y) 796 | let re;try{re=RegExp(x)}catch(e){domErr()} 797 | let m=re.exec(y);if(!m)return A.zld 798 | let r=[m.index];for(let i=0;i{ 802 | x&&nyiErr();let r=Array(y.a.length) 803 | for(let i=0;i{typeof process==='undefined'&&nyiErr();process.exit(0)} 809 | voc['?']=(y,x)=>x?deal(y,x):roll(y) 810 | const roll=perv(y=>{isInt(y,1)||domErr();return Math.floor(Math.random()*y)}) 811 | ,deal=(y,x)=>{ 812 | x=unw(x);y=unw(y) 813 | isInt(y,0)&&isInt(x,0,y+1)||domErr() 814 | let r=Array(y);for(let i=0;ierr(str(y)) 819 | voc['⍴']=(y,x)=>{ 820 | if(x){ 821 | x.s.length<=1||rnkErr() 822 | let s=x.a,n=prd(s),m=y.a.length,a=y.a 823 | for(let i=0;i{ 832 | asrt(typeof h==='undefined'||h.isA) 833 | if(x){ 834 | h=h?unw(h):y.s.length-1 835 | isInt(h)||domErr() 836 | if(y.s.length&&!(0<=h&&h=0&&i[a]+1===y.s[a]){p-=i[a]*d[a];i[a--]=0} 847 | if(a<0)break 848 | i[a]++;p+=d[a] 849 | } 850 | return A(r,y.s) 851 | }else{ 852 | if(h){h.a.length===1||lenErr();h=unw(h);isInt(h)||domErr();0<=h&&hvoc['⌽'](y,x,h||A.zero) 860 | voc['⌿']=adv((y,x,h)=>voc['/'](y,x,h||A.zero)) 861 | voc['/']=adv((y,x,h)=>{ 862 | if(typeof y==='function'){ 863 | let f=y,g=x,h0=h 864 | asrt(typeof f==='function') 865 | asrt(typeof g==='undefined') 866 | asrt(typeof h0==='undefined'||h0.isA) 867 | return(y,x)=>{ 868 | if(!y.s.length)y=A([unw(y)]) 869 | h=h0?toInt(h0):y.s.length-1 870 | 0<=h&&h=0||lenErr() 878 | }else{ 879 | s=s.slice();s.splice(h,1) 880 | } 881 | if(!y.a.length){let z=f.identity;z!=null||domErr();asrt(!z.s.length);return A(rpt([z.a[0]],prd(s)),s)} 882 | let r=[],ind=rpt([0],s0.length),p=0,u,d=strides(y.s) 883 | while(1){ 884 | if(b){ 885 | u=y.a[p];u.isA||(u=A.scal(u)) 886 | for(let i=1;i=0;i--){let v=y.a[p+i*d[h]];v.isA||(v=A.scal(v));u=f(u,v)} 890 | } 891 | u.s.length||(u=unw(u));r.push(u) 892 | let a=ind.length-1;while(a>=0&&ind[a]+1===s0[a]){p-=ind[a]*d[a];ind[a--]=0} 893 | if(a<0)break 894 | p+=d[a];ind[a]++ 895 | } 896 | return A(r,s) 897 | } 898 | }else{ 899 | y.s.length||(y=A([unw(y)])) 900 | h=h?toInt(h,0,y.s.length):y.s.length-1 901 | x.s.length<=1||rnkErr() 902 | let a=[],n=y.s[h] 903 | for(let i=0;i0?i:null) 911 | } 912 | if(n===1)for(let i=0;i=0&&ind[i]+1===s[i]){if(i!==h)p-=d[i]*ind[i];ind[i--]=0} 919 | if(i<0)break 920 | if(i!==h)p+=d[i] 921 | ind[i]++ 922 | } 923 | } 924 | return A(r,s) 925 | } 926 | }) 927 | voc['⌷']=(y,x,h)=>{ 928 | if(typeof y==='function')return(u,v)=>y(u,v,x) 929 | x||nyiErr();x.s.length>1&&rnkErr();x.a.length>y.s.length&&lenErr() 930 | if(h){ 931 | h=h.a;x.a.length===h.length||lenErr() 932 | let u=Array(y.s.length) 933 | for(let i=0;i=0;i--)r=indexAtSingleAxis(r,x.a[i].isA?x.a[i]:A([x.a[i]],[]),h[i]) 940 | return r 941 | } 942 | const indexAtSingleAxis=(x,y,h)=>{ // y:subscript 943 | asrt(x.isA&&y.isA&&isInt(h)&&0<=h&&hvoc['⌷'](y,a[0],a[1]) 951 | voc._amend=args=>{ 952 | let[value,x,y,h]=args.a.map(u=>u.isA?u:A([u],[])) 953 | x.s.length>1&&rnkErr() 954 | let a=Array(x.a.length);a.length>y.s.length&&lenErr() 955 | if(h){h.s.length>1&&rnkErr();h=h.a;a.length===h.length||lenErr()} 956 | else{h=[];for(let i=0;i{ 971 | x||nyiErr() 972 | x.s.length<=1||rnkErr() 973 | if(!y.s.length)y=A([unw(y)],x.s.length?rpt([1],x.s[0]):[1]) 974 | x.a.length<=y.s.length||rnkErr() 975 | for(let i=0;i0;i--)d[i-1]=d[i]*s[i] 979 | let r=rpt([getProt(y)],prd(s)) 980 | let cs=s.slice(),p=0,q=0,xd=strides(y.s) // cs:shape to copy 981 | for(let i=0;i=0&&ci[h]+1===cs[h]){p-=ci[h]*xd[h];q-=ci[h]*d[h];ci[h--]=0} 990 | if(h<0)break 991 | p+=xd[h];q+=d[h];ci[h]++ 992 | } 993 | } 994 | return A(r,s) 995 | } 996 | voc['⊃']=(y,x)=>{x&&nyiErr();y=y.a.length?y.a[0]:getProt(y);return y.isA?y:A([y],[])} 997 | voc['⍉']=(y,x)=>{ 998 | let a,s=[],d=[],d0=strides(y.s) 999 | if(x){x.s.length<=1||rnkErr();x.s.length||(x=A([unw(x)]));x.s[0]===y.s.length||lenErr();a=x.a} 1000 | else{a=new Int32Array(y.s.length);for(let i=0;i=0&&j[u]+1===s[u]){p-=j[u]*d[u];j[u--]=0} 1011 | if(u<0)break 1012 | j[u]++;p+=d[u] 1013 | } 1014 | return A(r,s) 1015 | } 1016 | voc['⍠']=conj((f,g)=>(y,x,h)=>(x?f:g)(y,x,h)) 1017 | 1018 | const NOUN=1,VRB=2,ADV=3,CNJ=4 1019 | ,exec=(s,o={})=>{ 1020 | const t=prs(s,o),b=compile(t,o),e=[preludeData.env[0].slice()] // t:ast,b:bytecode,e:env 1021 | for(let k in t.v)e[0][t.v[k].i]=o.ctx[k] 1022 | const r=vm(b,e) 1023 | for(let k in t.v){const v=t.v[k],x=o.ctx[k]=e[0][v.i];if(v.g===ADV)x.adv=1;if(v.g===CNJ)x.conj=1} 1024 | return r 1025 | } 1026 | ,repr=x=>x===null||['string','number','boolean'].indexOf(typeof x)>=0?JSON.stringify(x): 1027 | x instanceof Array?'['+x.map(repr).join(',')+']': 1028 | x.repr?x.repr():'{'+Object.keys(x).map(k=>repr(k)+':'+repr(x[k])).join(',')+'}' 1029 | ,compile=(ast,o={})=>{ 1030 | ast.d=0;ast.n=preludeData?preludeData.n:0;ast.v=preludeData?Object.create(preludeData.v):{} // n:nSlots,d:scopeDepth,v:vars 1031 | o.ctx=o.ctx||Object.create(voc) 1032 | for(let key in o.ctx)if(!ast.v[key]){ // VarInfo{g:grammaticalCategory(1=noun,2=vrb,3=adv,4=cnj),i:slot,d:scopeDepth} 1033 | const u=o.ctx[key],v=ast.v[key]={g:NOUN,i:ast.n++,d:ast.d} 1034 | if(typeof u==='function'||u instanceof Proc){ 1035 | v.g=u.adv?ADV:u.conj?CNJ:VRB 1036 | if(/^[gs]et_.*/.test(key))ast.v[key.slice(4)]={g:NOUN} 1037 | } 1038 | } 1039 | const synErrAt=x=>{synErr({file:o.file,offset:x.offset,aplCode:o.aplCode})} 1040 | const gl=x=>{switch(x[0]){default:asrt(0) // categorise lambdas 1041 | case'B':case':':case'←':case'[':case'{':case'.':case'⍬': 1042 | let r=VRB;for(let i=1;i{ 1052 | x.scp=scp 1053 | switch(x[0]){default:asrt(0) 1054 | case':':{const r=vst(x[1]);vst(x[2]);return r} 1055 | case'←':return vstLHS(x[1],vst(x[2])) 1056 | case'X':{ 1057 | const s=x[1],v=scp.v['get_'+s];if(v&&v.g===VRB)return NOUN 1058 | return(scp.v[s]||{}).g||valErr({file:o.file,offset:x.offset,aplCode:o.aplCode}) 1059 | } 1060 | case'{':{ 1061 | for(let i=1;i=0;i--)h[i]=vst(a[i]) 1074 | // strands 1075 | let i=0 1076 | while(i1&&h[h.length-1]===VRB){a=[['T'].concat(a)];h=[VRB]} // trains 1097 | if(h[h.length-1]!==NOUN){ 1098 | if(h.length>1)synErrAt(a[h.length-1]) 1099 | }else{ 1100 | while(h.length>1){ // monadic and dyadic verbs 1101 | if(h.length===2||h[h.length-3]!==NOUN){a.splice(-2,9e9,['M'].concat(a.slice(-2)));h.splice(-2,9e9,NOUN)} 1102 | else {a.splice(-3,9e9,['D'].concat(a.slice(-3)));h.splice(-3,9e9,NOUN)} 1103 | } 1104 | } 1105 | x.splice(0,9e9,a[0]);extend(x,a[0]);return h[0] 1106 | } 1107 | } 1108 | } 1109 | ,vstLHS=(x,rg)=>{ // rg:right-hand side grammatical category 1110 | x.scp=scp 1111 | switch(x[0]){default:asrt(0) 1112 | case'X':const s=x[1];if(s==='∇'||s==='⍫')synErrAt(x) 1113 | if(scp.v[s]){scp.v[s].g!==rg&&synErrAt(x)}else{scp.v[s]={d:scp.d,i:scp.n++,g:rg}};break 1114 | case'.':rg===NOUN||synErrAt(x);for(let i=1;i{switch(x[0]){default:asrt(0) 1122 | case'B':{if(x.length===1)return[LDC,A.zld,RET] 1123 | const a=[];for(let i=1;ix==='-'?Infinity:x==='--'?-Infinity:parseFloat(x)) 1137 | return[LDC,A([a[1]?new Z(a[0],a[1]):a[0]],[])]} 1138 | case'J':{const f=Function('return(_w,_a)=>('+x[1].replace(/^«|»$/g,'')+')')();return[EMB,(_w,_a)=>aplify(f(_w,_a))]} 1139 | case'[':{const v=x.scp.v._index,h=[],a=[] 1140 | for(let i=2;iisSimple(f[1])?unw(f[1]):f[1]))] 1145 | :[].concat.apply([],frags).concat([VEC,x.length-1])} 1146 | case'⍬':return[LDC,A.zld] 1147 | case'M':return rndr(x[2]).concat(rndr(x[1]),MON) 1148 | case'A':return rndr(x[1]).concat(rndr(x[2]),MON) 1149 | case'D':case'C':return rndr(x[3]).concat(rndr(x[2]),rndr(x[1]),DYA) 1150 | case'T':{const u=x.scp.v._atop,v=x.scp.v._fork1,w=x.scp.v._fork2;let i=x.length-1,r=rndr(x[i--]) 1151 | while(i>=2)r=r.concat(GET,v.d,v.i,rndr(x[i--]),DYA,GET,w.d,w.i,rndr(x[i--]),DYA) 1152 | return i?r.concat(GET,u.d,u.i,rndr(x[1]),DYA):r} 1153 | }} 1154 | const rndrLHS=x=>{switch(x[0]){default:asrt(0) 1155 | case'X':{const s=x[1],vars=x.scp.v,v=vars['set_'+s];return v&&v.g===VRB?[GET,v.d,v.i,MON]:[SET,vars[s].d,vars[s].i]} 1156 | case'.':{const n=x.length-1,a=[SPL,n];for(let i=1;i{ 1165 | if(typeof x==='string')return x.length===1?A.scal(x):A(x) 1166 | if(typeof x==='number')return A.scal(x) 1167 | if(x instanceof Array)return A(x.map(y=>{y=aplify(y);return y.s.length?y:unw(y)})) 1168 | if(x.isA)return x 1169 | domErr() 1170 | } 1171 | 1172 | let preludeData 1173 | ;(_=>{ 1174 | const ast=prs(prelude),code=compile(ast),v={},env=[[]];for(let k in ast.v)v[k]=ast.v[k] 1175 | preludeData={n:ast.n,v,env} 1176 | for(let k in v)env[0][v[k].i]=voc[k] 1177 | vm(code,env) 1178 | for(let k in v)voc[k]=env[0][v[k].i] 1179 | })() 1180 | let apl=this.apl=(s,o)=>apl.ws(o)(s) // s:apl code; o:options 1181 | extend(apl,{fmt,aprx,prs,compile,repr}) 1182 | apl.ws=(o={})=>{ 1183 | const ctx=Object.create(voc) 1184 | if(o.in )ctx['get_⎕']=ctx['get_⍞']=_=>{let s=o.in();asrt(typeof s==='string');return new A(s)} 1185 | if(o.out)ctx['set_⎕']=ctx['set_⍞']=x=>{o.out(fmt(x).join('\n')+'\n')} 1186 | return s=>exec(s,{ctx}) 1187 | } 1188 | const readline=(p,f)=>{ // p:prompt 1189 | ;(readline.requesters=readline.requesters||[]).push(f) 1190 | let rl=readline.rl 1191 | if(!rl){ 1192 | rl=readline.rl=require('readline').createInterface(process.stdin,process.stdout) 1193 | rl.on('line',x=>{let h=readline.requesters.pop();h&&h(x)}) 1194 | rl.on('close',_=>{process.stdout.write('\n');process.exit(0)}) 1195 | } 1196 | rl.setPrompt(p);rl.prompt() 1197 | } 1198 | if(typeof module!=='undefined'){ 1199 | module.exports=apl 1200 | if(module===require.main){ 1201 | let usage='Usage: apl.js [options] [filename.apl]\n'+ 1202 | 'Options:\n'+ 1203 | ' -l --linewise Process stdin line by line and disable prompt\n' 1204 | let file,linewise 1205 | process.argv.slice(2).forEach(arg=>{ 1206 | if(arg==='-h'||arg==='--help'){process.stderr.write(usage);process.exit(0)} 1207 | else if(arg==='-l'||arg=='--linewise')linewise=1 1208 | else if(arg[0]==='-'){process.stderr.write('unrecognized option:'+arg+'\n'+usage);process.exit(1)} 1209 | else if(file){process.stderr.write(usage);process.exit(1)} 1210 | else file=arg 1211 | }) 1212 | if(file){ 1213 | exec(require('fs').readFileSync(file,'utf8')) 1214 | }else if(linewise){ 1215 | let fs=require('fs'),ws=apl.ws(),a=Buffer(256),i=0,n=0,b=Buffer(a.length),k 1216 | while(k=fs.readSync(0,b,0,b.length)){ 1217 | if(n+k>a.length)a=Buffer.concat([a,a]) 1218 | b.copy(a,n,0,k);n+=k 1219 | while(i{ 1235 | try{s.match(/^\s*$/)||out.write(fmt(ws(s)).join('\n')+'\n')}catch(e){out.write(e+'\n')} 1236 | readline(' ',f) 1237 | } 1238 | f('') 1239 | } 1240 | } 1241 | } 1242 | -------------------------------------------------------------------------------- /examples/0-rho-iota.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | 3 | ⍝ ⍳ n generates a list of numbers from 0 to n-1 4 | ⍝ n n ⍴ A rearranges the elements of A in an n×n matrix 5 | ⎕←5 5⍴⍳25 6 | -------------------------------------------------------------------------------- /examples/0-rho-iota.out: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 2 | 5 6 7 8 9 3 | 10 11 12 13 14 4 | 15 16 17 18 19 5 | 20 21 22 23 24 6 | -------------------------------------------------------------------------------- /examples/1-mult.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | 3 | ⍝ Multiplication table 4 | ⍝ a × b scalar multiplication, "a times b" 5 | ⍝ ∘. is the "outer product" operator 6 | ⍝ A ∘.× B every item in A times every item in B 7 | ⎕ ← (⍳ 10) ∘.× ⍳ 10 8 | -------------------------------------------------------------------------------- /examples/1-mult.out: -------------------------------------------------------------------------------- 1 | 0 0 0 0 0 0 0 0 0 0 2 | 0 1 2 3 4 5 6 7 8 9 3 | 0 2 4 6 8 10 12 14 16 18 4 | 0 3 6 9 12 15 18 21 24 27 5 | 0 4 8 12 16 20 24 28 32 36 6 | 0 5 10 15 20 25 30 35 40 45 7 | 0 6 12 18 24 30 36 42 48 54 8 | 0 7 14 21 28 35 42 49 56 63 9 | 0 8 16 24 32 40 48 56 64 72 10 | 0 9 18 27 36 45 54 63 72 81 11 | -------------------------------------------------------------------------------- /examples/2-sierpinski.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | 3 | ⍝ Sierpinski's triangle 4 | f←{(⍵,(⍴⍵)⍴0)⍪⍵,⍵} 5 | S←{' #'[(f⍣⍵)1 1⍴1]} 6 | ⎕←S 5 7 | -------------------------------------------------------------------------------- /examples/2-sierpinski.out: -------------------------------------------------------------------------------- 1 | # 2 | ## 3 | # # 4 | #### 5 | # # 6 | ## ## 7 | # # # # 8 | ######## 9 | # # 10 | ## ## 11 | # # # # 12 | #### #### 13 | # # # # 14 | ## ## ## ## 15 | # # # # # # # # 16 | ################ 17 | # # 18 | ## ## 19 | # # # # 20 | #### #### 21 | # # # # 22 | ## ## ## ## 23 | # # # # # # # # 24 | ######## ######## 25 | # # # # 26 | ## ## ## ## 27 | # # # # # # # # 28 | #### #### #### #### 29 | # # # # # # # # 30 | ## ## ## ## ## ## ## ## 31 | # # # # # # # # # # # # # # # # 32 | ################################ 33 | -------------------------------------------------------------------------------- /examples/3-primes.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | ⎕←(1=+⌿0=a∘.|a)/a←2↓⍳100 3 | -------------------------------------------------------------------------------- /examples/3-primes.out: -------------------------------------------------------------------------------- 1 | 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 2 | -------------------------------------------------------------------------------- /examples/4-life.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | 3 | ⍝ Conway's game of life 4 | ⍝ This example was inspired by the impressive demo at 5 | ⍝ https://www.youtube.com/watch?v=a9xAKttWgP4 6 | 7 | ⍝ 0 1 1 8 | ⍝ 1 1 0 9 | ⍝ 0 1 0 10 | c←(3 3⍴⍳9)∊1 2 3 4 7 ⍝ original creature from demo 11 | c←(3 3⍴⍳9)∊1 3 6 7 8 ⍝ glider 12 | 13 | b←¯1⊖¯2⌽5 7↑c ⍝ place the creature on a larger board, near the centre 14 | life←{⊃1⍵∨.∧3 4=+/+⌿1 0¯1∘.⊖1 0¯1⌽¨⊂⍵} ⍝ function to compute next generation 15 | gen←{' #'[(life⍣⍵)b]} ⍝ n-th generation as a character matrix 16 | ⎕←gen¨1+⍳3 ⍝ show first few generations 17 | -------------------------------------------------------------------------------- /examples/4-life.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | # # # # 4 | ## # # ## 5 | # ## ## 6 | -------------------------------------------------------------------------------- /examples/5-rule30.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env a 2 | ⍝ See https://en.wikipedia.org/wiki/Rule_30 3 | 4 | r←30 5 | n←50 6 | t←⌽r⊤⍨8⍴2 7 | ⎕←' #'[↑⌽{⍵,⍨⊂t[2⊥¨3,/0,0,⍨⊃⍵]}⍣n⊂z,1,z←n⍴0] 8 | -------------------------------------------------------------------------------- /examples/5-rule30.out: -------------------------------------------------------------------------------- 1 | # 2 | ### 3 | ## # 4 | ## #### 5 | ## # # 6 | ## #### ### 7 | ## # # # 8 | ## #### ###### 9 | ## # ### # 10 | ## #### ## # ### 11 | ## # # #### ## # 12 | ## #### ## # # #### 13 | ## # ### ## ## # # 14 | ## #### ## ### ### ## ### 15 | ## # # ### # ### # # 16 | ## #### ## # # ##### ####### 17 | ## # ### #### # ### # 18 | ## #### ## ### ## ## # ### 19 | ## # # ### # ## ### #### ## # 20 | ## #### ## # ###### # # ### #### 21 | ## # ### #### #### ### ## # # 22 | ## #### ## ### # ## # # # ### ### 23 | ## # # ### # ### ## # ### ## # # # # 24 | ## #### ## # ### # # #### # # ## ###### 25 | ## # ### #### ## ##### # ##### # # # 26 | ## #### ## ### # ## # # ## # ##### ### 27 | ## # # ### # ## # #### ## # ## ## # ## # 28 | ## #### ## # ### # # # ### #### # ## # ## # #### 29 | ## # ### #### #### ## ## ### # # #### # # # 30 | ## #### ## ### # ## # # ### # ## #### ### ## ### 31 | ## # # ### # ## # # ##### # ###### # # ## # # # 32 | ## #### ## # ### # # #### #### #### ## # # ######### 33 | ## # ### #### #### # # ## # ## # # # # # 34 | ## #### ## ### # ## ## ### ## # ### ## # ##### # ## ### 35 | ## # # ### # ## # # ## # # # # # #### # # # ## # 36 | ## #### ## # ### # # #### #### ##### ## ##### # ## # ## ## #### 37 | ## # ### #### #### # # # # # # ### ## # # ### # # 38 | ## #### ## ### # ## ## ### ### ###### ## # # ### # # #### ### 39 | ## # # ### # ## # # ## ### ### # ## ### ## ## # # #### # # 40 | ## #### ## # ### # # #### # ### ### # # ## ### # ## ## # # ###### 41 | ## # ### #### #### # ###### ### # ## ## ### ###### # ## ##### # 42 | ## #### ## ### # ## ## ## ### # ## # # # ### ###### # # ### 43 | ## # # ### # ## # # ## # # ## ### # ########## # ## #### ### ## # 44 | ## #### ## # ### # # #### ### ## ## ### #### #### ## # ## ### # #### 45 | ## # ### #### #### # # # # # # ## # ## # ## ## # ## # ## # # 46 | ## #### ## ### # ## ## ### ########### # # ### ## # ##### # # # ### # ## ### 47 | ## # # ### # ## # # ## ### # # # # # ## #### ###### # # #### # # 48 | ## #### ## # ### # # #### # # ### ## # ##### ## ### # ## # ## ## ####### 49 | ## # ### #### #### # ###### # # ## # # # # # ##### # ## # # # ## # 50 | ## #### ## ### # ## ## ## ##### ## ### ## ######## # ## ## #### # # # ### 51 | ## # # ### # ## # # ## # # ## # ## # # # ## ## ## ### ### # # ## ## # 52 | -------------------------------------------------------------------------------- /examples/6-queens.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | 3 | queens←{ ⍝ The N-queens problem. 4 | 5 | search←{ ⍝ Search for all solutions. 6 | (⊂⍬)∊⍵:0⍴⊂⍬ ⍝ stitched: abandon this branch. 7 | 0=⍴⍵:rmdups ⍺ ⍝ all done: solution! 8 | (hd tl)←(⊃⍵)(1↓⍵) ⍝ head 'n tail of remaining ranks. 9 | next←⍺∘,¨hd ⍝ possible next steps. 10 | rems←hd free¨⊂tl ⍝ unchecked squares. 11 | ↑,/next ∇¨rems ⍝ ... in following ranks. 12 | } 13 | 14 | cvex←(1+⍳⍵)×⊂¯1 0 1 ⍝ Checking vectors. 15 | 16 | free←{⍵~¨⍺+(⍴⍵)↑cvex} ⍝ Unchecked squares. 17 | 18 | rmdups←{ ⍝ Ignore duplicate solution. 19 | rots←{{⍒⍵}\4/⊂⍵} ⍝ 4 rotations. 20 | refs←{{⍋⍵}\2/⊂⍵} ⍝ 2 reflections. 21 | best←{(⊃⍋↑⍵)⊃⍵} ⍝ best (=lowest) solution. 22 | all8←,↑refs¨rots ⍵ ⍝ all 8 orientations. 23 | (⍵≡best all8)⊃⍬(,⊂⍵) ⍝ ignore if not best. 24 | } 25 | 26 | fmt←{ ⍝ Format solution. 27 | chars←'·⍟'[(↑⍵)∘.=⍳⍺] ⍝ char array of placed queens. 28 | expd←1↓,↑⍺⍴⊂0 1 ⍝ expansion mask. 29 | ↑¨↓↓expd\chars ⍝ vector of char matrices. 30 | } 31 | 32 | squares←(⊂⍳⌈⍵÷2),1↓⍵⍴⊂⍳⍵ ⍝ initial squares 33 | 34 | ⍵ fmt ⍬ search squares ⍝ all distinct solutions. 35 | } 36 | 37 | ⎕←queens 5 38 | -------------------------------------------------------------------------------- /examples/6-queens.out: -------------------------------------------------------------------------------- 1 | ⍟ · · · · · ⍟ · · · 2 | · · ⍟ · · · · · · ⍟ 3 | · · · · ⍟ · · ⍟ · · 4 | · ⍟ · · · ⍟ · · · · 5 | · · · ⍟ · · · · ⍟ · 6 | -------------------------------------------------------------------------------- /examples/7-mandelbrot.apl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env apl 2 | ⎕←' #'[9>|⊃{⍺+⍵*2}/9⍴⊂¯3×.7j.5-⍉a∘.+0j1×a←(⍳n+1)÷n←98] 3 | -------------------------------------------------------------------------------- /examples/7-mandelbrot.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ## 15 | # 16 | ## 17 | ###### 18 | ###### 19 | ##### 20 | ###### 21 | ######### 22 | ########### 23 | ############ 24 | ############ 25 | ############ 26 | ############# 27 | ## ################## # 28 | ########################### ## 29 | ################################## 30 | ################################### 31 | ################################### 32 | ################################## 33 | ################################### 34 | #################################### 35 | ##################################### 36 | # ##################################### 37 | ## # ######################################## 38 | ### ### ######################################### 39 | ######################################################### 40 | ######################################################### 41 | ######################################################### 42 | ######################################################### 43 | ########################################################## 44 | ########################################################## 45 | ############################################################# 46 | ############################################################# 47 | ############################################################# 48 | # ############################################################## 49 | ### ################################################################## 50 | ############################################################################# 51 | ### ################################################################## 52 | # ############################################################## 53 | ############################################################# 54 | ############################################################# 55 | ############################################################# 56 | ########################################################## 57 | ########################################################## 58 | ######################################################### 59 | ######################################################### 60 | ######################################################### 61 | ######################################################### 62 | ### ### ######################################### 63 | ## # ######################################## 64 | # ##################################### 65 | ##################################### 66 | #################################### 67 | ################################### 68 | ################################## 69 | ################################### 70 | ################################### 71 | ################################## 72 | ########################### ## 73 | ## ################## # 74 | ############# 75 | ############ 76 | ############ 77 | ############ 78 | ########### 79 | ######### 80 | ###### 81 | ##### 82 | ###### 83 | ###### 84 | ## 85 | # 86 | ## 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /examples/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | cd $(dirname "$0") 4 | for f in *.apl; do 5 | echo "Testing $f" 6 | ../apl.js $f | diff - ${f%.apl}.out # fails if the files are different 7 | done 8 | -------------------------------------------------------------------------------- /icons/apl-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrudz/ngn-apl/d156d4e2b33c178e82dac55a19244014700d4cfa/icons/apl-logo.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ngn/apl 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

Demo

18 | 19 | -------------------------------------------------------------------------------- /licence: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2018 Nikolay G. Nikolov 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngn/apl", 3 | "icons": [ 4 | { 5 | "src": "icons/apl-logo.png", 6 | "type": "image/png", 7 | "sizes": "512x512" 8 | } 9 | ], 10 | "start_url": "https://abrudz.github.io/ngn-apl/web/index.html", 11 | "display": "standalone" 12 | } -------------------------------------------------------------------------------- /ngn-apl-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrudz/ngn-apl/d156d4e2b33c178e82dac55a19244014700d4cfa/ngn-apl-screenshot.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | **This is an archive of ngn/apl but PRs to this repo are still accepted. Feel free to contribute!** 2 | 3 | Its author thinks it has served its purpose and has become a distraction. He went on to create a free [implementation](https://codeberg.org/ngn/k) of [K6](https://en.wikipedia.org/wiki/K_(programming_language)) and encouraged people to use that instead, until he stopped supporting that too. 4 | 5 | ---- 6 | 7 | [Online Demo](https://abrudz.github.io/ngn-apl) - can also be installed offline as a [PWA (Progressive Web App)](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/What_is_a_progressive_web_app) on a computer / phone - even without internet! 8 | 9 | ![Screenshot](ngn-apl-screenshot.png) 10 | 11 | An [APL](https://aplwiki.com) interpreter written in JavaScript. 12 | Runs in a browser or [NodeJS](https://nodejs.org/). 13 | 14 | Supports: most primitives, dfns (`{⍺ ⍵}`), nested arrays, complex numbers (`1j2`), infinities (`¯` or `∞`), forks and 15 | atops, strand assignment (`(a b)←c`), indexed assignment (`a[b]←c`), user-defined operators (`{⍺⍺ ⍵⍵}`). 16 | 17 | Doesn't support: tradfns (`∇R←X f Y`), non-zero index origin (`⎕IO`), comparison tolerance (`⎕CT`), 18 | prototypes, modified assignment (`x+←1`), control structures (`:If`), object-oriented features, namespaces. 19 | 20 | Used in [Paul L Jackson's web site](https://plj541.github.io/APL.js/), [repl.it](https://repl.it/languages/APL), 21 | and [tio.run](https://tio.run/#apl-ngn). 22 | 23 | # Offline usage with NodeJS 24 | 25 | Run `apl.js` with [Node](https://nodejs.org/) to start a REPL: 26 | 27 | node apl.js 28 | 29 | An APL script can be given as argument: 30 | 31 | node apl.js filename.apl 32 | 33 | `apl.js` can be `require()`d as a CommonJS module from JavaScript: 34 | 35 | var apl=require('./apl') 36 | var r=apl('1 2 3+4 5 6') 37 | 38 | or used in an HTML page: 39 | 40 | 41 | 42 | 43 | # Editor support 44 | 45 | * [Vim keymap and syntax](https://gitlab.com/n9n/vim-apl) 46 | * [baruchel/vim-notebook](https://github.com/baruchel/vim-notebook): evaluate blocks of APL code in a vim buffer 47 | -------------------------------------------------------------------------------- /serviceWorker.js: -------------------------------------------------------------------------------- 1 | console.log('Service Worker running') 2 | const CACHE_NAME = 'ngn/apl-v1'; 3 | const urlsToCache = [ 4 | '../icons/apl-logo.png', 5 | '../web/index.html', 6 | '../web/Apl385.woff', // font 7 | '../web/index.js', 8 | '../web/lb.js', 9 | '../apl.js', 10 | '../t.js', 11 | '../t.apl' 12 | ]; 13 | 14 | async function addToCache() { 15 | try { 16 | let cache = await caches.open(CACHE_NAME); 17 | console.log('Opened cache'); 18 | await cache.addAll(urlsToCache); 19 | console.log('All urls cached') 20 | } catch(error) { 21 | console.error('One or more URLs failed to cache:', error.url || error); 22 | } 23 | } 24 | 25 | self.addEventListener('install', function(event) { 26 | console.log('Install - Add required urls to cache') 27 | event.waitUntil(addToCache()); 28 | }); 29 | 30 | // Function acts as proxy - any network request goes through this function 31 | async function fetchEvent(event) { 32 | let cacheResponse = await caches.match(event.request); 33 | console.log('Cache hit', event.request.url) 34 | if (cacheResponse) { 35 | return cacheResponse; 36 | } 37 | 38 | // Ideally there should be no cache miss 39 | // as all urls should already be added to cache when service worker was installed 40 | console.log('Cache missed', event.request.url) 41 | 42 | // IMPORTANT: Clone the request. A request is a stream and 43 | // can only be consumed once. Since we are consuming this 44 | // once by cache and once by the browser for fetch, we need 45 | // to clone the response. 46 | let fetchRequest = event.request.clone(); 47 | 48 | let response = await fetch(fetchRequest); 49 | // Check if we received a valid response 50 | if(!response || response.status !== 200 || response.type !== 'basic') { 51 | console.log('Invalid response', event.request.url, response); 52 | return response; 53 | } 54 | 55 | // IMPORTANT: Clone the response. A response is a stream 56 | // and because we want the browser to consume the response 57 | // as well as the cache consuming the response, we need 58 | // to clone it so we have two streams. 59 | let responseToCache = response.clone(); 60 | 61 | let cache = await caches.open(CACHE_NAME); 62 | await cache.put(event.request, responseToCache); 63 | console.log('Put in cache', event.request.url); 64 | 65 | return response; 66 | } 67 | 68 | self.addEventListener('fetch', function(event) { 69 | event.respondWith(fetchEvent(event)); 70 | }); 71 | -------------------------------------------------------------------------------- /t.apl: -------------------------------------------------------------------------------- 1 | ⍬ ←→ 0⍴0 2 | ⍴⍬ ←→ ,0 3 | 'abcd'~'bde' ←→ 'ac' 4 | (⍳6)~0 2 4 ←→ 1 3 5 5 | 'ab' 'cd' 'ad'~'a' ←→ 'ab' 'cd' 'ad' 6 | 'ab' 'cd' 'ad'~'cd' ←→ 'ab' 'cd' 'ad' 7 | 'ab' 'cd' 'ad'~⊂'cd' ←→ 'ab' 'ad' 8 | 'ab' 'cd' 'ad'~'a' 'cd' ←→ 'ab' 'ad' 9 | (11+⍳6)~2 3⍴1 2 3 14 5 6 ←→ 11 12 13 15 16 10 | (2 2⍴⍳4)~2 !! RANK ERROR 11 | (-⍟)2 3 ←→ -⍟2 3 12 | 2(-*)3 ←→ -2*3 13 | ↑3 ←→ 3 14 | ↑(1 2)(3 4) ←→ 2 2⍴1 2 3 4 15 | ↑(1 2)(3 4 5) ←→ 2 3⍴1 2 0 3 4 5 16 | ↑1 2 ←→ 1 2 17 | ↑(1 2)3 ←→ 2 2⍴1 2 3 0 18 | ↑1(2 3) ←→ 2 2⍴1 0 2 3 19 | ↑2 2⍴1(1 1 2⍴3 4)(5 6)(2 0⍴0) ←→ 2 2 1 2 2⍴1 0 0 0 3 4 0 0 5 6 0 0 0 0 0 0 20 | ↑⍬ ←→ ⍬ 21 | ↑2 3 0⍴0 ←→ 2 3 0⍴0 22 | ⍬⊃3 ←→ 3 23 | 2⊃'pick' ←→ 'c' 24 | (⊂1 0)⊃2 2⍴'abcd' ←→ 'c' 25 | 1⊃'foo' 'bar' ←→ 'bar' 26 | 1 2⊃'foo' 'bar' ←→ 'r' 27 | (2 2⍴0)⊃1 2 !! RANK ERROR 28 | (⊂2 1⍴0)⊃2 2⍴0 !! RANK ERROR 29 | (⊂2 2⍴0)⊃1 2 !! RANK ERROR 30 | (⊂2 2)⊃1 2 !! RANK ERROR 31 | (⊂0 2)⊃2 2⍴'ABCD' !! INDEX ERROR 32 | a←' this is a test '⋄(a≠' ')⊂a ←→ 'this' 'is' (,'a') 'test' 33 | ↓1 2 3 ←→ ⊂1 2 3 34 | ↓(1 2)(3 4) ←→ ⊂(1 2)(3 4) 35 | ↓2 2⍴⍳4 ←→ (0 1)(2 3) 36 | ↓2 3 4⍴⍳24 ←→ 2 3⍴(0 1 2 3)(4 5 6 7)(8 9 10 11)(12 13 14 15)(16 17 18 19)(20 21 22 23) 37 | 2↓'abc' ←→ ,'c' 38 | ¯1↓'abc' ←→ 'ab' 39 | 5↓'abc' ←→ '' 40 | 0 ¯2↓3 3⍴⎕a ←→ 3 1⍴'ADG' 41 | ¯2 ¯1↓3 3⍴⎕a ←→ 1 2⍴'AB' 42 | 1↓3 3⍴⎕a ←→ 2 3⍴'DEFGHI' 43 | ⍬↓3 3⍴⍳9 ←→ 3 3⍴⍳9 44 | 1 1↓2 3 4⍴⎕a ←→ 1 2 4⍴'QRSTUVWX' 45 | ¯1 ¯1↓2 3 4⍴⎕a ←→ 1 2 4⍴'ABCDEFGH' 46 | 1↓0 ←→ ⍬ 47 | 0 1↓2 ←→ 1 0⍴0 48 | 1 2↓3 ←→ 0 0⍴0 49 | ⍬↓0 ←→ 0 50 | ⍪2 3 4 ←→ 3 1⍴2 3 4 51 | ⍪0 ←→ 1 1⍴0 52 | ⍪2 2⍴2 3 4 5 ←→ 2 2⍴2 3 4 5 53 | ⍴⍪2 3⍴⍳6 ←→ 2 3 54 | ⍴⍪2 3 4⍴⍳24 ←→ 2 12 55 | (2 3⍴⍳6)⍪9 ←→ 3 3⍴0 1 2 3 4 5 9 9 9 56 | 1⍪2 ←→ 1 2 57 | 1⊢2 ←→ 2 58 | ⊢3 ←→ 3 59 | 1⊣2 ←→ 1 60 | ⊣3 ←→ 3 61 | ≢0 ←→ 1 62 | ≢0 0 ←→ 2 63 | ≢⍬ ←→ 0 64 | ≢2 3⍴⍳6 ←→ 2 65 | 2≢2 ←→ 0 66 | ,2 13⍴⎕a ←→ ⎕a 67 | ,1 ←→ 1⍴1 68 | ⌹2 ←→ .5 69 | ⌹2 2⍴4 3 3 2 ←→ 2 2⍴¯2 3 3 ¯4 70 | ⌹2 2 2⍴⍳8 !! RANK ERROR 71 | ⌹2 3⍴⍳6 !! LENGTH ERROR 72 | (4 4⍴12 1 4 10 ¯6 ¯5 4 7 ¯4 9 3 4 ¯2 ¯6 7 7)⌹93 81 93.5 120.5 ←→ .0003898888816687221 ¯.005029566573526544 .04730651764247189 .0705568912859835 73 | 17-⍨23 ←→ 6 74 | 7⍴⍨2 3 ←→ 2 3⍴7 75 | +⍨2 ←→ 4 76 | -⍨123 ←→ 0 77 | ¯3 ¯4*2 ←→ 9 16 78 | 0j1*2 ←→ ¯1 79 | 1j2*3 ←→ ¯11j¯2 80 | .5j1.5*5 ←→ 9.875j¯0.375 81 | 9 4 0 ¯4 ¯9*.5 ←→ 3 2 0 0j2 0j3 82 | 'hello'} !! SYNTAX ERROR 83 | (1 1⍴2)+1 1 1⍴3 ←→ 1 1 1⍴5 84 | +0((1j¯2 ¯3j4)¯5.6) ←→ 0((1j2 ¯3j¯4)¯5.6) 85 | 1(2 3)+(4 5)6 ←→ (5 6)(8 9) 86 | (2 3⍴1 2 3 4 5 6)+¯2 ←→ 2 3⍴¯1 0 1 2 3 4 87 | 1 2 3+4 5 !! LENGTH ERROR 88 | (2 3⍴1 2 3 4 5 6)+2⍴¯2 !! RANK ERROR 89 | (2 3⍴⍳6)+3 2⍴⍳6 !! LENGTH ERROR 90 | (2 3⍴1 2 3 4 5 6)+2 3⍴¯2 ←→ 2 3⍴¯1 0 1 2 3 4 91 | 1j¯2+¯2j3 ←→ ¯1j1 92 | +/⍬ ←→ 0 93 | ¯+¯¯ !! DOMAIN ERROR 94 | 1j¯+2j¯¯ !! DOMAIN ERROR 95 | -4(1 2 3)1j2 ←→ ¯4(¯1 ¯2 ¯3)¯1j¯2 96 | 1-3 ←→ ¯2 97 | 5j2-3j8 ←→ 2j¯6 98 | -/⍬ ←→ 0 99 | ׯ2 ¯1 0 1 2 ¯ ¯¯ 3j¯4 ←→ ¯1 ¯1 0 1 1 1 ¯1 .6j¯.8 100 | 7×8 ←→ 56 101 | 1j¯2ׯ2j3 ←→ 4j7 102 | 2×1j¯2 ←→ 2j¯4 103 | ×/⍬ ←→ 1 104 | ÷2 ←→ .5 105 | ÷2j3 ←→ 0.15384615384615385J¯0.23076923076923078 106 | 0÷0 !! DOMAIN ERROR 107 | 27÷9 ←→ 3 108 | 4j7÷1j¯2 ←→ ¯2j3 109 | 0j2÷0j1 ←→ 2 110 | 5÷2j1 ←→ 2j¯1 111 | ÷/⍬ ←→ 1 112 | *2 ←→ 7.38905609893065 113 | *2j3 ←→ ¯7.315110094901103J1.0427436562359045 114 | 2 3 ¯2 ¯3*3 2 3 2 ←→ 8 9 ¯8 9 115 | ¯1*.5 ←→ 0j1 116 | */⍬ ←→ 1 117 | 1j2*3j4 ←→ .129009594074467j.03392409290517014 118 | ⍟123 ←→ 4.812184355372417 119 | ⍟0 ←→ ¯¯ 120 | ⍟¯1 ←→ 0j1×○1 121 | ⍟123j456 ←→ 6.157609243895447J1.3073297857599793 122 | 12⍟34 ¯34 ←→ 1.419111870829036 1.419111870829036j1.26426988871305 123 | ¯12⍟¯34 ←→ 1.1612974763994781j¯.2039235425372641 124 | 1j2⍟3j4 ←→ 1.2393828252698689J¯0.5528462880299602 125 | |¯8 0 8 ¯3.5 ←→ 8 0 8 3.5 126 | |5j12 ←→ 13 127 | 3|5 ←→ 2 128 | 1j2|3j4 ←→ ¯1j1 129 | 7 ¯7∘.|31 28 ¯30 ←→ 2 3⍴3 0 5 ¯4 0 ¯2 130 | ¯0.2 0 0.2∘.|¯0.3 0 0.3 ←→ 3 3⍴¯0.1 0 ¯0.1 ¯0.3 0 0.3 0.1 0 0.1 131 | |/⍬ ←→ 0 132 | 0|¯4 ←→ ¯4 133 | 0|¯4j5 ←→ ¯4j5 134 | 10|4j3 ←→ 4j3 135 | 4j6|7j10 ←→ 3j4 136 | ¯10 7j10 0.3|17 5 10 ←→ ¯3 ¯5j7 0.1 137 | +\20 10 ¯5 7 ←→ 20 30 25 32 138 | ,\'AB' 'CD' 'EF' ←→ 'AB' 'ABCD' 'ABCDEF' 139 | ×\2 3⍴5 2 3 4 7 6 ←→ 2 3⍴5 10 30 4 28 168 140 | ∧\1 1 1 0 1 1 ←→ 1 1 1 0 0 0 141 | -\1 2 3 4 ←→ 1 ¯1 2 ¯2 142 | ∨\0 0 1 0 0 1 0 ←→ 0 0 1 1 1 1 1 143 | +\1 2 3 4 5 ←→ 1 3 6 10 15 144 | +\(1 2 3)(4 5 6)(7 8 9) ←→ (1 2 3)(5 7 9)(12 15 18) 145 | M←2 3⍴1 2 3 4 5 6⋄+\M ←→ 2 3⍴1 3 6 4 9 15 146 | M←2 3⍴1 2 3 4 5 6⋄+⍀M ←→ 2 3⍴1 2 3 5 7 9 147 | M←2 3⍴1 2 3 4 5 6⋄+\[0]M ←→ 2 3⍴1 2 3 5 7 9 148 | ,\'abc' ←→ 'a' 'ab' 'abc' 149 | T←'ONE(TWO) BOOK(S)'⋄≠\T∊'()' ←→ 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 0 150 | T←'ONE(TWO) BOOK(S)'⋄((T∊'()')⍱≠\T∊'()')/T ←→ 'ONE BOOK' 151 | 1 0 1\'ab' ←→ 'a b' 152 | 0 1 0 1 0\2 3 ←→ 0 2 0 3 0 153 | (2 2⍴0)\'food' !! RANK ERROR 154 | 'abc'\'def' !! DOMAIN ERROR 155 | 1 0 1 1\'ab' !! LENGTH ERROR 156 | 1 0 1 1\'abcd' !! LENGTH ERROR 157 | 1 0 1\2 2⍴'ABCD' ←→ 2 3⍴'A BC D' 158 | 1 0 1⍀2 2⍴'ABCD' ←→ 3 2⍴'AB CD' 159 | 1 0 1\[0]2 2⍴'ABCD' ←→ 3 2⍴'AB CD' 160 | 1 0 1\[1]2 2⍴'ABCD' ←→ 2 3⍴'A BC D' 161 | ○2 ←→ 6.283185307179586 162 | ○2j2 ←→ 6.283185307179586j6.283185307179586 163 | ○'ABC' !! DOMAIN ERROR 164 | ¯12○2 2j3 ←→ ¯0.4161468365471j0.9092974268257 ¯0.02071873100224j0.04527125315609 165 | ¯11○2 2j3 ←→ 0j2 ¯3j2 166 | ¯10○2 2j3 ←→ 2 2j¯3 167 | ¯9○2 2j3 ←→ 2 2j3 168 | ¯8○2 2j3 ←→ 0j¯2.2360679774998 ¯2.8852305489054j2.0795565201111 169 | ¯7○0.5 2 2j3 ←→ 0.54930614433405 0.5493061443340548456976226185j¯1.570796326794896619231321692 0.1469466662255297520474327852j1.338972522294493561124193576 170 | ¯6○0.5 2 2j3 ←→ ¯1.1102230246252e¯16j1.0471975511966 1.316957896924816708625046347 1.983387029916535432347076903j1.000143542473797218521037812 171 | ¯5○2 2j3 ←→ 1.443635475178810342493276740 1.968637925793096291788665095j0.9646585044076027920454110595 172 | ¯4○2 0 ¯2 2j3 ←→ 1.7320508075689 0j1 ¯1.7320508075689 1.9256697360917j3.1157990841034 173 | ¯3○0.5 2 2j3 ←→ 0.46364760900081 1.107148717794090503017065460 1.409921049596575522530619385j0.2290726829685387662958818029 174 | ¯2○0.5 2 2j3 ←→ 1.0471975511966 0j1.316957896924816708625046347 1.000143542473797218521037812j¯1.983387029916535432347076903 175 | ¯1○0.5 2 2j3 ←→ 0.5235987755983 1.570796326794896619231321692j¯1.316957896924816708625046347 0.5706527843210994007102838797j1.983387029916535432347076903 176 | 0○0.5 2 2j3 ←→ 0.86602540378444 0j1.7320508075689 3.1157990841034j¯1.9256697360917 177 | 1e¯10>|.5-1○○÷6 ←→ 1 # sin(pi/6) = .5 178 | 1○1 2j3 ←→ 0.8414709848079 9.1544991469114j¯4.1689069599666 179 | 2○1 2j3 ←→ 0.54030230586814 ¯4.1896256909688j¯9.1092278937553 180 | 3○1 2j3 ←→ 1.5574077246549 ¯0.0037640256415041j1.0032386273536 181 | 4○2 2j3 ←→ 2.2360679774998 2.0795565201111j2.8852305489054 182 | 5○2 2j3 ←→ 3.626860407847 ¯3.5905645899858j0.53092108624852 183 | 6○2 2j3 ←→ 3.7621956910836 ¯3.7245455049153j0.51182256998738 184 | 7○2 2j3 ←→ 0.96402758007582 0.96538587902213j¯0.0098843750383225 185 | 8○2 2j3 ←→ 0j2.2360679774998 2.8852305489054j¯2.0795565201111 186 | 9○2 2j3 ←→ 2 2 187 | 10○¯2 ¯2j3 ←→ 2 3.605551275464 188 | 11○2 2j3 ←→ 0 3 189 | 12○2 2j3 ←→ 0 0.98279372324733 190 | 1○'a' !! DOMAIN ERROR 191 | 99○1 !! DOMAIN ERROR 192 | 99○1j2 !! DOMAIN ERROR 193 | 10,66 ←→ 10 66 194 | ⍬,⍬ ←→ ⍬ 195 | ⍬,1 ←→ ,1 196 | 1,⍬ ←→ ,1 197 | 'ab','c','def' ←→ 'abcdef' 198 | (2 3⍴⍳6),2 2⍴⍳4 ←→ 2 5⍴0 1 2 0 1 3 4 5 2 3 199 | (2 3⍴⍳6),⍳2 ←→ 2 4⍴0 1 2 0 3 4 5 1 200 | (3 2⍴⍳6),2 2⍴⍳4 !! LENGTH ERROR 201 | (⍳2),2 3⍴⍳6 ←→ 2 4⍴0 0 1 2 1 3 4 5 202 | (2 3⍴⍳6),9 ←→ 2 4⍴0 1 2 9 3 4 5 9 203 | (2 3 4⍴⎕a),'*' ←→ 2 3 5⍴'ABCD*EFGH*IJKL*MNOP*QRST*UVWX*' 204 | 12=12 ←→ 1 205 | 2=12 ←→ 0 206 | 'Q'='Q' ←→ 1 207 | 1='1' ←→ 0 208 | '1'=1 ←→ 0 209 | 11 7 2 9=11 3 2 6 ←→ 1 0 1 0 210 | 4=2+2 ←→ 1 211 | 2j3=2j3 ←→ 1 212 | 2j3=3j2 ←→ 0 213 | 0j0 ←→ 0 214 | 123j0 ←→ 123 215 | 2j¯3+¯2j3 ←→ 0 216 | =/⍬ ←→ 1 217 | 'stoat'='toast' ←→ 0 0 0 0 1 218 | (2 3⍴1 2 3 4 5 6)=2 3⍴3 3 3 5 5 5 ←→ 2 3⍴0 0 1 0 1 0 219 | 3=2 3⍴1 2 3 4 5 6 ←→ 2 3⍴0 0 1 0 0 0 220 | 3=(2 3⍴1 2 3 4 5 6)(2 3⍴3 3 3 5 5 5) ←→ (2 3⍴0 0 1 0 0 0)(2 3⍴1 1 1 0 0 0) 221 | 3≢5 ←→ 1 222 | 8≠8 ←→ 0 223 | ≠/⍬ ←→ 0 224 | /⍬ ←→ 0 226 | ≤/⍬ ←→ 1 227 | ≥/⍬ ←→ 1 228 | 3≡3 ←→ 1 229 | 3≡,3 ←→ 0 230 | 4 7.1 8≡4 7.2 8 ←→ 0 231 | (3 4⍴⍳12)≡3 4⍴⍳12 ←→ 1 232 | (3 4⍴⍳12)≡⊂3 4⍴⍳12 ←→ 0 233 | ('ab' 'c')≡'abc' ←→ 0 234 | (2 0⍴0)≡(0 2⍴0) ←→ 0 235 | ≡4 ←→ 0 236 | ≡⍳4 ←→ 1 237 | ≡2 2⍴⍳4 ←→ 1 238 | ≡'abc'1 2 3(23 55) ←→ 2 239 | ≡'abc'(2 4⍴'abc'2 3'k') ←→ 3 240 | 8(÷∘-)2 ←→ ¯4 241 | ÷∘-2 ←→ ¯0.5 242 | 8÷∘-2 ←→ ¯4 243 | ⍴∘⍴2 3⍴⍳6 ←→ ,2 244 | 3⍴∘⍴2 3⍴⍳6 ←→ 2 3 2 245 | 3∘-1 ←→ 2 246 | (-∘2)9 ←→ 7 247 | 1 2∪2 3 ←→ 1 2 3 248 | 'abc'∪'cad' ←→ 'abcd' 249 | 1∪1 ←→ ,1 250 | 1∪2 ←→ 1 2 251 | 1∪2 1 ←→ 1 2 252 | 1 2∪2 2 2 2 ←→ 1 2 253 | 2 3 3∪4 5 3 4 ←→ 2 3 3 4 5 4 254 | ⍬∪1 ←→ ,1 255 | 1 2∪⍬ ←→ 1 2 256 | ⍬∪⍬ ←→ ⍬ 257 | 1 2∪2 2⍴3 !! RANK ERROR 258 | (2 2⍴3)∪4 5 !! RANK ERROR 259 | 'ab' 'c'(0 1)∪'ab' 'de' ←→ 'ab' 'c'(0 1)'de' 260 | ∪3 17 ←→ 3 17 261 | ∪⍬ ←→ ⍬ 262 | ∪17 ←→ ,17 263 | ∪3 17 17 17 ¯3 17 0 ←→ 3 17 ¯3 0 264 | 'abca'∩'dac' ←→ 'aca' 265 | 1'2'3∩⍳5 ←→ 1 3 266 | 1∩2 ←→ ⍬ 267 | 1∩2 3⍴4 !! RANK ERROR 268 | ∩1 !! NONCE ERROR 269 | 10⊥3 2 6 9 ←→ 3269 270 | 8⊥3 1 ←→ 25 271 | 1760 3 12⊥1 2 8 ←→ 68 272 | 2 2 2⊥1 ←→ 7 273 | 0 20 12 4⊥2 15 6 3 ←→ 2667 274 | 1760 3 12⊥3 3⍴1 1 1 2 0 3 0 1 8 ←→ 60 37 80 275 | 60 60⊥3 13 ←→ 193 276 | 0 60⊥3 13 ←→ 193 277 | 60⊥3 13 ←→ 193 278 | 2⊥1 0 1 0 ←→ 10 279 | 2⊥1 2 3 4 ←→ 26 280 | 3⊥1 2 3 4 ←→ 58 281 | 2j3⊤4j5 6j7 8j9 ←→ 2j2 2j1 ¯1j2 282 | 10⊥3 4.5j1 ←→ 34.5j1 283 | (4 3⍴1 1 1 2 2 2 3 3 3 4 4 4)⊥3 8⍴0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 ←→ 4 8⍴0 1 1 2 1 2 2 3 0 1 2 3 4 5 6 7 0 1 3 4 9 10 12 13 0 1 4 5 16 17 20 21 284 | 2⊥3 8⍴0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 ←→ 0 1 2 3 4 5 6 7 285 | (2 1⍴2 10)⊥3 8 ⍴0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 ←→ 2 8⍴0 1 2 3 4 5 6 7 0 1 10 11 100 101 110 111 286 | 2 3 4∘.×1 2 3 4 ←→ 3 4⍴2 4 6 8 3 6 9 12 4 8 12 16 287 | 0 1 2 3 4∘.!0 1 2 3 4 ←→ 5 5⍴1 1 1 1 1 0 1 2 3 4 0 0 1 3 6 0 0 0 1 4 0 0 0 0 1 288 | 1 2∘.,1+⍳3 ←→ 2 3⍴(1 1)(1 2)(1 3)(2 1)(2 2)(2 3) 289 | 2 3∘.↑1 2 ←→ (2 2⍴(1 0)(2 0)(1 0 0)(2 0 0)) 290 | ⍴1 2∘.,1+⍳3 ←→ 2 3 291 | ⍴2 3∘.↑1 2 ←→ 2 2 292 | ⍴((4 3⍴0)∘.+5 2⍴0) ←→ 4 3 5 2 293 | 2 3∘.×4 5 ←→ 2 2⍴8 10 12 15 294 | 2 3∘ . ×4 5 ←→ 2 2⍴8 10 12 15 295 | 2 3∘.{⍺×⍵}4 5 ←→ 2 2⍴8 10 12 15 296 | 1 3 5 7+.=2 3 6 7 ←→ 2 297 | 7+.=8 8 7 7 8 7 5 ←→ 3 298 | 1 3 5 7∧.=2 3 6 7 ←→ 0 299 | 8 8 7 7 8 7 5+.=7 ←→ 3 300 | 1 3 5 7∧.=1 3 5 7 ←→ 1 301 | 7+.=7 ←→ 1 302 | (3 2⍴5 ¯3 ¯2 4 ¯1 0)+.×2 2⍴6 ¯3 5 7 ←→ 3 2⍴15 ¯36 8 34 ¯6 3 303 | ⍴¨(⍳4)(0 0 0) ←→ (,4)(,3) 304 | ⍴¨'ab' 'cde' 'f' ←→ (,2)(,3)⍬ 305 | ⍴ (2 2⍴⍳4)(⍳10)97.3(3 4⍴'K') ←→ ,4 306 | ⍴¨ (2 2⍴⍳4)(⍳10)97.3(3 4⍴'K') ←→ (2 2)(,10)⍬(3 4) 307 | ⍴⍴¨ (2 2⍴⍳4)(⍳10)97.3(3 4⍴'K') ←→ ,4 308 | ⍴¨⍴¨(2 2⍴⍳4)(⍳10)97.3(3 4⍴'K') ←→ (,2)(,1)(,0)(,2) 309 | 1 2 3,¨4 5 6 ←→ (1 4)(2 5)(3 6) 310 | 2 3↑¨'monday' 'tuesday' ←→ 'mo' 'tue' 311 | 2↑¨'monday' 'tuesday' ←→ 'mo' 'tu' 312 | 2 3⍴¨1 2 ←→ (1 1)(2 2 2) 313 | 4 5⍴¨'the' 'cat' ←→ 'thet' 'catca' 314 | {1+⍵*2}¨2 3⍴⍳6 ←→ 2 3⍴1 2 5 10 17 26 315 | 1760 3 12⊤75 ←→ 2 0 3 316 | 3 12⊤75 ←→ 0 3 317 | 100000 12⊤75 ←→ 6 3 318 | 16 16 16 16⊤100 ←→ 0 0 6 4 319 | 1760 3 12⊤75.3 ←→ 2 0(75.3-72) 320 | 0 1⊤75.3 ←→ 75(75.3-75) 321 | 2 2 2 2 2⊤1 2 3 4 5 ←→ 5 5⍴0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 0 1 322 | 10⊤5 15 125 ←→ 5 5 5 323 | 0 10⊤5 15 125 ←→ 2 3⍴0 1 12 5 5 5 324 | 0j1 2j3 4j5⊤6j7 ←→ 0 ¯2j2 2j2 325 | (8 3⍴2 0 0 2 0 0 2 0 0 2 0 0 2 8 0 2 8 0 2 8 16 2 8 16)⊤75 ←→ 8 3⍴0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 1 4 1 3 11 326 | 2 3 4 5 6∊1 2 3 5 8 13 21 ←→ 1 1 0 1 0 327 | 5∊1 2 3 5 8 13 21 ←→ 1 328 | ∊17 ←→ ,17 329 | ⍴∊(1 2 3)'ab'(4 5 6) ←→ ,8 330 | ∊2 2⍴(1+2 2⍴⍳4)'ab'(1+2 3⍴⍳6)(7 8) ←→ 1 2 3 4,'ab',1 2 3 4 5 6 7 8 331 | !0 5 21 ←→ 1 120 51090942171709440000 332 | !1.5 ¯1.5 ¯2.5 ←→ 1.3293403881791 ¯3.544907701811 2.3632718012074 333 | !¯200.5 ←→ 0 334 | !¯1 !! DOMAIN ERROR 335 | !¯200 !! DOMAIN ERROR 336 | 2!4 ←→ 6 337 | 3!20 ←→ 1140 338 | 2!6 12 20 ←→ 15 66 190 339 | (2 3⍴1+⍳6)!2 3⍴3 6 9 12 15 18 ←→ 2 3⍴3 15 84 495 3003 18564 340 | 0.5!1 ←→ 1.2732395447351612 341 | 1.2!3.4 ←→ 3.795253463731253 342 | !/⍬ ←→ 1 343 | (2!1000)=499500 ←→ 1 344 | (998!1000)=499500 ←→ 1 345 | 0.5!¯1 !! DOMAIN ERROR 346 | 3!5 ←→ 10 ⍝ 0 0 0 (!⍵)÷(!⍺)×!⍵-⍺ 347 | 5!3 ←→ 0 ⍝ 0 0 1 0 348 | 3!¯5 ←→ ¯35 ⍝ 0 1 1 (¯1*⍺)×⍺!⍺-⍵+1 349 | ¯3!5 ←→ 0 ⍝ 1 0 0 0 350 | ¯5!¯3 ←→ 6 ⍝ 1 1 0 (¯1*⍵-⍺)×(|⍵+1)!(|⍺+1) 351 | ¯3!¯5 ←→ 0 ⍝ 1 1 1 0 352 | ⍎'+/2 2⍴1 2 3 4' ←→ 3 7 353 | ⍴⍎'123 456' ←→ ,2 354 | ⍎'{⍵*2}⍳5' ←→ 0 1 4 9 16 355 | ⍎'let' !! 356 | ⍎'1 2 (3' !! 357 | 'ab'⍷'bababc' ←→ 0 1 0 1 0 0 358 | 'ab' 'cde'⍷'ab' 'cde' 'fg' ←→ 1 0 0 359 | 'cd'⍷'abcd efghi' ←→ 0 0 1 0 0 0 0 0 0 0 360 | 'day'⍷7 9⍴'sunday monday tuesday wednesdaythursday friday saturday ' ←→ 7 9⍴0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 361 | (2 2⍴'abcd')⍷'abcd' ←→ 4⍴0 362 | (1 2)(3 4)⍷'start'(1 2 3)(1 2)(3 4) ←→ 0 0 1 0 363 | (2 2⍴7 8 12 13)⍷1+4 5⍴⍳20 ←→ 4 5⍴0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 364 | 1⍷⍳5 ←→ 0 1 0 0 0 365 | 1 2⍷⍳5 ←→ 0 1 0 0 0 366 | ⍬⍷⍳5 ←→ 1 1 1 1 1 367 | ⍬⍷⍬ ←→ ⍬ 368 | 1⍷⍬ ←→ ⍬ 369 | 1 2 3⍷⍬ ←→ ⍬ 370 | (2 3 0⍴0)⍷3 4 5⍴0 ←→ 3 4 5⍴1 371 | (2 3 4⍴0)⍷3 4 0⍴0 ←→ 3 4 0⍴0 372 | (2 3 0⍴0)⍷3 4 0⍴0 ←→ 3 4 0⍴0 373 | ⌊123 12.3 ¯12.3 ¯123 ←→ 123 12 ¯13 ¯123 374 | ⌊12j3 1.2j2.3 1.2j¯2.3 ¯1.2j2.3 ¯1.2j¯2.3 ←→ 12j3 1j2 1j¯3 ¯1j2 ¯1j¯3 375 | ⌊0 5 ¯5 (○1) ¯1.5 ←→ 0 5 ¯5 3 ¯2 376 | ⌊'a' !! DOMAIN ERROR 377 | 3⌊5 ←→ 3 378 | ⌊/⍬ ←→ ¯ 379 | ⌈123 12.3 ¯12.3 ¯123 ←→ 123 13 ¯12 ¯123 380 | ⌈12j3 1.2j2.3 1.2j¯2.3 ¯1.2j2.3 ¯1.2j¯2.3 ←→ 12j3 1j3 1j¯2 ¯1j3 ¯1j¯2 381 | ⌈0 5 ¯5(○1)¯1.5 ←→ 0 5 ¯5 4 ¯1 382 | ⌈'a' !! DOMAIN ERROR 383 | 3⌈5 ←→ 5 384 | ⌈/⍬ ←→ ¯¯ 385 | (+/÷⍴)4 5 10 7 ←→ ,6.5 386 | (+,-,×,÷)2 ←→ 2 ¯2 1 .5 387 | 1(+,-,×,÷)2 ←→ 3 ¯1 2 .5 388 | a←1⋄b←¯22⋄c←85⋄√←{⍵*.5}⋄((-b)(+,-)√(b*2)-4×a×c)÷2×a ←→ 17 5 389 | ⍕123 ←→ 1 3⍴'123' 390 | ⍕123 456 ←→ 1 7⍴'123 456' 391 | ⍕123 'a' ←→ 1 5⍴'123 a' 392 | ⍕12 'ab' ←→ 1 7⍴'12 ab ' 393 | ⍕1 2⍴'a' ←→ 1 2⍴'a' 394 | ⍕2 2⍴'a' ←→ 2 2⍴'a' 395 | ⍕2 2⍴5 ←→ 2 3⍴'5 5','5 5' 396 | ⍕2 2⍴0 0 0 'a' ←→ 2 3⍴'0 0','0 a' 397 | ⍕2 2⍴0 0 0 'ab' ←→ 2 6⍴'0 0 ','0 ab ' 398 | ⍕2 2⍴0 0 0 123 ←→ 2 5⍴('0 0','0 123') 399 | ⍕4 3⍴'---' '---' '---' 1 2 3 4 5 6 100 200 300 ←→ 4 17⍴(' --- --- --- ',' 1 2 3 ',' 4 5 6 ',' 100 200 300 ') 400 | ⍕1 ⍬ 2 '' 3 ←→ 1 11⍴'1 2 3' 401 | ⍕∞ ←→ 1 1⍴'∞' 402 | ⍕¯∞ ←→ 1 2⍴'¯∞' 403 | ⍕¯1 ←→ 1 2⍴'¯1' 404 | ⍕¯1e¯100J¯2e¯99 ←→ 1 14⍴'¯1e¯100J¯2e¯99' 405 | ⍋13 8 122 4 ←→ 3 1 0 2 406 | a←13 8 122 4⋄a[⍋a] ←→ 4 8 13 122 407 | ⍋'ZAMBIA' ←→ 1 5 3 4 2 0 408 | s←'ZAMBIA'⋄s[⍋s] ←→ 'AABIMZ' 409 | t←3 3⍴'BOBALFZAK'⋄⍋t ←→ 1 0 2 410 | t←3 3⍴4 5 6 1 1 3 1 1 2⋄⍋t ←→ 2 1 0 411 | t←3 3⍴4 5 6 1 1 3 1 1 2⋄t[⍋t;] ←→ 3 3⍴ 1 1 2 1 1 3 4 5 6 412 | a←3 2 3⍴2 3 4 0 1 0 1 1 3 4 5 6 1 1 2 10 11 12⋄a[⍋a;;] ←→ 3 2 3⍴1 1 2 10 11 12 1 1 3 4 5 6 2 3 4 0 1 0 413 | a←3 2 5⍴'joe doe bob jonesbob zwart'⋄a[⍋a;;] ←→ 3 2 5⍴'bob jonesbob zwartjoe doe ' 414 | 'ZYXWVUTSRQPONMLKJIHGFEDCBA'⍋'ZAMBIA' ←→ 0 2 4 3 1 5 415 | ⎕A←'ABCDEFGHIJKLMNOPQRSTUVWXYZ'⋄(⌽⎕A)⍋3 3⍴'BOBALFZAK' ←→ 2 0 1 416 | a←6 4⍴'ABLEaBLEACREABELaBELACES'⋄a[(2 26⍴'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')⍋a;] ←→ 6 4⍴'ABELaBELABLEaBLEACESACRE' 417 | a←6 4⍴'ABLEaBLEACREABELaBELACES'⋄a[('AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz')⍋a;] ←→ 6 4⍴'ABELABLEACESACREaBELaBLE' 418 | ⍋0 1 2 3 4 3 6 6 4 9 1 11 12 13 14 15 ←→ 0 1 10 2 3 5 4 8 6 7 9 11 12 13 14 15 419 | ⍒3 1 8 ←→ 2 0 1 420 | f←{⍺+2×⍵}⋄f/⍬ !! DOMAIN ERROR 421 | f←{⍺+2×⍵}⋄(f⍁123)/⍬ ←→ 123 422 | f←{⍺+2×⍵}⋄(456⍁f)/⍬ ←→ 456 423 | f←{⍺+2×⍵}⋄g←f⍁789⋄f/⍬ !! DOMAIN ERROR 424 | {}⍁1 2 !! RANK ERROR 425 | ({}⍁(1 1 1⍴123))/⍬ ←→ 123 426 | 2 5 9 14 20⍳9 ←→ 2 427 | 2 5 9 14 20⍳6 ←→ 5 428 | 'abcde'⍳'d' ←→ 3 429 | ⎕a⍳'NGN/' ←→ 13 6 13 26 430 | 'ab' 'cd' 'efg'⍳'cd' 'efh' ←→ 1 3 431 | 1 3 2 0 3⍳⍳5 ←→ 3 0 2 1 5 432 | 'cat' 'dog' 'mouse'⍳'dog' 'bird' ←→ 1 3 433 | 1⍳1 !! RANK ERROR 434 | (1 2⍴3)⍳3 !! RANK ERROR 435 | 1 1⍳1 ←→ 0 436 | ⍬⍳1 2 ←→ 0 0 437 | 1 2⍳⍬ ←→ ⍬ 438 | ⍳5 ←→ 0 1 2 3 4 439 | ⍴⍳5 ←→ 1⍴5 440 | ⍳0 ←→ ⍬ 441 | ⍴⍳0 ←→ ,0 442 | ⍴⍳2 3 4 ←→ 2 3 4 443 | ⍳¯1 !! DOMAIN ERROR 444 | ⍳2 3 4 ←→ 2 3 4⍴(0 0 0)(0 0 1)(0 0 2)(0 0 3)(0 1 0)(0 1 1)(0 1 2)(0 1 3)(0 2 0)(0 2 1)(0 2 2)(0 2 3)(1 0 0)(1 0 1)(1 0 2)(1 0 3)(1 1 0)(1 1 1)(1 1 2)(1 1 3)(1 2 0)(1 2 1)(1 2 2)(1 2 3) 445 | ⍴⊂2 3⍴⍳6 ←→ ⍬ 446 | ⍴⍴⊂2 3⍴⍳6 ←→ ,0 447 | ⊂[0]2 3⍴⍳6 ←→ (0 3)(1 4)(2 5) 448 | ⍴⊂[0]2 3⍴⍳6 ←→ ,3 449 | ⊂[1]2 3⍴⍳6 ←→ (0 1 2)(3 4 5) 450 | ⍴⊂[1]2 3⍴⍳6 ←→ ,2 451 | ⊃⊂[1 0]2 3⍴⍳6 ←→ 3 2⍴0 3 1 4 2 5 452 | ⍴⊂[1 0]2 3⍴⍳6 ←→ ⍬ 453 | ⍴⊃⊂⊂1 2 3 ←→ ⍬ 454 | 0 0 1 1∨0 1 0 1 ←→ 0 1 1 1 455 | 12∨18 ←→ 6 456 | 299∨323 ←→ 1 457 | 12345∨12345 ←→ 12345 458 | 0∨123 ←→ 123 459 | 123∨0 ←→ 123 460 | ∨/⍬ ←→ 0 461 | ¯12∨18 ←→ 6 462 | 12∨¯18 ←→ 6 463 | ¯12∨¯18 ←→ 6 464 | 135j¯14∨155j34 ←→ 5j12 465 | 2 3 4∨0j1 1j2 2j3 ←→ 1 1 1 466 | 2j2 2j4∨5j5 4j4 ←→ 1j1 2 467 | 1.5∨2.5 !! DOMAIN ERROR 468 | 'a'∨1 !! DOMAIN ERROR 469 | 1∨'a' !! DOMAIN ERROR 470 | 'a'∨'b' !! DOMAIN ERROR 471 | 0 0 1 1∧0 1 0 1 ←→ 0 0 0 1 472 | 1∧3 3⍴1 1 1 0 0 0 1 0 1 ←→ 3 3⍴1 1 1 0 0 0 1 0 1 473 | ∧/3 3⍴1 1 1 0 0 0 1 0 1 ←→ 1 0 0 474 | 12∧18 ←→ 36 475 | 299∧323 ←→ 96577 476 | 123∧123 ←→ 123 477 | 0∧123 ←→ 0 478 | 123∧0 ←→ 0 479 | ∧/⍬ ←→ 1 480 | ¯12∧18 ←→ ¯36 481 | 12∧¯18 ←→ ¯36 482 | ¯12∧¯18 ←→ 36 483 | 1.5∧2.5 !! DOMAIN ERROR 484 | 'a'∧1 !! DOMAIN ERROR 485 | 1∧'a' !! DOMAIN ERROR 486 | 'a'∧'b' !! DOMAIN ERROR 487 | 135j¯14∧155j34 ←→ 805j¯1448 488 | 2 3 4∧0j1 1j2 2j3 ←→ 0j2 3j6 8j12 489 | 2j2 2j4∧5j5 4j4 ←→ 10j10 ¯4j12 490 | 0 0 1 1⍱0 1 0 1 ←→ 1 0 0 0 491 | 0⍱2 !! DOMAIN ERROR 492 | 0 0 1 1⍲0 1 0 1 ←→ 1 1 1 0 493 | 0⍲2 !! DOMAIN ERROR 494 | ~0 1 ←→ 1 0 495 | ~2 !! DOMAIN ERROR 496 | ({⍵+1}⍣5)3 ←→ 8 497 | ({⍵+1}⍣0)3 ←→ 3 498 | (⍴⍣3)2 2⍴⍳4 ←→ ,1 499 | 'a'(,⍣3)'b' ←→ 'aaab' 500 | 1{⍺+÷⍵}⍣=1 ←→ 1.618033988749895 501 | c←0⋄5⍣{c←c+1}0⋄c ←→ 5 502 | ⎕IO ←→ 0 503 | ⎕IO←0 ←→ 0 504 | 'b(c+)d'⎕RE'abcd' ←→ 1'bcd'(,'c') 505 | 'B(c+)d'⎕RE'abcd' ←→ ⍬ 506 | 'a(b'⎕RE'c' !! DOMAIN ERROR 507 | ⎕UCS'a' ←→ 97 508 | ⎕UCS'ab' ←→ 97 98 509 | ⎕UCS 2 2⍴97+⍳4 ←→ 2 2⍴'abcd' 510 | n←6⋄r←?n⋄(0≤r)∧(rs.split('\n').filter(x=>x) 5 | .map(x=>{let m=x.match(/^(.+)(←→|!!)(.*)$/);return[m[1].trim(),m[2].trim(),m[3].trim()]}) 6 | ,runDocTest=([s,m,exp],exec,aprx)=>{ // s:code, m:mode, exp:expectation 7 | let x,y 8 | if(m==='←→'){ 9 | try{y=exec(exp)}catch(e){return{e,m:'cannot compute expected value '+S(exp)}} 10 | try{x=exec(s);if(!aprx(x,y))return{m:' actual: '+S(x)+'\n expected: '+S(y)}}catch(e){return{e}} 11 | }else{ 12 | try{exec(s);return{m:"should have thrown but didn't"}}catch(e){ 13 | if(exp&&e.name.slice(0,exp.length)!==exp)return{e,m:' actual: '+S(e.name)+'\n expected: '+S(exp)} 14 | } 15 | } 16 | } 17 | if(typeof require!=='undefined'&&typeof module!=='undefined'&&module===require.main){ 18 | const t=collectTests(require('fs').readFileSync(__dirname+'/t.apl','utf8')) 19 | const apl=require('./apl'),so=process.stdout,t0=Date.now() 20 | let ne=0,nf=0,ts=0 //ne/nf:number of executed/failed tests, ts:last test timestamp 21 | for(let i=0;i100){so.write(ne+'/'+t.length+(nf?' ('+nf+' failed)':'')+'\r');ts=Date.now()} 25 | } 26 | so.write((nf?nf+'/'+ne+' tests failed':ne+' tests passed')+' in '+(Date.now()-t0)+' ms\n') 27 | process.exit(+!!nf) 28 | } 29 | -------------------------------------------------------------------------------- /web/Apl385.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abrudz/ngn-apl/d156d4e2b33c178e82dac55a19244014700d4cfa/web/Apl385.woff -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ngn/apl 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 | 29 | lb 31 | # 32 | 33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /web/index.js: -------------------------------------------------------------------------------- 1 | ;(_=>{ 2 | const a=document.body.querySelectorAll('[id]'),I={};for(let i=0;i{I.perm.href='#code='+escape(I.code.value);return!1} 8 | I.go.onclick=_=>{ 9 | try{const s=I.code.value;I.rslt.classList.remove('err') 10 | if(s===')t'){I.rslt.textContent='Running tests...\n';setTimeout(runDocTests,1)} 11 | else{I.rslt.textContent=apl.fmt(apl(s)).join('\n')+'\n'}} 12 | catch(e){console&&console.error&&console.error(e.stack);I.rslt.classList.add('err');I.rslt.textContent=e} 13 | return!1 14 | } 15 | hp.run&&I.go.click() 16 | I.code.focus() 17 | let bqm=0 18 | I.code.onkeydown=x=>{ 19 | const k=x.ctrlKey+2*x.shiftKey+4*x.altKey+8*x.metaKey+100*x.which 20 | if(bqm){ 21 | const e=I.code,i=e.selectionStart,v=e.value,c=bqc[x.key] 22 | if(x.which>31){bqm=0;e.classList.remove('bq')} 23 | if(c){e.value=v.slice(0,i)+c+v.slice(i);e.selectionStart=e.selectionEnd=i+1;return!1} 24 | } 25 | switch(k){ 26 | case 1301:{I.go.click();return!1} // ctrl-enter 27 | } 28 | } 29 | const get=(x,f)=>{const r=new XMLHttpRequest;r.open('get',x) 30 | r.onreadystatechange=x=>{r.readyState===4&&f(r.responseText)};r.send()} 31 | ,runDocTests=_=>{get('../t.apl',x=>{ 32 | const t=collectTests(x) 33 | I.rslt.classList.remove('err');I.rslt.textContent='' 34 | let ne=0,nf=0,t0=+new Date // ne:number of executed, nf:number of failed 35 | for(let i=0;i{ 2 | let hc={'<':'<','&':'&',"'":''','"':'"'},he=x=>x.replace(/[<&'"]/g,c=>hc[c]) //html chars and escape fn 3 | ,tcs='<-←xx×:-÷*o⍟[-⌹oo○ff⌈FF⌈ll⌊LL⌊tt⊥TT⊤-|⊣|-⊢~~≈=/≠<=≤>=≥==≡=-≢vv∨^^∧^~⍲v~⍱^|↑v|↓<<⊂>>⊃[|⌷A|⍋V|⍒ii⍳ee∊e-⍷'+ 4 | 'uu∪nn∩/-⌿\\-⍀,-⍪rr⍴pp⍴o|⌽o-⊖o\\⍉..¨~:⍨*:⍣o.∘[\'⍞[]⎕[:⍠[=⌸ot⍎oT⍕<>⋄on⍝aa⍺ww⍵a-⍶w-⍹VV∇--¯88∞0~⍬V~⍫//↗[/⍁' 5 | ,lbs=`←assign_+conjugate;add_-negate;subtract_×signum;multiply_÷reciprocal;divide_*exp;power_⍟ln;log 6 | ⌹matrix inverse;matrix divide_○pi;circular_!factorial;binomial_?roll;deal_|magnitude;residue_⌈ceiling;max_⌊floor;min 7 | ⊥decode_⊤encode_⊣left_⊢right_=equals_≈approx_≠not equals_≤lesser or equal to_greater than 8 | ≥greater or equal to_≡depth;match_≢tally;not match_∨or_∧and_⍲nand_⍱nor_↑mix;take_↓split;drop_⊂enclose_⊃first;pick 9 | ⌷index_⍋grade up_⍒grade down_⍳indices;index of_∊flatten;member of_⍷find_∪unique;union_∩intersection_~not;without 10 | /reduce;replicate_\\scan_⌿1st axis reduce;1st axis replicate_⍀1st axis scan_,enlist;catenate_⍪table;1st axis catenate 11 | ⍴shape of;reshape_⌽reverse;rotate_⊖1st axis reverse;1st axis rotate_⍉transpose;reorder axes_¨each_⍨selfie;commute 12 | ⍣power operator_.inner product_∘compose_⍞stdin/stdout_⎕eval\'ed stdin/stdout_⍠combine monadic-dyadic fns_⌸key operator 13 | ⍎execute_⍕format_⋄statement separator_⍝comment_⍺left argument_⍵right argument_⍶left operand_⍹right operand_∇recursion 14 | ¯negative_∞infinity_⍬empty numeric vector_⍫"return" reified as a function_↗throw_⍁identity element operator`.split(/[\n_]/) 15 | ,bqk=' =1234567890-qwertyuiop\\asdfghjkl;\'zxcvbnm,./`[]+!@#$%^&*()_QWERTYUIOP|ASDFGHJKL:"ZXCVBNM<>?~{}' 16 | ,bqv='`÷¨¯<≤=≥>≠∨∧×?⍵∊⍴~↑↓⍳○*⊢ ⍺⌈⌊_∇∆∘k⎕⍎⍕ ⊂⊃∩∪⊥⊤|⍝⍀⌿⋄←→⌹⌶⍫⍒⍋⌽⍉⊖⍟⍱⍲!⍰⍵⍷⍷⍨↑↓⍸⍥⍣⊣⍺⌈⌊_⍢HJ⌸⌷≡≢ZXCV⍭⍡∥⍪⍙⍠¤⍞⍬'.replace(/ /g,'') 17 | ,tc={},bqc={} //tab completions and ` completions 18 | for(let i=0;i') 24 | for(let j=0;j'+lbs[i][0]+'' 26 | } 27 | let d=document,el=d.createElement('div');el.innerHTML= 28 | `
${lbh}
29 | 30 | ` 39 | d.body.appendChild(el) 40 | let t,ts=[],lb=el.firstChild,bqm=0 //t:textarea or input, lb:language bar, bqm:backquote mode 41 | let pd=x=>x.preventDefault() 42 | let ev=(x,t,f,c)=>x.addEventListener(t,f,c) 43 | ev(lb,'mousedown',x=>{ 44 | if(x.target.classList.contains('ngn_x')){lb.hidden=1;upd();pd(x);return} 45 | if(x.target.nodeName==='B'&&t){ 46 | let i=t.selectionStart,j=t.selectionEnd,v=t.value,s=x.target.textContent 47 | if(i!=null&&j!=null){t.value=v.slice(0,i)+s+v.slice(j);t.selectionStart=t.selectionEnd=i+s.length} 48 | pd(x);return 49 | } 50 | }) 51 | let fk=x=>{ 52 | let t=x.target 53 | if(bqm){let i=t.selectionStart,v=t.value,c=bqc[x.key];if(x.which>31){bqm=0;d.body.classList.remove('ngn_bq')} 54 | if(c){t.value=v.slice(0,i)+c+v.slice(i);t.selectionStart=t.selectionEnd=i+1;pd(x);return!1}} 55 | switch(x.ctrlKey+2*x.shiftKey+4*x.altKey+8*x.metaKey+100*x.which){ 56 | case 19200:bqm=1;d.body.classList.add('ngn_bq');pd(x);break //` 57 | case 900:{let i=t.selectionStart,v=t.value,c=tc[v.slice(i-2,i)] //tab 58 | if(c){t.value=v.slice(0,i-2)+c+v.slice(i);t.selectionStart=t.selectionEnd=i-1;pd(x)} 59 | break} 60 | } 61 | } 62 | let ff=x=>{ 63 | let t0=x.target,nn=t0.nodeName.toLowerCase() 64 | if(nn!=='textarea'&&(nn!=='input'||t0.type!=='text'&&t0.type!=='search'))return 65 | t=t0;if(!t.ngn){t.ngn=1;ts.push(t);ev(t,'keydown',fk)} 66 | } 67 | let upd=_=>{d.body.style.marginTop=lb.clientHeight+'px'} 68 | upd();ev(window,'resize',upd) 69 | ev(d,'focus',ff,!0);let ae=d.activeElement;ae&&ff({type:'focus',target:ae}) 70 | })(); --------------------------------------------------------------------------------