├── .gitignore ├── BQN ├── LICENSE ├── REPL ├── app ├── AndroidManifest.xml ├── Drawable.pde ├── GUI.pde ├── Highlight.pde ├── Interpreter.pde ├── Keyboard.pde ├── Nfield.pde ├── P5.pde ├── PS.pde ├── ROText.pde ├── Tab.pde ├── TextReciever.pde ├── app.pde ├── code │ └── sketch.properties ├── cpJar ├── data │ ├── BQN386.ttf │ ├── L.json │ ├── Lcalc.json │ ├── Ldef.txt │ ├── P.json │ ├── def │ ├── kbs.txt │ ├── parse.js │ ├── test │ └── tetris ├── grapher.pde ├── readme.md ├── sketch.properties └── stuff.pde ├── build ├── build8 ├── readme.md ├── src └── BQN │ ├── Comp.java │ ├── Main.java │ ├── Scope.java │ ├── Sys.java │ ├── errors │ ├── AssertionError.java │ ├── BQNError.java │ ├── DomainError.java │ ├── ImplementationError.java │ ├── IncorrectArgsError.java │ ├── LengthError.java │ ├── NYIError.java │ ├── RankError.java │ ├── SyntaxError.java │ ├── SystemError.java │ └── ValueError.java │ ├── tokenizer │ ├── Tk2.java │ ├── Token.java │ ├── Tokenizer.java │ └── types │ │ ├── ArrayTok.java │ │ ├── BasicLines.java │ │ ├── BigTok.java │ │ ├── BlockTok.java │ │ ├── ChrTok.java │ │ ├── ColonTok.java │ │ ├── CommentTok.java │ │ ├── CompToken.java │ │ ├── ConstTok.java │ │ ├── DiamondTok.java │ │ ├── DotTok.java │ │ ├── ErrTok.java │ │ ├── ExportTok.java │ │ ├── LineTok.java │ │ ├── ModTok.java │ │ ├── NameTok.java │ │ ├── NothingTok.java │ │ ├── NullChrTok.java │ │ ├── NumTok.java │ │ ├── OpTok.java │ │ ├── ParenTok.java │ │ ├── PredTok.java │ │ ├── ScopeTok.java │ │ ├── SemiTok.java │ │ ├── SetTok.java │ │ ├── StrTok.java │ │ ├── StrandTok.java │ │ ├── StranderTok.java │ │ └── TokArr.java │ ├── tools │ ├── Body.java │ ├── FmtInfo.java │ ├── Format.java │ ├── Indexer.java │ ├── JBC.java │ ├── JBQNComp.java │ ├── JFn.java │ ├── MutByteArr.java │ ├── MutIntArr.java │ ├── MutVal.java │ ├── Pervasion.java │ └── SysVals.java │ └── types │ ├── Arr.java │ ├── BQNObj.java │ ├── BigValue.java │ ├── Callable.java │ ├── Char.java │ ├── Fun.java │ ├── Md1.java │ ├── Md2.java │ ├── Nothing.java │ ├── Num.java │ ├── Obj.java │ ├── Primitive.java │ ├── Tokenable.java │ ├── Value.java │ ├── arrs │ ├── BitArr.java │ ├── ChrArr.java │ ├── DoubleArr.java │ ├── EmptyArr.java │ ├── HArr.java │ ├── IntArr.java │ └── SingleItemArr.java │ ├── callable │ ├── Md1Derv.java │ ├── Md2Derv.java │ ├── Md2HalfDerv.java │ ├── blocks │ │ ├── FunBlock.java │ │ ├── Md1Block.java │ │ └── Md2Block.java │ ├── builtins │ │ ├── BaseNS.java │ │ ├── FileNS.java │ │ ├── FnBuiltin.java │ │ ├── MathNS.java │ │ ├── Md1Builtin.java │ │ ├── Md2Builtin.java │ │ ├── RandNS.java │ │ ├── fns │ │ │ ├── AndBuiltin.java │ │ │ ├── AssertBuiltin.java │ │ │ ├── CeilingBuiltin.java │ │ │ ├── DTackBuiltin.java │ │ │ ├── DivBuiltin.java │ │ │ ├── DownArrowBuiltin.java │ │ │ ├── EQBuiltin.java │ │ │ ├── EpsBuiltin.java │ │ │ ├── EvalBuiltin.java │ │ │ ├── FindBuiltin.java │ │ │ ├── FloorBuiltin.java │ │ │ ├── FormatBuiltin.java │ │ │ ├── GEBuiltin.java │ │ │ ├── GTBuiltin.java │ │ │ ├── GradeDownBuiltin.java │ │ │ ├── GradeUpBuiltin.java │ │ │ ├── GroupBuiltin.java │ │ │ ├── JoinBuiltin.java │ │ │ ├── LBoxBuiltin.java │ │ │ ├── LBoxUBBuiltin.java │ │ │ ├── LEBuiltin.java │ │ │ ├── LTBuiltin.java │ │ │ ├── LTackBuiltin.java │ │ │ ├── LaminateBuiltin.java │ │ │ ├── LogBuiltin.java │ │ │ ├── MatchBuiltin.java │ │ │ ├── MinusBuiltin.java │ │ │ ├── MulBuiltin.java │ │ │ ├── NEBuiltin.java │ │ │ ├── NotBuiltin.java │ │ │ ├── OrBuiltin.java │ │ │ ├── PairBuiltin.java │ │ │ ├── PlusBuiltin.java │ │ │ ├── RBoxBuiltin.java │ │ │ ├── RBoxUBBuiltin.java │ │ │ ├── RTackBuiltin.java │ │ │ ├── ReverseBuiltin.java │ │ │ ├── RootBuiltin.java │ │ │ ├── ShABuiltin.java │ │ │ ├── ShBBuiltin.java │ │ │ ├── ShapeBuiltin.java │ │ │ ├── SlashBuiltin.java │ │ │ ├── StarBuiltin.java │ │ │ ├── StileBuiltin.java │ │ │ ├── TallyBuiltin.java │ │ │ ├── TransposeBuiltin.java │ │ │ ├── UDBuiltin.java │ │ │ ├── UTackBuiltin.java │ │ │ └── UpArrowBuiltin.java │ │ ├── md1 │ │ │ ├── CellBuiltin.java │ │ │ ├── ConstBultin.java │ │ │ ├── EachBuiltin.java │ │ │ ├── EachLeft.java │ │ │ ├── EachRight.java │ │ │ ├── FoldBuiltin.java │ │ │ ├── InsertBuiltin.java │ │ │ ├── InvBuiltin.java │ │ │ ├── ObliqueBuiltin.java │ │ │ ├── OldKeyBuiltin.java │ │ │ ├── ScanBuiltin.java │ │ │ ├── SelfieBuiltin.java │ │ │ └── TableBuiltin.java │ │ └── md2 │ │ │ ├── AfterBuiltin.java │ │ │ ├── AmbivalentBuiltin.java │ │ │ ├── AtBuiltin.java │ │ │ ├── AtopBuiltin.java │ │ │ ├── BeforeBuiltin.java │ │ │ ├── CRepeatBuiltin.java │ │ │ ├── CatchBuiltin.java │ │ │ ├── CondBuiltin.java │ │ │ ├── DepthBuiltin.java │ │ │ ├── DotBuiltin.java │ │ │ ├── JotUBBuiltin.java │ │ │ ├── NCellBuiltin.java │ │ │ ├── ObverseBuiltin.java │ │ │ ├── OverBuiltin.java │ │ │ ├── RepeatBuiltin.java │ │ │ └── UnderBuiltin.java │ └── trains │ │ ├── Atop.java │ │ └── Fork.java │ └── mut │ ├── Alias.java │ ├── Local.java │ ├── MatchSettable.java │ ├── Namespace.java │ ├── Quad.java │ ├── Settable.java │ ├── SettableArr.java │ ├── SettableNS.java │ ├── SimpleMap.java │ └── Variable.java └── test ├── assignment ├── eq ├── export ├── headers ├── namespaces ├── shape ├── test ├── tk └── types /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | src/build 3 | .idea/ 4 | BQN.jar 5 | nBQN 6 | BQN.iml 7 | 8 | app/code/*.jar 9 | app/android/ 10 | app/build* 11 | app/application*/ 12 | 13 | *.apk -------------------------------------------------------------------------------- /BQN: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | java -jar BQN.jar "$@" 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 dzaima 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /REPL: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rlwrap -s99999 -H.history java -ea -jar BQN.jar "$@" -r 3 | -------------------------------------------------------------------------------- /app/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/Drawable.pde: -------------------------------------------------------------------------------- 1 | abstract static class Drawable { 2 | int x, y; 3 | int w, h; 4 | boolean visible; 5 | Drawable() { x=y=-100; w=h=100; } 6 | abstract void draw(); // called on every frame; won't be called when not visible 7 | void setVisible(boolean v) { this.visible = v; } // will be followed by a redraw() call if visible 8 | abstract void redraw(); // be careful on calling! 9 | final void upd(int x, int y, int w, int h) { // update everything; won't be called when not visible 10 | this.x = x; this.y = y; 11 | this.w = w; this.h = h; 12 | redraw(); 13 | } 14 | 15 | void mouseWheel(int dir) { } 16 | void mouseEvent(MouseEvent e, boolean pressed) { } 17 | boolean mouseInMe() { 18 | return a.mouseX > x && a.mouseY > y && a.mouseX < x+w && a.mouseY < y+h; 19 | } 20 | boolean smouseIn() { 21 | return smouseX > x && smouseY > y && smouseX < x+w && smouseY < y+h; 22 | } 23 | void pasted(String s) { 24 | throw new Error(this+" didn't ask for a clipboard!"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/GUI.pde: -------------------------------------------------------------------------------- 1 | static class TabSelect extends Drawable { 2 | int tsz; 3 | TopBar tb; 4 | Tab ctab; 5 | TabSelect() { 6 | tsz = MOBILE? scale*3/2 : scale; 7 | tb = new TopBar(this); 8 | } 9 | void setTsz(int ntsz) { 10 | tsz = ntsz; 11 | redraw(); 12 | } 13 | void redraw() { 14 | tb.upd(x, y, w, tsz); 15 | redrawTab(); 16 | } 17 | void redrawTab() { 18 | ctab.vw.upd(x, y+tsz, w, h-tsz); 19 | } 20 | void draw() { 21 | tb.draw(); 22 | ctab.vw.draw(); 23 | } 24 | void mouseWheel(int am) { 25 | ctab.vw.mouseWheel(am); 26 | } 27 | void mouseEvent(MouseEvent e, boolean pressed) { 28 | ctab.vw.mouseEvent(e, pressed); 29 | } 30 | } 31 | static class TopBar extends Drawable { 32 | ArrayList tabs = new ArrayList(); 33 | TabSelect ts; 34 | TopBar(TabSelect ts) { 35 | this.ts = ts; 36 | } 37 | void draw() { 38 | if (smouseIn() && a.mousePressed && !pmousePressed) { 39 | d.textSize(h*.8); 40 | int cx = x; 41 | for (Tab t : tabs) { 42 | String n = t.name(); 43 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 44 | if (a.mouseX > cx && a.mouseX < cx + dx) to(t); 45 | cx+= dx; 46 | } 47 | } 48 | } 49 | void redraw() { 50 | d.textSize(h*.8); 51 | d.rectMode(CORNER); 52 | d.fill(#222222); 53 | d.noStroke(); 54 | d.rect(x, y, w, h); 55 | 56 | int cx = x; 57 | for (Tab t : tabs) { 58 | String n = t.name(); 59 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 60 | if (t == ts.ctab) { 61 | d.fill(#333333); 62 | d.rect(cx, y, dx, h); 63 | } 64 | cx+= dx; 65 | } 66 | 67 | d.fill(#D2D2D2); 68 | d.textAlign(CENTER, CENTER); 69 | cx = x; 70 | for (Tab t : tabs) { 71 | String n = t.name(); 72 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 73 | d.text(n, cx + dx/2, y + h*.4); 74 | cx+= dx; 75 | } 76 | } 77 | void to(Tab t) { 78 | if (ts.ctab!=null) ts.ctab.vw.setVisible(false); 79 | ts.ctab = t; 80 | t.vw.setVisible(true); 81 | ts.redraw(); 82 | } 83 | void move(int d) { 84 | int i = tabs.indexOf(ts.ctab) + d; 85 | i%= tabs.size(); 86 | if (i < 0) i+= tabs.size(); 87 | to(tabs.get(i)); 88 | } 89 | void toNew(Tab t) { 90 | tabs.add(t); 91 | to(t); 92 | t.opened(); 93 | } 94 | void add(Tab t) { 95 | tabs.add(t); 96 | redraw(); 97 | } 98 | 99 | void closeCurr() { 100 | close(ts.ctab); 101 | } 102 | void close(Tab t) { 103 | if (tabs.size() == 1) return; 104 | int i = tabs.indexOf(t); 105 | if (i==-1) { println(t.name()+" was already closed"); return; } 106 | tabs.remove(i); 107 | if (t==ts.ctab) to(tabs.get(Math.max(0, i-1))); 108 | else ts.redraw(); 109 | t.close(); 110 | } 111 | } 112 | 113 | 114 | static class KBView extends Drawable { 115 | Drawable ct; 116 | KBView(Drawable ct) { 117 | this.ct = ct; 118 | } 119 | void redraw() { 120 | ct.upd(x, y , w, h-kb.h); 121 | kb.upd(x, y+h-kb.h, w, kb.h ); 122 | } 123 | void mouseWheel(int am) { 124 | ct.mouseWheel(am); 125 | } 126 | void draw() { ct.draw(); kb.draw(); } 127 | } 128 | -------------------------------------------------------------------------------- /app/ROText.pde: -------------------------------------------------------------------------------- 1 | static class ROText extends Drawable { 2 | float tsz, chw; 3 | ROText() { 4 | s = new ArrayList(); 5 | setSize(scale); 6 | } 7 | int xoff = 0; // scroll 8 | int yoff = 0; 9 | int border = 10; 10 | boolean redraw; 11 | void redraw() { 12 | beginClip(d, x+border, y, w-border*2, h); 13 | d.fill(#101010); 14 | d.noStroke(); 15 | d.rectMode(CORNER); 16 | d.rect(x, y, w, h); 17 | d.textAlign(LEFT, TOP); 18 | d.fill(#D2D2D2); 19 | d.stroke(#D2D2D2); 20 | d.strokeWeight(2); 21 | d.textSize(tsz); 22 | d.line(x, y+h, x+w, y+h); 23 | int dy = -s.size(); 24 | d.clip(x+border, y+3, w-border*2, h-6); 25 | for (String c : s) { 26 | float cy = dy*tsz + yoff; 27 | dy++; 28 | if (cy>-tsz && cy (max + 5)*chw) xoff = 0; 47 | if (xoff > 0) xoff = 0; 48 | } 49 | 50 | if (redraw) redraw(); 51 | } 52 | 53 | ArrayList s; 54 | boolean newline; 55 | void appendLns(String a) { 56 | String[] lns = split(a, "\n"); 57 | if (newline) { 58 | for (String s : lns) append(s); 59 | } else { 60 | if (s.size()==0) s.add(""); 61 | s.set(s.size()-1, s.get(s.size()-1)+lns[0]); 62 | for (int i = 1; i < lns.length; i++) append(lns[i]); 63 | } 64 | newline = a.endsWith("\n"); 65 | if (newline)s.remove(s.size()-1); 66 | } 67 | void append(String a) { // append a line 68 | s.add(a); 69 | yoff = h-border; 70 | xoff = 0; 71 | newline = true; 72 | redraw = true; 73 | } 74 | void set(ArrayList a) { 75 | s = a; 76 | yoff = h-border; 77 | xoff = 0; 78 | newline = true; 79 | redraw = true; 80 | } 81 | void setSize(int sz) { 82 | tsz = sz; 83 | a.textSize(tsz); 84 | chw = d.textWidth('H'); 85 | redraw = true; 86 | } 87 | void end() { 88 | yoff = h-border; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/TextReciever.pde: -------------------------------------------------------------------------------- 1 | abstract interface TextReciever { 2 | void append(String str); // may contain newlines 3 | void ldelete(); 4 | void rdelete(); 5 | void clear(); 6 | String allText(); 7 | void special(String s); 8 | void eval(); 9 | } 10 | -------------------------------------------------------------------------------- /app/code/sketch.properties: -------------------------------------------------------------------------------- 1 | mode=Java 2 | component=app 3 | mode.id=processing.mode.java.JavaMode 4 | -------------------------------------------------------------------------------- /app/cpJar: -------------------------------------------------------------------------------- 1 | cp ../BQN.jar code/BQN8.jar -------------------------------------------------------------------------------- /app/data/BQN386.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/BQN/6bf341b51297d174693f40a3dacbe17607726996/app/data/BQN386.ttf -------------------------------------------------------------------------------- /app/data/Ldef.txt: -------------------------------------------------------------------------------- 1 | 8×4 2 | center: up: down: col: left: right: 3 | L D←| ##### |12345678|10000012| | | 4 | «»⍳ ÷×A| |*^| √∧v|11222221| | | 5 | {}=≠ -+ |⍵⍺≥> | ≤< ∨ |33222222| | | 6 | ()/\ ⍴,¨|[]⌿⍀ ⍪ |########|33222222| | | -------------------------------------------------------------------------------- /app/data/def: -------------------------------------------------------------------------------- 1 | toSet ← ⍬ 2 | updated ← ⍬ 3 | app.update←updateFun←{ 4 | ⍺≢'portrait':← ⍬ ⍝ this is only for portrait 5 | ⎕IO←0 6 | dmap ← (u:1⋄l:3⋄r:4⋄d:2⋄c:0) 7 | L ← ⍵ 8 | m←dmap 9 | txt ← { 10 | 2=≡⍵:← ⍺ app.set '{"chr":"',(⊃⍵),'","type":"',(1⊃⍵),'"}' 11 | ⍺ app.set '{"chr":"',⍵,'"}' 12 | } 13 | L≡'ABC3': 1 4 m.u txt 'sd' ':ex /sdcard/def' 14 | L≡'ABC3': 1 4 m.l txt 'set' 'toSet←''''' 15 | L≡'ABC3': 2 1 0 txt 'derv' 16 | { 17 | x y dir l nm ← ⍵ 18 | l≡L: x y dir txt nm 19 | }¨updated 20 | } 21 | app.action ← { 22 | x y d l ← ⍵ 23 | ⍬≢toSet: { 24 | updated,←⊂ x y d l toSet 25 | ⎕← "L≡'",l,"': ",(⍕x)," ",(⍕y)," ",(⍕d)," txt '",toSet,"'" 26 | toSet⊢← ⍬ 27 | app.update ← updateFun 28 | 'stop' 29 | }⍵ 30 | } 31 | 1 -------------------------------------------------------------------------------- /app/data/parse.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | fs=require('fs'); 3 | if (!process.argv[2]) { 4 | process.argv[2] = 'kbs.txt'; 5 | } 6 | function chunks(arr, len) { 7 | let res = []; 8 | let i = 0; 9 | while(i < arr.length) { 10 | res.push(arr.slice(i, i+len)); 11 | i+= len; 12 | } 13 | return res; 14 | } 15 | chunks("hello!", 2); 16 | 17 | function parse(chr, mods) { 18 | let o = {chr: chr}; 19 | if (mods[chr]) { 20 | for (let mod of mods[chr]) { 21 | if (mod === 'sd') o.sd = true; 22 | else { 23 | let [key, val] = mod.split(/(? { 40 | let arr = c.split('\n'); 41 | let mods = {}; 42 | let layoutArr = []; 43 | let layouts = {}; 44 | while (arr.length) { 45 | let header = arr.shift(); 46 | if (header.startsWith("LAYOUT ")) { 47 | let [_, name, size, mainName, fullName] = header.split(" "); 48 | let [w, h] = size.split("×").map(c=>parseInt(c)); 49 | let o = {w, h, name, obj: {mainName, fullName}}; 50 | layouts[name] = o; 51 | layoutArr.push(o); 52 | } 53 | if (header.startsWith("MOD ")) { 54 | let [_, chr, ...data] = header.split(" "); 55 | if (!mods[chr]) mods[chr] = []; 56 | for (let cd of data) mods[chr].push(cd); 57 | } 58 | if (header.startsWith("PART ")) { 59 | arr.shift(); // column names 60 | let [_, name, layoutName] = header.split(" "); 61 | let layout = layouts[layoutName]; 62 | let w = layout.w; 63 | let h = layout.h; 64 | let ps = arr.slice(0, h).map(c=>chunks([...c], w+1).map(n=>n.slice(0, w))); 65 | console.table(ps.map(c=>c.map(k=>k.join('')))); 66 | let res = []; 67 | for (let y = 0; y < h; y++) { 68 | let row = []; 69 | let drow = ps[y]; 70 | for (let x = 0; x < w; x++) { 71 | row.push({ 72 | col: drow[3][x], 73 | def : parse(drow[0][x], mods), 74 | up : parse(drow[1][x], mods), 75 | down : parse(drow[2][x], mods), 76 | left : parse(drow[4][x], mods), 77 | right: parse(drow[5][x], mods), 78 | }); 79 | } 80 | res.push(row); 81 | } 82 | layout.obj[name] = res; 83 | } 84 | } 85 | 86 | for (let layout of layoutArr) { 87 | fs.writeFile(layout.name+".json", 88 | JSON.stringify({ 89 | "colors": ["ff101010", "FF134ADB", "FF282828", "FF353535"], 90 | "defcol": 1, 91 | ...layout.obj 92 | }), e=>console.log(e) 93 | ); 94 | } 95 | }); -------------------------------------------------------------------------------- /app/data/test: -------------------------------------------------------------------------------- 1 | g←p5.g 2 | p5.sz ← 2⥊400 3 | 4 | ram←0 5 | td←(p5.sz÷2) 6 | p5.Resized ← { 7 | td ↩ (10+𝕩÷2)∾20‿"D2"‿"center"‿"baseline" 8 | ram+↩ 1 9 | } 10 | 11 | p5.Draw ← {𝕩: 12 | g.BG '1' 13 | td g.Text "At frame "∾(⍕p5.fc)∾" "∾(⍕ram) 14 | (20⊸+⌾(1⊸⊑)td) g.Text ⍉>{∾⍕¨⟨𝕩.p,𝕩.pp,𝕩.c,𝕩.r⟩}¨⟨p5.lm,p5.mm,p5.rm⟩ 15 | a←¯12‿12+2÷˜1⊑p5.sz 16 | ⟨"80ffffff",2⟩ g.Ln 10‿a‿(¯10+⊑p5.sz)‿a 17 | ⟨"fff","00f",3⟩ g.Rect ⟨0‿100, 0‿0, 50‿150, 50‿50⟩ 18 | ⟨"80000000"⟩ g.Circle ⟨25‿75‿125, 25, 50⟩ 19 | ⟨"00f",3⟩ g.Ellipse ⟨75‿225÷2, 75, 75,50, "f00"‿"0f0"⟩ 20 | ((p5.sz-≢)g.Img⊢) {(𝕩∾˜0×𝕩)∾˘𝕩∾𝕩}⍟7 1‿1⥊¯1+2*32 21 | ⟨"0f0"⟩ g.Poly 200‿10‿220‿120‿300‿10 22 | } -------------------------------------------------------------------------------- /app/data/tetris: -------------------------------------------------------------------------------- 1 | p5.size ← 600‿800 2 | g←p5.g 3 | 4 | colors ← ∾⟜(⊑ .3 p5._lerp¨ ⊢) p5.Col¨ "0"‿"00fdff"‿"ff00ff"‿"ffff00"‿"ff8000"‿"0000ff"‿"00ff00"‿"ff0000" 5 | sz ← 23‿10 6 | b ← sz⥊0 7 | T ← {<˘⍉>𝕩} 8 | 9 | pcs ← T ⟨ # tetromino definitions: (blank) I T O L J S Z 10 | ⟨⟩‿⟨⟩ # blank 11 | ⟨¯1,0,1, 2⟩‿⟨ 0, 0,0, 0⟩ # I 12 | ⟨ 0,0,0,¯1⟩‿⟨ 0,¯1,1, 0⟩ # T 13 | ⟨ 0,1,0, 1⟩‿⟨ 0, 0,1, 1⟩ # O 14 | ⟨¯1,0,1, 1⟩‿⟨ 0, 0,0, 1⟩ # L 15 | ⟨¯1,0,1, 1⟩‿⟨ 0, 0,0,¯1⟩ # J 16 | ⟨ 0,0,1, 1⟩‿⟨ 1, 0,0,¯1⟩ # S 17 | ⟨ 0,0,1, 1⟩‿⟨¯1, 0,0, 1⟩ # Z 18 | ⟩ 19 | 20 | hpn ← 0 # held piece number 21 | hpu ← 0 # is held piece used up 22 | cpn ← 4 # current piece number 23 | cpp ← 5‿5 # current piece position 24 | cpr ← 0 # current piece rotation 25 | 26 | bsz ← 30 # block size 27 | osz ← 20 # UI block icon size 28 | speed ← 7 # how many frames between dropping due to gravity 29 | nextDown ← speed # current frame 30 | nextAm ← 4 # how many pieces to preview 31 | lockDelay ← 0 # frames to not lock down 32 | lockDef ← 15 # frames of default lock delaying on action 33 | nextPcs←⟨⟩ # future pieces 34 | 35 | ResetTime ← {𝕊: nextDown ↩ speed} 36 | 37 | 38 | 39 | Blks ← {(1‿¯1×⌽)⍟𝕨 𝕩⊑¨pcs} 40 | WithPc ← {n‿i𝕊b: n¨⌾((T i+cpr Blks cpn)⊸⊑) b} 41 | 42 | OK ← { 43 | nps ← 𝕩+𝕨 Blks cpn 44 | {∨´⥊>(nps<0)∨nps≥sz? 0; ∧´⥊0=nps T⊸⊑b} 45 | } 46 | Move ← { 47 | npp ← cpp+𝕩 48 | {cpp↩npp⋄𝕩}⍟⊢ cpr OK npp 49 | } 50 | 51 | SetPiece ← { 52 | cpn ↩ 𝕩 53 | cpp ↩ 2‿(4+cpn=5) 54 | cpr ↩ 0 55 | } 56 | RandPiece ← {𝕊: 57 | {𝕊: nextPcs∾↩1+•rand.Deal 7}⍟⊢ (1+nextAm)>≠nextPcs 58 | SetPiece ⊑nextPcs 59 | nextPcs↓˜↩ 1 60 | hpu ↩ 0 61 | lockDelay ↩ lockDef 62 | } 63 | NextPiece ← {𝕊: 64 | b ↩ (-∘≠↑(∨˝˘0=⊢)⊸/) cpn‿cpp WithPc b 65 | RandPiece@ 66 | } 67 | 68 | 69 | p5.Setup ← RandPiece 70 | NoLock ← {𝕊: {𝕊: lockDelay↩lockDef}⍟¬ cpr OK cpp+1‿0} 71 | keys ← ⟨ 72 | {k⇐"down" ⋄ t⇐0 ⋄ ST⇐{t↩𝕩} ⋄ s⇐0 ⋄ d⇐2 ⋄ F⇐{𝕊:NoLock⍟⊢Move 1‿0 }} 73 | {k⇐"left" ⋄ t⇐0 ⋄ ST⇐{t↩𝕩} ⋄ s⇐7 ⋄ d⇐4 ⋄ F⇐{𝕊:NoLock@⋄Move 0‿¯1}} 74 | {k⇐"right" ⋄ t⇐0 ⋄ ST⇐{t↩𝕩} ⋄ s⇐7 ⋄ d⇐4 ⋄ F⇐{𝕊:NoLock@⋄Move 0‿1 }} 75 | ⟩ 76 | 77 | DrawPiece ← {off𝕊n: (n⊑colors)‿"2"‿1 g.Rect (⊢∾osz+⊢) off+⌽osz×0 Blks n} 78 | p5.Draw ← {𝕊: 79 | g.BG "2" 80 | off ← .5×p5.sz-bsz×⌽sz # offset to center board 81 | db ← (¯20↑ cpn‿cpp WithPc ⟨cpn+8 ⋄ {cpr⊸OK◶𝕩‿𝕊 𝕩+1‿0}cpp⟩ WithPc b) # drawn board 82 | "2"‿1 g.Rect ((⊢∾bsz+⊢) off+⌽bsz×<˘⍉⁼>↕≢db)∾𝕩.s? 1=𝕩.d|t? k.F 1; @ 93 | }¨ keys 94 | } 95 | 96 | Rot ← {𝕊: NoLock@ ⋄ {cpr↩𝕩}⍟(OK⟜cpp) 4|cpr + (cpn≢3)×𝕩} 97 | p5.OnKey ← { 98 | " ": {𝕊⍟Move 1‿0}@ ⋄ NextPiece@; # hard drop 99 | "c": ¬hpu? hpu↩1 ⋄ t←hpn ⋄ hpn↩cpn ⋄ 0⊸≡◶SetPiece‿RandPiece t; # hold 100 | "z": Rot ¯1; 101 | "up": Rot 1; 102 | @ 103 | }∘⊢ -------------------------------------------------------------------------------- /app/readme.md: -------------------------------------------------------------------------------- 1 | A PC & Android app for BQN made in [Processing](https://processing.org/); [download APK](https://github.com/dzaima/BQN/releases/latest) 2 | 3 | Contains a REPL, a calculator-like keyboard for Android, and a very basic editor. Interprets dzaima/BQN. 4 | 5 | ### Run on PC: 6 | 1. build dzaima/BQN with Java 8 (by running `./build` in the base directory; `./build8` with a newer Java might not work (does not with Java 21)) 7 | 2. run `./cpJar` in the `app` directory 8 | 3. Open `app/` in Processing and run 9 | 10 | ### Compile for Android: 11 | 4. Install the Android mode in Processing (see top right corner → `Java`; requires Processing 3) and switch to it 12 | 5. In `PS.pde` change the first line to `/*` 13 | 6. Either run in Android Mode with a device connected, or File → Export Signed Package to generate an APK 14 | 15 | 16 | --- 17 | 18 | ``` 19 | swipe on characters to enter ones around it 20 | A - switch to text layout 21 | F - change capitalization of the name under the cursor 22 | ⇧ - shift - caps letters, select with «»; double tap to hold 23 | X - close tab (where applicable - grapher & editor) 24 | K - open virtual keyboard 25 | = - save /evaluate (keeps REPL input) 26 | ⏎ - enter/evaluate (clears REPL input) 27 | 28 | ↶↷ - undo/redo 29 | ▲▼ - up/down or move trough REPL history 30 | ^C/^V - copy/paste 31 | 32 | () / {} / ⟨⟩ allow wrapping around selected substring 33 | double-tap line in the history to edit it 34 | 35 | 36 | :isz sz change input box font size 37 | :hsz sz change REPL history font size 38 | :tsz sz change top bar size 39 | :g expr graph the expression (editable in the window) 40 | :clear clear REPL history 41 | :f path edit file at the path 42 | :fx path edit file at the path, executing on save 43 | :ex path execute file at the path 44 | :ed fn edit the function by name in another window (= - save, ⏎ - newline, X - save & close) 45 | ``` 46 | -------------------------------------------------------------------------------- /app/sketch.properties: -------------------------------------------------------------------------------- 1 | mode=Android 2 | mode.id=processing.mode.android.AndroidMode 3 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | rm -f BQN.jar 3 | mkdir -p classes 4 | javac -encoding UTF-8 -d ./classes $(find src -name '*.java') 5 | cd classes 6 | jar cvfe BQN.jar BQN.Main * > /dev/null 7 | mv BQN.jar ../BQN.jar 8 | cd .. 9 | rm -rf classes -------------------------------------------------------------------------------- /build8: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | rm -f BQN.jar 3 | mkdir -p classes 4 | javac --release 8 -encoding UTF-8 -d ./classes $(find src -name '*.java') || echo "Note: ./build8 can only be run in Java 9 and later. Use ./build on java 8" 5 | cd classes 6 | jar cvfe BQN.jar BQN.Main * > /dev/null 7 | mv BQN.jar ../BQN.jar 8 | cd .. 9 | rm -rf classes -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | A [BQN](https://github.com/mlochbaum/BQN) implementation based on dzaima/APL 2 | 3 | `./build` to build a `.jar` file 4 | 5 | `./REPL` to start a simple REPL 6 | 7 | Adding the following to `~/bin/dbqn` will make hashbangs like `#!/usr/bin/env dbqn` execute dzaima/BQN: 8 | ```bash 9 | #!/bin/bash 10 | 11 | java -jar /path/to/dzaima/BQN/BQN.jar -f "$@" 12 | ``` 13 | 14 | With GraalVM's Native Image, you can build a complete binary (≈10MB, doesn't need Java at all, startup time <10ms): 15 | 16 | ```bash 17 | native-image --report-unsupported-elements-at-runtime -J-Dfile.encoding=UTF-8 -jar BQN.jar nBQN 18 | ``` 19 | This generates a regular executable file `nBQN`, usable in place of `java -jar BQN.jar`. Note that this also disables compilation to Java bytecode, and has different performance characteristics to a regular JVM. 20 | 21 | 22 | ### [app](https://github.com/dzaima/BQN/tree/master/app) 23 | A BQN-specific app with syntax highlighting and most regular text editor stuff (very much work in progress) 24 | 25 | Works on Linux and Android (should work on Windows, assuming bash is available to compile BQN itself) -------------------------------------------------------------------------------- /src/BQN/errors/AssertionError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.callable.builtins.fns.AssertBuiltin; 4 | 5 | public class AssertionError extends BQNError { 6 | public AssertionError(String msg, AssertBuiltin b) { 7 | super(msg, b); 8 | } 9 | } -------------------------------------------------------------------------------- /src/BQN/errors/DomainError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class DomainError extends BQNError { 6 | public DomainError(String s) { 7 | super(s); 8 | } 9 | 10 | public DomainError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/errors/ImplementationError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class ImplementationError extends BQNError { 6 | public ImplementationError(String s) { 7 | super(s); 8 | } 9 | 10 | public ImplementationError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | 14 | public ImplementationError(Throwable orig) { 15 | super(orig.toString()); 16 | initCause(orig); 17 | } 18 | } -------------------------------------------------------------------------------- /src/BQN/errors/IncorrectArgsError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class IncorrectArgsError extends BQNError { 6 | public IncorrectArgsError(String s, Tokenable blame) { 7 | super(s, blame); 8 | } 9 | } -------------------------------------------------------------------------------- /src/BQN/errors/LengthError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class LengthError extends BQNError { 6 | public LengthError(String s) { 7 | super(s); 8 | } 9 | 10 | public LengthError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/errors/NYIError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class NYIError extends BQNError { // AKA LazyError 6 | public NYIError(String s) { 7 | super(s); 8 | } 9 | 10 | public NYIError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/errors/RankError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class RankError extends BQNError { 6 | public RankError(String s) { 7 | super(s); 8 | } 9 | 10 | public RankError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/errors/SyntaxError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class SyntaxError extends BQNError { 6 | public SyntaxError(String s) { 7 | super(s); 8 | } 9 | 10 | public SyntaxError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/errors/SystemError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | public class SystemError extends BQNError { 4 | public SystemError(String msg, Throwable p) { 5 | super(msg); 6 | initCause(p); 7 | } 8 | } -------------------------------------------------------------------------------- /src/BQN/errors/ValueError.java: -------------------------------------------------------------------------------- 1 | package BQN.errors; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public class ValueError extends BQNError { 6 | public ValueError(String s) { 7 | super(s); 8 | } 9 | 10 | public ValueError(String s, Tokenable blame) { 11 | super(s, blame); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/Token.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer; 2 | 3 | import BQN.types.Tokenable; 4 | 5 | public abstract class Token implements Tokenable { 6 | public char type; // \0 by default 7 | public byte flags = -1; // 1 - is constant; 2 - has no inner blocks; 4 - is safe for variable renaming 8 | public final String raw; 9 | public final int spos; // incl 10 | public final int epos; // excl 11 | public Token(String raw, int spos, int epos) { 12 | this.raw = raw; 13 | this.spos = spos; 14 | this.epos = epos; 15 | } 16 | 17 | @Override public Token getToken() { 18 | return this; 19 | } 20 | public String toTree(String p) { 21 | return p + this.getClass().getSimpleName()+" "+spos+"-"+epos+" "+type+" "+flags+"\n"; 22 | } 23 | public abstract String toRepr(); 24 | 25 | public String source() { 26 | return raw.substring(spos, epos); 27 | } 28 | 29 | 30 | public static Token COMP = new Token("•COMPiled function", 0, 18) { 31 | public String toRepr() { 32 | return "•COMPiled function"; 33 | } 34 | }; 35 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ArrayTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | import java.util.List; 6 | 7 | public class ArrayTok extends TokArr { 8 | 9 | public ArrayTok(String line, int spos, int epos, List tokens) { 10 | super(line, spos, epos, tokens); 11 | } 12 | 13 | @Override public String toRepr() { 14 | StringBuilder s = new StringBuilder("⟨"); 15 | boolean tail = false; 16 | for (Token v : tokens) { 17 | if (tail) s.append(" ⋄ "); 18 | s.append(v.toRepr()); 19 | tail = true; 20 | } 21 | s.append("⟩"); 22 | return s.toString(); 23 | } 24 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/BasicLines.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class BasicLines extends TokArr { 8 | public BasicLines(String line, int spos, int epos, ArrayList tokens) { 9 | super(line, spos, epos, tokens); 10 | } 11 | 12 | @Override public String toRepr() { 13 | StringBuilder s = new StringBuilder(); 14 | boolean tail = false; 15 | for (Token v : tokens) { 16 | if (tail) s.append("\n"); 17 | s.append(v.toRepr()); 18 | tail = true; 19 | } 20 | return s.toString(); 21 | } 22 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/BigTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.types.BigValue; 4 | 5 | public class BigTok extends ConstTok { 6 | public BigTok(String line, int spos, int epos, BigValue val) { 7 | super(line, spos, epos, val); 8 | } 9 | @Override public String toRepr() { 10 | return source(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ChrTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.errors.SyntaxError; 4 | import BQN.types.Char; 5 | 6 | public class ChrTok extends ConstTok { 7 | 8 | public ChrTok(String line, int spos, int epos, String str) { 9 | super(line, spos, epos, Char.of(str.charAt(0))); 10 | if (str.length() != 1) throw new SyntaxError("Characters must be UTF-16", this); 11 | } 12 | 13 | public ChrTok(String line, int spos, int epos, char chr) { 14 | this(line, spos, epos, String.valueOf(chr)); 15 | } 16 | 17 | public String toRepr() { 18 | return source(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ColonTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ColonTok extends Token { 6 | public ColonTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | type = ':'; 9 | flags = 0; 10 | } 11 | 12 | @Override public String toRepr() { 13 | return ":"; 14 | } 15 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/CommentTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class CommentTok extends Token { 6 | public CommentTok(String raw, int spos, int epos) { 7 | super(raw, spos, epos); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return source(); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/CompToken.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class CompToken extends Token { 6 | public CompToken(String raw, int spos, int epos) { 7 | super(raw, spos, epos); 8 | } 9 | 10 | public String toRepr() { 11 | return source(); 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ConstTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | 7 | public abstract class ConstTok extends Token { 8 | public final Value val; 9 | 10 | public ConstTok(String raw, int spos, int epos, Value val) { 11 | super(raw, spos, epos); 12 | this.val = val; 13 | type = 'a'; 14 | } 15 | 16 | 17 | public String toTree(String p) { 18 | return p+(getClass().getSimpleName())+" val="+val.ln(FmtInfo.def)+"\n"; 19 | } 20 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/DiamondTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class DiamondTok extends Token { 6 | public DiamondTok(String raw, int pos) { 7 | super(raw, pos, pos+1); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return "⋄"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/DotTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class DotTok extends Token { 6 | 7 | public DotTok(String raw, int spos, int epos) { 8 | super(raw, spos, epos); 9 | type = '.'; 10 | flags = 6; 11 | } 12 | 13 | public String toRepr() { 14 | return "."; 15 | } 16 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ErrTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ErrTok extends Token { 6 | public ErrTok(String raw, int spos, int epos) { 7 | super(raw, Math.max(0,spos), Math.min(epos,raw.length()-1)); 8 | } 9 | public ErrTok(String raw, int onepos) { 10 | this(raw, onepos, onepos+1); 11 | } 12 | 13 | @Override public String toRepr() { 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ExportTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ExportTok extends Token { 6 | 7 | public ExportTok(String line, int spos, int epos) { 8 | super(line, spos, epos); 9 | type = '⇐'; 10 | flags = 2; 11 | } 12 | 13 | public String toRepr() { 14 | return "⇐"; 15 | } 16 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/LineTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | import java.util.List; 6 | 7 | public class LineTok extends TokArr { // +TODO make things using this verify end 8 | 9 | public LineTok(String raw, int spos, int epos, List tokens) { 10 | super(raw, spos, epos, tokens); 11 | } 12 | 13 | public String toString() { 14 | return toRepr(); 15 | } 16 | 17 | @Override public String toRepr() { 18 | StringBuilder s = new StringBuilder(); 19 | boolean tail = false; 20 | for (Token v : tokens) { 21 | if (tail) s.append(" "); 22 | s.append(v.toRepr()); 23 | tail = true; 24 | } 25 | return s.toString(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ModTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ModTok extends Token { 6 | public ModTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | type = '↩'; 9 | } 10 | 11 | @Override public String toRepr() { 12 | return "←"; 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/NameTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import java.nio.file.*; 4 | import BQN.errors.SyntaxError; 5 | import BQN.tokenizer.Token; 6 | import BQN.tools.SysVals; 7 | import BQN.types.*; 8 | import BQN.types.arrs.*; 9 | import BQN.types.callable.builtins.FileNS; 10 | 11 | public class NameTok extends Token { 12 | public final String name; 13 | public final String rawName; 14 | public Value val; 15 | 16 | public NameTok(String line, int spos, int epos, String rawName, Value[] args) { 17 | super(line, spos, epos); 18 | this.rawName = rawName; 19 | this.type = varType(rawName); 20 | if (rawName.length()<=2 && type=='d') throw new SyntaxError("\""+rawName+"\" is an invalid name", this); 21 | boolean isSys = rawName.charAt(0) == '•'; 22 | String name0 = (isSys? rawName.substring(1) : rawName).toLowerCase(); 23 | String name1 = name0.replace("_", ""); 24 | name = isSys? '•'+name1 : name1; 25 | if (isSys) switch (SysVals.rel(name)) { 26 | case 1: if (args==null||args[0]==null) throw new SyntaxError("•path hasn't been defined", this); val = args[0]; break; 27 | case 2: if (args==null||args[1]==null) throw new SyntaxError("•name hasn't been defined", this); val = args[1]; break; 28 | case 3: if (args==null||args[2]==null) throw new SyntaxError("•args hasn't been defined", this); val = args[2]; break; 29 | case 4: 30 | if (args==null) val = EmptyArr.SHAPE0SV; 31 | else val = new HArr(args); 32 | break; 33 | case 5: 34 | val = new ChrArr(Paths.get("").toAbsolutePath().toString()); 35 | break; 36 | case 6: if (args==null||args[0]==null) throw new SyntaxError("•path hasn't been defined for •file", this); 37 | val = new FileNS(Paths.get(args[0].asString())); 38 | break; 39 | case 10: 40 | if (args==null) val = Nothing.inst; 41 | else val = args[0]; 42 | break; 43 | } 44 | } 45 | public static char varType(String name) { 46 | char s = name.charAt(0); 47 | if (s=='•') s = name.charAt(1); 48 | if (s=='_') { 49 | char e = name.charAt(name.length()-1); 50 | return e=='_'? 'd' : 'm'; 51 | } 52 | if (s>='A' && s<='Z') return 'f'; 53 | return 'a'; 54 | } 55 | 56 | @Override public String toTree(String p) { 57 | return p+"name: " + rawName + "\n"; 58 | } 59 | 60 | @Override public String toRepr() { 61 | return rawName; 62 | } 63 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/NothingTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | import BQN.types.Nothing; 5 | 6 | public class NothingTok extends Token { 7 | public final Nothing val; 8 | 9 | public NothingTok(String raw, int spos, int epos) { 10 | super(raw, spos, epos); 11 | val = Nothing.inst; 12 | type = 'A'; 13 | } 14 | 15 | public String toRepr() { 16 | return "·"; 17 | } 18 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/NullChrTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.types.Char; 4 | 5 | public class NullChrTok extends ConstTok { 6 | 7 | public NullChrTok(String raw, int spos, int epos) { 8 | super(raw, spos, epos, Char.of('\0')); 9 | type = 'A'; 10 | } 11 | 12 | public String toRepr() { 13 | return "@"; 14 | } 15 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/NumTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.types.Num; 4 | 5 | public class NumTok extends ConstTok { 6 | 7 | public NumTok(String line, int spos, int epos, double d) { 8 | super(line, spos, epos, Num.of(d)); 9 | } 10 | 11 | public String toRepr() { 12 | return source(); 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/OpTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.Comp; 4 | import BQN.tokenizer.Token; 5 | import BQN.types.Callable; 6 | 7 | public class OpTok extends Token { 8 | public final String op; 9 | public final Callable b; 10 | 11 | public OpTok(String line, int spos, int epos, String op) { 12 | super(line, spos, epos); 13 | this.op = op; 14 | this.b = Comp.builtin(op.charAt(0), this); 15 | if (b != null) b.token = this; 16 | } 17 | public OpTok(String line, int spos, int epos, char op) { 18 | super(line, spos, epos); 19 | this.op = String.valueOf(op); 20 | this.b = Comp.builtin(op, this); 21 | if (b != null) b.token = this; 22 | } 23 | 24 | public String toRepr() { 25 | return op; 26 | } 27 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ParenTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ParenTok extends Token { 6 | public final Token ln; 7 | 8 | public ParenTok(String line, int spos, int epos, Token ln) { 9 | super(line, spos, epos); 10 | this.ln = ln; 11 | } 12 | 13 | @Override public String toRepr() { 14 | return "(" + ln.toRepr() + ")"; 15 | } 16 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/PredTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class PredTok extends Token { 6 | public PredTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | type = '?'; 9 | flags = 0; 10 | } 11 | 12 | @Override public String toRepr() { 13 | return "?"; 14 | } 15 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/ScopeTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class ScopeTok extends Token { 6 | public ScopeTok(String raw, int spos, int epos) { 7 | super(raw, spos, epos); 8 | } 9 | 10 | public String toRepr() { 11 | return "#"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/SemiTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class SemiTok extends Token { 6 | public SemiTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | type = ';'; 9 | flags = 0; 10 | } 11 | 12 | @Override public String toRepr() { 13 | return ";"; 14 | } 15 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/SetTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class SetTok extends Token { 6 | public SetTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | type = '←'; 9 | } 10 | 11 | @Override public String toRepr() { 12 | return "←"; 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/StrTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.types.arrs.ChrArr; 4 | 5 | public class StrTok extends ConstTok { 6 | 7 | public StrTok(String line, int spos, int epos, String str) { 8 | super(line, spos, epos, new ChrArr(str)); 9 | } 10 | 11 | public String toRepr() { 12 | return source(); 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/StrandTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | import java.util.List; 6 | 7 | public class StrandTok extends TokArr { 8 | 9 | public StrandTok(String line, int spos, int epos, List tokens) { 10 | super(line, spos, epos, tokens); 11 | } 12 | 13 | public String toRepr() { 14 | StringBuilder s = new StringBuilder(); 15 | boolean tail = false; 16 | for (Token v : tokens) { 17 | if (tail) s.append("‿"); 18 | s.append(v.toRepr()); 19 | tail = true; 20 | } 21 | return s.toString(); 22 | } 23 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/StranderTok.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public class StranderTok extends Token { 6 | public StranderTok(String raw, int spos, int epos) { 7 | super(raw, spos, epos); 8 | } 9 | 10 | public String toRepr() { 11 | return "‿"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/BQN/tokenizer/types/TokArr.java: -------------------------------------------------------------------------------- 1 | package BQN.tokenizer.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | import java.util.List; 6 | 7 | abstract public class TokArr extends Token { 8 | public final List tokens; 9 | 10 | TokArr(String line, int spos, int epos, List tokens) { 11 | super(line, spos, epos); 12 | this.tokens = tokens; 13 | } 14 | 15 | public String toTree(String p) { 16 | StringBuilder r = new StringBuilder(); 17 | r.append(p).append(this.getClass().getSimpleName()); 18 | r.append(' ').append(spos).append('-').append(epos).append(' ').append(type).append(' ').append(flags); 19 | r.append('\n'); 20 | p+= " "; 21 | for (Token t : tokens) r.append(t.toTree(p)); 22 | return r.toString(); 23 | } 24 | } -------------------------------------------------------------------------------- /src/BQN/tools/FmtInfo.java: -------------------------------------------------------------------------------- 1 | package BQN.tools; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.types.Value; 5 | import BQN.types.arrs.ChrArr; 6 | 7 | import java.util.HashSet; 8 | 9 | public class FmtInfo { 10 | public static FmtInfo def = new FmtInfo(99, 10, 10); 11 | 12 | public final int pp; 13 | public final int pns, pne; // use positional notation in (10*-pns)…(10*pne) 14 | public final HashSet v = new HashSet<>(); 15 | 16 | public FmtInfo(int pp, int pns, int pne) { 17 | this.pp = pp; 18 | this.pns = pns; 19 | this.pne = pne; 20 | } 21 | 22 | public static String fmt(Value v) { 23 | if (v.r()==1) { 24 | if (v instanceof ChrArr) return ((ChrArr) v).s; 25 | StringBuilder b = new StringBuilder(); 26 | for (Value c : v) b.append(c.asString()); 27 | return b.toString(); 28 | } else { 29 | if (v instanceof ChrArr) return Format.outputFmt(v); 30 | int h = v.shape[0]; 31 | int w = v.shape[1]; 32 | StringBuilder b = new StringBuilder(); 33 | for (int y = 0; y < h; y++) { 34 | if (y!=0) b.append("\n"); 35 | for (int x = 0; x < w; x++) b.append(v.get(y*w + x).asString()); 36 | } 37 | return b.toString(); 38 | } 39 | } 40 | 41 | 42 | 43 | public FmtInfo with(int pp, int pns, int pne) { 44 | if (pp < 2) throw new DomainError("Significant digit count must be ≥2"); 45 | return new FmtInfo(pp, pns, pne); 46 | } 47 | public FmtInfo with(int[] args) { 48 | if (args.length==0) return this; 49 | else if (args.length==1) return with(args[0], pns, pne); 50 | else if (args.length==2) return with(args[0], args[1], args[1]); 51 | else if (args.length==3) return with(args[0], args[1], args[2]); 52 | else throw new DomainError("Cannot use "+args.length+"-item vector as formatting specification"); 53 | } 54 | } -------------------------------------------------------------------------------- /src/BQN/tools/Format.java: -------------------------------------------------------------------------------- 1 | package BQN.tools; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.types.*; 5 | import BQN.types.arrs.ChrArr; 6 | 7 | public class Format { 8 | public static String outputFmt(Value v) { 9 | if (v instanceof Primitive) { 10 | if (v instanceof Num) { 11 | double n = ((Num) v).num; 12 | long b = Double.doubleToRawLongBits(n); 13 | if (Double.isInfinite(n)) return n==Double.POSITIVE_INFINITY? "∞" : "¯∞"; 14 | if (Double.isNaN(n)) return "NaN"; 15 | StringBuilder s = new StringBuilder(b<0? "¯" : ""); 16 | s.append(Math.abs(n)); 17 | int l = s.length(); 18 | if (s.charAt(l-2)=='.' && s.charAt(l-1)=='0') s.delete(l-2, l); 19 | return s.toString(); 20 | } 21 | if (v instanceof Char) return String.valueOf(((Char) v).chr); 22 | if (v instanceof BigValue) return ((BigValue) v).i.toString(); 23 | throw new DomainError("Cannot format "+v.humanType(true)); 24 | } 25 | if (v.r() > 2) throw new DomainError("Cannot format rank "+v.r()+" array"); 26 | if (v.r()<=1) { 27 | if (v instanceof ChrArr) { 28 | return v.asString(); 29 | } else { 30 | StringBuilder b = new StringBuilder(v.ia); 31 | for (Value c : v) { 32 | if (!(c instanceof Char)) throw new DomainError("Cannot format array of non-chars"); 33 | b.append(((Char) c).chr); 34 | } 35 | return b.toString(); 36 | } 37 | } else { 38 | StringBuilder b = new StringBuilder(v.ia); 39 | int h = v.shape[0]; 40 | int w = v.shape[1]; 41 | if (v instanceof ChrArr) { 42 | String str = ((ChrArr) v).s; 43 | for (int y = 0; y < h; y++) { 44 | b.append(str, y*w, (y+1)*w); 45 | if (y!=h-1) b.append('\n'); 46 | } 47 | } else { 48 | for (int y = 0; y < h; y++) { 49 | // b.append(str, y*w, (y+1)*w); 50 | for (int x = 0; x < w; x++) { 51 | Value c = v.get(x+y*w); 52 | if (!(c instanceof Char)) throw new DomainError("Cannot format array of non-chars"); 53 | b.append(((Char) c).chr); 54 | } 55 | if (y!=h-1) b.append('\n'); 56 | } 57 | } 58 | return b.toString(); 59 | } 60 | } 61 | 62 | public static Value str(String s) { // TODO split graphemes, color escapes, etc idk 63 | int len = s.codePointCount(0, s.length()); 64 | if (len==s.length()) return new ChrArr(s); 65 | MutVal mv = new MutVal(Arr.vecsh(len), Char.SPACE); 66 | int i=0, o=0; 67 | while (i < s.length()) { 68 | int c = s.codePointAt(i); 69 | int csz = Character.charCount(c); 70 | mv.set(o++, chr(c, csz)); 71 | i+= csz; 72 | } 73 | return mv.get(); 74 | } 75 | 76 | public static Value chr(int c, int csz) { 77 | return csz==1? Char.of((char) c) : new ChrArr(new String(Character.toChars(c))); 78 | } 79 | public static String chr(int c) { 80 | return Character.charCount(c)==1? Character.toString((char) c) : new String(Character.toChars(c)); 81 | } 82 | } -------------------------------------------------------------------------------- /src/BQN/tools/JFn.java: -------------------------------------------------------------------------------- 1 | package BQN.tools; 2 | 3 | import BQN.Scope; 4 | import BQN.types.Value; 5 | 6 | public abstract class JFn { 7 | public abstract Value get(Scope sc, Body bd); 8 | } -------------------------------------------------------------------------------- /src/BQN/tools/MutByteArr.java: -------------------------------------------------------------------------------- 1 | package BQN.tools; 2 | 3 | import java.util.Arrays; 4 | 5 | public class MutByteArr { 6 | public byte[] bs; 7 | public int len; 8 | 9 | public MutByteArr() { 10 | bs = new byte[20]; 11 | } 12 | public MutByteArr(int cap) { 13 | bs = new byte[cap]; 14 | } 15 | private void dbl() { 16 | bs = Arrays.copyOf(bs, bs.length*2); 17 | } 18 | 19 | public void u(int v) { 20 | assert v>=0 && v<256; 21 | if (len>=bs.length) dbl(); 22 | bs[len++] = (byte) v; 23 | } 24 | public void u(byte... v) { 25 | while (len+v.length>=bs.length) dbl(); 26 | System.arraycopy(v,0,bs,len,v.length); 27 | len+= v.length; 28 | } 29 | public void u(int... v) { 30 | while (len+v.length>=bs.length) dbl(); 31 | for (int i = 0; i < v.length; i++) { 32 | int c = v[i]; 33 | assert c>=0 && c<255; 34 | bs[i+len] = (byte) c; 35 | } 36 | len+= v.length; 37 | } 38 | public void u2(int v) { 39 | assert v>=0 && v<65536; 40 | u((v>>8)&0xff); 41 | u( v &0xff); 42 | } 43 | public void u4(int v) { 44 | u((v>>24)&0xff); 45 | u((v>>16)&0xff); 46 | u((v>> 8)&0xff); 47 | u( v &0xff); 48 | } 49 | 50 | public void s(byte v) { 51 | if (len>=bs.length) dbl(); 52 | bs[len++] = v; 53 | } 54 | public void s(int v) { 55 | assert (byte)v == v; 56 | if (len>=bs.length) dbl(); 57 | bs[len++] = (byte) v; 58 | } 59 | public void s2(int v) { 60 | assert (short)v == v; 61 | u((v>>8)&0xff); 62 | u( v &0xff); 63 | } 64 | 65 | public void add(byte[] a) { 66 | while (len+a.length >= bs.length) dbl(); 67 | System.arraycopy(a, 0, bs, len, a.length); 68 | len+= a.length; 69 | } 70 | 71 | public byte[] get() { 72 | return Arrays.copyOf(bs, len); 73 | } 74 | } -------------------------------------------------------------------------------- /src/BQN/tools/MutIntArr.java: -------------------------------------------------------------------------------- 1 | package BQN.tools; 2 | 3 | import BQN.types.arrs.IntArr; 4 | 5 | import java.util.Arrays; 6 | 7 | public class MutIntArr { 8 | public int[] is; 9 | public int sz; 10 | public int pos; // arbitrary variable for personal usage 11 | public MutIntArr(int initial) { 12 | is = new int[initial]; 13 | } 14 | 15 | public void add(int i) { 16 | if (sz>=is.length) is = Arrays.copyOf(is, is.length*2); 17 | is[sz] = i; 18 | sz++; 19 | } 20 | public IntArr getA() { 21 | return new IntArr(Arrays.copyOf(is, sz)); 22 | } 23 | public int[] get() { 24 | return Arrays.copyOf(is, sz); 25 | } 26 | } -------------------------------------------------------------------------------- /src/BQN/types/BQNObj.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.*; 4 | import BQN.errors.*; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.arrs.ChrArr; 7 | import BQN.types.mut.Settable; 8 | 9 | public abstract class BQNObj extends Primitive { 10 | 11 | public MapPointer getMut(Value k) { 12 | return new MapPointer(this, k); 13 | } 14 | public MapPointer getMut(String k) { 15 | return getMut(new ChrArr(k)); 16 | } 17 | 18 | public abstract Value get(Value k); // returns null if doesn't have 19 | public Value get(String k) { 20 | return get(new ChrArr(k)); 21 | } 22 | public Value getChk(String k) { 23 | Value v = get(k); 24 | if (v == null) throw new ValueError("Reading non-defined key "+k); 25 | return v; 26 | } 27 | 28 | abstract public void set(Value k, Value v); 29 | abstract public Value[][] kvPair(); 30 | abstract public int size(); 31 | 32 | public static class MapPointer extends Settable { 33 | private final BQNObj map; 34 | private final Value k; 35 | 36 | MapPointer(BQNObj map, Value k) { 37 | this.map = map; 38 | this.k = k; 39 | } 40 | 41 | public Value get(Scope sc) { 42 | return map.get(k); 43 | } 44 | 45 | public void set(Value x, boolean update, Scope sc, Callable blame) { 46 | boolean prev = map.get(k) != null; 47 | if (prev && !update) throw new SyntaxError("←: Cannot redefine map key '"+k+"'", blame); 48 | if (!prev && update) throw new SyntaxError("↩: Cannot update non-existing key '"+k+"'", blame); 49 | map.set(k, x); 50 | } 51 | 52 | public boolean seth(Value x, Scope sc) { 53 | throw new SyntaxError("map key cannot be a part of a header"); 54 | } 55 | 56 | public String toString() { 57 | Value v = get(null); 58 | if (Main.debug) return v == null? "map@"+k : "ptr@"+k+":"+v; 59 | return v == null? "map@"+k : v.ln(FmtInfo.def); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/BQN/types/BigValue.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.arrs.ChrArr; 6 | 7 | import java.math.BigInteger; 8 | 9 | 10 | public class BigValue extends Primitive { 11 | public static final BigValue ZERO = new BigValue(BigInteger.ZERO); 12 | public static final BigValue ONE = new BigValue(BigInteger.ONE); 13 | public static final BigValue MINUS_ONE = new BigValue(BigInteger.valueOf(-1)); 14 | public static final BigValue TWO = new BigValue(BigInteger.valueOf(2)); 15 | 16 | public static final BigInteger MAX_SAFE_DOUBLE = BigInteger.valueOf(Num.MAX_SAFE_DOUBLE); 17 | 18 | public static final BigInteger MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE); 19 | public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE); 20 | 21 | public final BigInteger i; 22 | public BigValue(BigInteger i) { 23 | this.i = i; 24 | } 25 | public BigValue(double d) { 26 | i = bigint(d); 27 | } 28 | public BigValue(int n) { 29 | i = BigInteger.valueOf(n); 30 | } 31 | public BigValue(long n) { 32 | i = BigInteger.valueOf(n); 33 | } 34 | 35 | 36 | public static BigInteger bigint(Value x) { 37 | if (x instanceof Num) return bigint(((Num) x).num); 38 | if (x instanceof BigValue) return ((BigValue) x).i; 39 | throw new DomainError("Using "+x.humanType(true)+" as biginteger"); 40 | } 41 | public static BigInteger bigint(double d) { 42 | if (Math.abs(d) > Num.MAX_SAFE_DOUBLE) throw new DomainError("creating biginteger from possibly rounded value"); 43 | if (d%1 != 0) throw new DomainError("creating biginteger from non-integer"); 44 | return BigInteger.valueOf((long) d); 45 | } 46 | public static int safeInt(BigInteger b) { 47 | if (b.signum()==-1) { 48 | if (b.compareTo(MIN_INT)<=0) return Integer.MIN_VALUE; 49 | } else { 50 | if (b.compareTo(MAX_INT)>=0) return Integer.MAX_VALUE; 51 | } 52 | return b.intValue(); 53 | } 54 | 55 | 56 | public Num num() { 57 | return new Num(i.doubleValue()); 58 | } 59 | 60 | 61 | 62 | 63 | 64 | public int asInt() { 65 | int n = i.intValue(); 66 | if (!BigInteger.valueOf(n).equals(i)) throw new DomainError("Using biginteger as integer"); 67 | return n; 68 | } 69 | public double asDouble() { 70 | if (i.abs().compareTo(MAX_SAFE_DOUBLE) > 0) throw new DomainError("Using biginteger as double"); 71 | return i.doubleValue(); 72 | } 73 | 74 | public Value fItemS() { return ZERO; } 75 | public long longValue() { 76 | if (i.bitLength() > 64) throw new DomainError("Using a biginteger with more than 64 bits as long"); 77 | return i.longValue(); 78 | } 79 | 80 | 81 | public boolean eq(Value o) { 82 | return o instanceof BigValue && i.equals(((BigValue) o).i); 83 | } 84 | public int hashCode() { 85 | return i.hashCode(); 86 | } 87 | 88 | public Value pretty(FmtInfo f) { return new ChrArr(ln(f)); } 89 | public String ln(FmtInfo f) { 90 | if (i.signum()==-1) return "¯" + i.negate() + "L"; 91 | return i.toString()+"L"; 92 | } 93 | } -------------------------------------------------------------------------------- /src/BQN/types/Callable.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tokenizer.Token; 5 | 6 | public abstract class Callable extends Primitive implements Tokenable { 7 | public Token token; 8 | 9 | public Value callInv ( Value x) { throw new DomainError("Cannot invert "+humanType(true), this);} 10 | public Value callInvX(Value w, Value x) { throw new DomainError("Cannot invert "+humanType(true), this);} 11 | public Value callInvW(Value w, Value x) { throw new DomainError("Cannot invert "+humanType(true), this);} 12 | 13 | 14 | public Token getToken() { 15 | return token; 16 | } 17 | } -------------------------------------------------------------------------------- /src/BQN/types/Char.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.arrs.ChrArr; 5 | 6 | 7 | public class Char extends Primitive { 8 | public char chr; 9 | public static final Char[] ASCII; 10 | static { 11 | ASCII = new Char[128]; 12 | for (int i = 0; i < 128; i++) { 13 | ASCII[i] = new Char((char) i); 14 | } 15 | } 16 | 17 | public static final Char SPACE = ASCII[' ']; 18 | 19 | public Char(char c) { 20 | chr = c; 21 | } 22 | public static Char of(char c) { 23 | if (c < 128) return ASCII[c]; 24 | return new Char(c); 25 | } 26 | 27 | public char asChar() { return chr; } 28 | 29 | 30 | 31 | public Char upper() { return Char.of(Character.toUpperCase(chr)); } 32 | public Char lower() { return Char.of(Character.toLowerCase(chr)); } 33 | public int getCase() { 34 | return Character.isUpperCase(chr)? 1 : Character.isLowerCase(chr)? -1 : 0; 35 | } 36 | 37 | public Value ofShape(int[] sh) { assert Arr.prod(sh) == 1; 38 | return new ChrArr(String.valueOf(chr), sh); 39 | } 40 | public Value fItemS() { return SPACE; } 41 | public String asString() { return String.valueOf(chr); } 42 | public int atomInfo() { return Pervasion.ATM_CHR; } 43 | 44 | public boolean eq(Value c) { 45 | return c instanceof Char && chr == ((Char) c).chr; 46 | } 47 | public int compareTo(Char v) { 48 | return Character.compare(chr, v.chr); 49 | } 50 | public int hashCode() { 51 | return chr; 52 | } 53 | 54 | public String ln(FmtInfo f) { 55 | if (spec()) { 56 | switch (chr) { 57 | case 0: return "@"; 58 | case 9: return "\\t"; 59 | case 10: return "\\n"; 60 | case 13: return "\\r"; 61 | default: 62 | String s = Integer.toHexString(chr); 63 | if (s.length()==1) s = "0"+s; 64 | return "\\x"+s; 65 | } 66 | } 67 | return "'"+chr+"'"; 68 | } 69 | public Value pretty(FmtInfo f) { 70 | return new ChrArr(ln(f)); 71 | } 72 | public boolean spec() { 73 | return chr<32 || chr==127; 74 | } 75 | } -------------------------------------------------------------------------------- /src/BQN/types/Md1.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.*; 5 | import BQN.types.callable.Md1Derv; 6 | 7 | public abstract class Md1 extends Callable { 8 | 9 | protected Md1() { } 10 | 11 | public Value call( Value x) { throw new SyntaxError("Cannot interpret a 1-modifier as a function", this); } 12 | public Value call(Value w, Value x) { throw new SyntaxError("Cannot interpret a 1-modifier as a function", this); } 13 | 14 | public Value call(Value f, Value x, Md1Derv derv) { throw new IncorrectArgsError(ln(FmtInfo.def)+" can't be called monadically", derv); } 15 | public Value call(Value f, Value w, Value x, Md1Derv derv) { throw new IncorrectArgsError(ln(FmtInfo.def)+" can't be called dyadically", derv); } 16 | 17 | public Value callInv (Value f, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support monadic inverting", this); } 18 | public Value callInvX(Value f, Value w, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support dyadic inverting of 𝕩", this); } 19 | public Value callInvW(Value f, Value w, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support dyadic inverting of 𝕨", this); } 20 | public Value under(Value f, Value o, Value x, Md1Derv derv) { 21 | Value v = o instanceof Fun? o.call(call(f, x, derv)) : o; 22 | return callInv(f, v); 23 | } 24 | public Value underW(Value f, Value o, Value w, Value x, Md1Derv derv) { 25 | Value v = o instanceof Fun? o.call(call(f, w, x, derv)) : o; 26 | return callInvX(f, w, v); 27 | } 28 | public Value underA(Value f, Value o, Value w, Value x, Md1Derv derv) { 29 | Value v = o instanceof Fun? o.call(call(f, w, x, derv)) : o; 30 | return callInvW(f, v, x); 31 | } 32 | 33 | public Value derive(Value f) { 34 | return new Md1Derv(f, this); 35 | } 36 | 37 | // functions in general are equal on a per-object basis 38 | public int hashCode() { 39 | return actualHashCode(); 40 | } 41 | public boolean eq(Value o) { 42 | return this == o; 43 | } 44 | 45 | public Value pretty(FmtInfo f) { return Format.str(ln(f)); } 46 | public abstract String ln(FmtInfo f); 47 | } -------------------------------------------------------------------------------- /src/BQN/types/Md2.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.*; 5 | import BQN.types.callable.*; 6 | 7 | public abstract class Md2 extends Callable { 8 | 9 | protected Md2() { } 10 | 11 | public Value call( Value x) { throw new SyntaxError("Cannot interpret a 2-modifier as a function", this); } 12 | public Value call(Value w, Value x) { throw new SyntaxError("Cannot interpret a 2-modifier as a function", this); } 13 | 14 | public Value call(Value f, Value g, Value x, Md2Derv derv) { throw new IncorrectArgsError(ln(FmtInfo.def)+" can't be called monadically", derv); } 15 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { throw new IncorrectArgsError(ln(FmtInfo.def)+" can't be called dyadically", derv); } 16 | 17 | public Value callInv (Value f, Value g, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support monadic inverting", this); } 18 | public Value callInvX(Value f, Value g, Value w, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support dyadic inverting of 𝕩", this); } 19 | public Value callInvW(Value f, Value g, Value w, Value x) { throw new DomainError(ln(FmtInfo.def)+" doesn't support dyadic inverting of 𝕨", this); } 20 | public Value under(Value f, Value g, Value o, Value x, Md2Derv derv) { 21 | Value v = o instanceof Fun? o.call(call(f, g, x, derv)) : o; 22 | return callInv(f, g, v); 23 | } 24 | public Value underW(Value f, Value g, Value o, Value w, Value x, Md2Derv derv) { 25 | Value v = o instanceof Fun? o.call(call(f, g, w, x, derv)) : o; 26 | return callInvX(f, g, w, v); 27 | } 28 | public Value underA(Value f, Value g, Value o, Value w, Value x, Md2Derv derv) { 29 | Value v = o instanceof Fun? o.call(call(f, g, w, x, derv)) : o; 30 | return callInvW(f, g, v, x); 31 | } 32 | 33 | public Value derive(Value f, Value g) { 34 | return new Md2Derv(f, g, this); 35 | } 36 | public Md1 derive(Value g) { 37 | return new Md2HalfDerv(g, this); 38 | } 39 | 40 | // functions in general are equal on a per-object basis 41 | public int hashCode() { 42 | return actualHashCode(); 43 | } 44 | public boolean eq(Value o) { 45 | return this == o; 46 | } 47 | 48 | public Value pretty(FmtInfo f) { return Format.str(ln(f)); } 49 | public abstract String ln(FmtInfo f); 50 | } -------------------------------------------------------------------------------- /src/BQN/types/Nothing.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.errors.SyntaxError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.arrs.ChrArr; 6 | 7 | public class Nothing extends Primitive { 8 | public static final Nothing inst = new Nothing(); 9 | 10 | 11 | SyntaxError used() { 12 | return new SyntaxError("didn't expect ·"); 13 | } 14 | 15 | 16 | 17 | public String asString() { throw used(); } 18 | public Value fItemS() { throw used(); } 19 | public Value ofShape(int[] sh) { throw used(); } 20 | 21 | 22 | public Value pretty(FmtInfo f) { return new ChrArr("·"); } 23 | public String ln(FmtInfo f) { return "·"; } 24 | 25 | 26 | public int hashCode() { return 0; } 27 | public boolean eq(Value o) { 28 | return o instanceof Nothing; 29 | } 30 | } -------------------------------------------------------------------------------- /src/BQN/types/Obj.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | public abstract class Obj { // union of Settable and Value 4 | final protected int actualHashCode() { 5 | return super.hashCode(); 6 | } 7 | } -------------------------------------------------------------------------------- /src/BQN/types/Primitive.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.tools.Pervasion; 4 | import BQN.types.arrs.SingleItemArr; 5 | 6 | public abstract class Primitive extends Value { 7 | private static final int[] SHAPE = new int[0]; 8 | 9 | public Primitive() { 10 | super(SHAPE, 1); 11 | } 12 | 13 | public Value call( Value x) { return this; } 14 | public Value call(Value w, Value x) { return this; } 15 | 16 | public final Value get(int i) { return this; } 17 | public Value ofShape(int[] sh) { assert Arr.prod(sh) == 1; 18 | return new SingleItemArr(this, sh); 19 | } 20 | 21 | 22 | public Value fItemS() { 23 | return null; 24 | } 25 | public Value fMineS() { 26 | return fItemS(); 27 | } 28 | 29 | public int arrInfo() { 30 | return Pervasion.ARR_ATM; 31 | } 32 | } -------------------------------------------------------------------------------- /src/BQN/types/Tokenable.java: -------------------------------------------------------------------------------- 1 | package BQN.types; 2 | 3 | import BQN.tokenizer.Token; 4 | 5 | public interface Tokenable { 6 | Token getToken(); 7 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/ChrArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.Pervasion; 5 | import BQN.types.*; 6 | 7 | import java.util.Arrays; 8 | 9 | public class ChrArr extends Arr { 10 | public String s; 11 | 12 | public ChrArr(String s) { 13 | super(vecsh(s.length()), s.length()); 14 | this.s = s; 15 | } 16 | public ChrArr(String s, int[] sh) { 17 | super(sh, s.length()); 18 | this.s = s; 19 | } 20 | 21 | public ChrArr(char[] arr, int[] sh) { 22 | this(new String(arr), sh); 23 | } 24 | public ChrArr(char[] arr) { 25 | this(new String(arr)); 26 | } 27 | 28 | 29 | public Value get(int i) { 30 | return Char.of(s.charAt(i)); 31 | } 32 | 33 | public String asString() { 34 | if (r() > 1) throw new DomainError("Using rank "+r()+" character array as string"); 35 | return s; 36 | } 37 | 38 | public Value fItem() { return Char.SPACE; } 39 | public Value fItemS() { return Char.SPACE; } 40 | public int arrInfo() { return Pervasion.ARR_C16; } 41 | 42 | public boolean quickDepth1() { return true; } 43 | public Value ofShape(int[] sh) { 44 | return new ChrArr(s, sh); 45 | } 46 | 47 | public int hashCode() { 48 | if (hash == 0) { 49 | for (char c : s.toCharArray()) hash = hash*31 + c; 50 | hash = shapeHash(hash); 51 | } 52 | return hash; 53 | } 54 | public boolean eq(Value x) { 55 | if (x instanceof ChrArr) { 56 | if (!Arrays.equals(shape, x.shape)) return false; 57 | int xh = ((Arr) x).hash; 58 | if (hash!=0 && xh!=0 && hash!=xh) return false; 59 | return s.equals(((ChrArr) x).s); 60 | } 61 | return super.eq(x); 62 | } 63 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/DoubleArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.Pervasion; 5 | import BQN.types.*; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class DoubleArr extends Arr { 10 | public static final double[] EMPTY = new double[0]; 11 | final public double[] arr; 12 | 13 | public DoubleArr(double[] arr, int[] sh) { 14 | super(sh, arr.length); 15 | this.arr = arr; 16 | } 17 | public DoubleArr(double[] arr) { // 1D 18 | super(vecsh(arr.length), arr.length); 19 | this.arr = arr; 20 | } 21 | 22 | public DoubleArr(ArrayList arrl) { 23 | super(vecsh(arrl.size()), arrl.size()); 24 | arr = new double[ia]; 25 | int j = 0; 26 | for (double d : arrl) arr[j++] = d; 27 | } 28 | 29 | 30 | public Value get(int i) { return Num.of(arr[i]); } 31 | 32 | 33 | 34 | public Value[] valuesClone() { 35 | Value[] vs = new Value[ia]; 36 | for (int i = 0; i < ia; i++) vs[i] = new Num(arr[i]); 37 | return vs; 38 | } 39 | 40 | 41 | public int[] asIntArrClone() { 42 | int[] r = new int[ia]; 43 | for (int i = 0; i < ia; i++) { 44 | int conv = (int) arr[i]; 45 | if (arr[i] != conv) throw new DomainError("Using a fractional number as integer"); 46 | r[i] = conv; 47 | } 48 | return r; 49 | } 50 | 51 | 52 | public double[] asDoubleArr() { 53 | return arr; 54 | } 55 | public double[] asDoubleArrClone() { 56 | return arr.clone(); 57 | } 58 | public double sum() { 59 | double r = 0; 60 | for (double val : arr) r+= val; 61 | return r; 62 | } 63 | 64 | 65 | 66 | public boolean quickDoubleArr() { return true; } 67 | public boolean quickDepth1() { return true; } 68 | public Value ofShape(int[] sh) { return new DoubleArr(arr, sh); } 69 | public Value fItem() { return Num.ZERO; } 70 | public Value fItemS() { return Num.ZERO; } 71 | public int arrInfo() { return Pervasion.ARR_F64; } 72 | 73 | public int hashCode() { 74 | if (hash == 0) { 75 | for (double d : arr) { 76 | hash*= 31; 77 | if (d != 0d) hash+= Double.hashCode(d); // ¯0 == 0 78 | } 79 | hash = shapeHash(hash); 80 | } 81 | return hash; 82 | } 83 | 84 | public Arr reverseOn(int dim) { 85 | if (r() == 0) { 86 | if (dim != 0) throw new DomainError("rotating a scalar with a non-0 axis"); 87 | return this; 88 | } 89 | if (dim < 0) dim+= r(); 90 | // 2×3×4: 91 | // 0 - 3×4s for 2 92 | // 1 - 4s for 3 93 | // 2 - 1s for 4 94 | int chunkS = 1; 95 | int cPSec = shape[dim]; // chunks per section 96 | for (int i = r()-1; i > dim; i--) { 97 | chunkS*= shape[i]; 98 | } 99 | int sec = chunkS * cPSec; // section length 100 | double[] res = new double[ia]; 101 | int c = 0; 102 | while (c < ia) { 103 | for (int i = 0; i < cPSec; i++) { 104 | for (int j = 0; j < chunkS; j++) { 105 | res[c + (cPSec-i-1)*chunkS + j] = arr[c + i*chunkS + j]; 106 | } 107 | } 108 | c+= sec; 109 | } 110 | return new DoubleArr(res, shape); 111 | } 112 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/EmptyArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.Pervasion; 5 | import BQN.types.*; 6 | 7 | import java.util.Iterator; 8 | 9 | public class EmptyArr extends Arr { 10 | public static final int[] SHAPE0 = new int[]{0}; 11 | public static final EmptyArr SHAPE0Q = new EmptyArr(SHAPE0, null); 12 | public static final EmptyArr SHAPE0N = new EmptyArr(SHAPE0, Num.ZERO); 13 | public static final EmptyArr SHAPE0S = new EmptyArr(SHAPE0, Char.SPACE); 14 | public static final EmptyArr SHAPE0SV = new EmptyArr(SHAPE0, SHAPE0S); 15 | public static final int[] NOINTS = new int[0]; 16 | public static final Value[] NOVALUES = new Value[0]; 17 | public static final String[] NOSTRS = new String[0]; 18 | 19 | private final Value proto; 20 | public EmptyArr(int[] sh, Value proto) { 21 | super(sh, 0); 22 | this.proto = proto; 23 | } 24 | 25 | public Value get(int i) { 26 | throw new ImplementationError("internal: using get() on empty array; view )jstack"); 27 | } 28 | 29 | 30 | public String asString() { 31 | if (r() > 1) throw new DomainError("Using rank "+r()+" array as char vector"); 32 | return ""; 33 | } 34 | 35 | public int[] asIntArrClone() { return NOINTS; } // safe, copy or not - doesn't matter 36 | public int[] asIntArr () { return NOINTS; } 37 | 38 | public double[] asDoubleArr () { return DoubleArr.EMPTY; } 39 | public double[] asDoubleArrClone() { return DoubleArr.EMPTY; } 40 | public double sum() { return 0; } 41 | 42 | public static final long[] NOLONGS = new long[0]; 43 | public long[] asBitLongs() { return NOLONGS; } 44 | 45 | public Value[] valuesClone() { return NOVALUES; } 46 | public Value[] values () { return NOVALUES; } 47 | 48 | 49 | 50 | public boolean quickIntArr() { return true; } 51 | public boolean quickDoubleArr() { return true; } 52 | public Value ofShape(int[] sh) { 53 | assert ia == Arr.prod(sh); 54 | return new EmptyArr(sh, proto); 55 | } 56 | public int arrInfo() { 57 | return proto==Char.SPACE? Pervasion.ARR_C16 : Pervasion.ARR_BIT; 58 | } 59 | 60 | public Value fItem() { 61 | if (proto == null) throw new DomainError("couldn't get prototype"); 62 | return proto; 63 | } 64 | public Value fItemS() { 65 | return proto; 66 | } 67 | public Value fMineS() { 68 | return this; 69 | } 70 | 71 | private static final Iterator EIT = new Iterator() { 72 | public boolean hasNext() { return false; } 73 | public Value next() { throw new IllegalStateException("iterating empty array"); } 74 | }; 75 | public Iterator iterator() { 76 | return EIT; 77 | } 78 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/HArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.types.*; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class HArr extends Arr { 9 | private final Value[] arr; 10 | public HArr(Value[] v, int[] sh) { 11 | super(sh, v.length); 12 | arr = v; 13 | } 14 | public HArr(ArrayList v) { // 1D 15 | super(vecsh(v.size())); 16 | arr = v.toArray(new Value[0]); 17 | } 18 | public HArr(Value[] v) { // 1D 19 | super(vecsh(v.length), v.length); 20 | arr = v; 21 | } 22 | 23 | public HArr(ArrayList v, int[] sh) { 24 | super(sh); 25 | arr = v.toArray(new Value[0]); 26 | } 27 | 28 | 29 | 30 | 31 | public Value get(int i) { return arr[i]; } 32 | 33 | 34 | 35 | public Value[] values () { return arr ; } 36 | public Value[] valuesClone() { return arr.clone(); } 37 | 38 | 39 | public Value fItemS() { 40 | if (ia == 0) return null; 41 | return arr[0].fMineS(); 42 | } 43 | public Value ofShape(int[] sh) { 44 | assert ia == Arr.prod(sh); 45 | return new HArr(arr, sh); 46 | } 47 | 48 | 49 | 50 | public String asString() { 51 | if (r() > 1) throw new DomainError("Using rank "+r()+" character array as string"); 52 | StringBuilder r = new StringBuilder(ia); 53 | for (Value v : arr) { 54 | if (!(v instanceof Char)) throw new DomainError("Using array containing "+v.humanType(true)+" as string"); 55 | r.append(((Char) v).chr); 56 | } 57 | return r.toString(); 58 | } 59 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/IntArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.Pervasion; 5 | import BQN.types.*; 6 | 7 | public class IntArr extends Arr { 8 | public final int[] arr; 9 | public IntArr(int[] arr, int[] shape) { 10 | super(shape, arr.length); 11 | this.arr = arr; 12 | } 13 | public IntArr(int[] arr) { 14 | super(vecsh(arr.length), arr.length); 15 | this.arr = arr; 16 | } 17 | public IntArr(byte[] arr) { 18 | super(vecsh(arr.length), arr.length); 19 | int[] a = new int[ia]; 20 | for (int i = 0; i < ia; i++) a[i] = arr[i]&0xff; 21 | this.arr = a; 22 | } 23 | 24 | public static Arr maybe(double[] ds, int[] sh) { // TODO not use 25 | ia: { 26 | for (double c : ds) if (c != (int)c) break ia; 27 | int[] is = new int[ds.length]; 28 | for (int i = 0; i < ds.length; i++) is[i] = (int) ds[i]; 29 | return new IntArr(is, sh); 30 | } 31 | return new DoubleArr(ds, sh); 32 | } 33 | 34 | public Value get(int i) { return Num.of(arr[i]); } 35 | 36 | public Value[] valuesClone() { 37 | Value[] res = new Value[ia]; 38 | for (int i = 0; i < arr.length; i++) res[i] = Num.of(arr[i]); 39 | return res; 40 | } 41 | 42 | 43 | public int[] asIntArr () { return arr ; } 44 | public int[] asIntArrClone() { return arr.clone(); } 45 | 46 | 47 | public double[] asDoubleArr() { 48 | return asDoubleArrClone(); 49 | } 50 | public double[] asDoubleArrClone() { 51 | double[] r = new double[arr.length]; 52 | for (int i = 0; i < r.length; i++) r[i] = arr[i]; 53 | return r; 54 | } 55 | public double sum() { 56 | long sum = 0; 57 | for (int c : arr) sum+= c; 58 | return sum; 59 | } 60 | 61 | 62 | public boolean quickDoubleArr() { return true; } 63 | public boolean quickIntArr() { return true; } 64 | public boolean quickDepth1() { return true; } 65 | public Value ofShape(int[] sh) { return new IntArr(arr, sh); } 66 | public Value fItem() { return Num.ZERO; } 67 | public Value fItemS() { return Num.ZERO; } 68 | public int arrInfo() { return Pervasion.ARR_I32; } 69 | 70 | public int hashCode() { 71 | if (hash == 0) { 72 | for (int d : arr) hash = hash*31 + Double.hashCode(d); 73 | hash = shapeHash(hash); 74 | } 75 | return hash; 76 | } 77 | 78 | public Arr reverseOn(int dim) { 79 | if (r() == 0) { 80 | if (dim != 0) throw new DomainError("rotating a scalar with a non-0 axis"); 81 | return this; 82 | } 83 | if (dim < 0) dim+= r(); 84 | int chunkS = 1; 85 | int cPSec = shape[dim]; // chunks per section 86 | for (int i = r()-1; i > dim; i--) { 87 | chunkS*= shape[i]; 88 | } 89 | int sec = chunkS * cPSec; // section length 90 | int[] res = new int[ia]; 91 | int c = 0; 92 | while (c < ia) { 93 | for (int i = 0; i < cPSec; i++) { 94 | for (int j = 0; j < chunkS; j++) { 95 | res[c + (cPSec-i-1)*chunkS + j] = arr[c + i*chunkS + j]; 96 | } 97 | } 98 | c+= sec; 99 | } 100 | return new IntArr(res, shape); 101 | } 102 | } -------------------------------------------------------------------------------- /src/BQN/types/arrs/SingleItemArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.arrs; 2 | 3 | import BQN.Main; 4 | import BQN.errors.DomainError; 5 | import BQN.tools.Pervasion; 6 | import BQN.types.*; 7 | 8 | import java.util.*; 9 | 10 | public class SingleItemArr extends Arr { 11 | private final Value item; 12 | 13 | public SingleItemArr(Value item, int[] shape) { 14 | super(shape); 15 | this.item = item; 16 | } 17 | public SingleItemArr(Value item, int[] shape, int ia) { 18 | super(shape, ia); 19 | this.item = item; 20 | } 21 | 22 | public static Value r0(Value v) { 23 | return new SingleItemArr(v, EmptyArr.NOINTS); 24 | } 25 | public static final int[] SH1 = new int[]{1}; 26 | public static Value sh1(Value v) { 27 | return new SingleItemArr(v, SH1); 28 | } 29 | 30 | public Value get(int i) { return item; } 31 | 32 | 33 | 34 | public String asString() { 35 | if (r() > 1) throw new DomainError("Using rank "+r()+" array as string"); 36 | if (!(item instanceof Char)) throw new DomainError("Using non-char array as string"); 37 | char c = ((Char) item).chr; 38 | return Main.repeat(String.valueOf(c), ia); 39 | } 40 | 41 | public Value fItemS() { 42 | return item.fMineS(); 43 | } 44 | 45 | public Value ofShape(int[] sh) { 46 | assert ia == Arr.prod(sh); 47 | return new SingleItemArr(item, sh); 48 | } 49 | public Arr reverseOn(int dim) { return this; } 50 | 51 | public boolean quickDoubleArr() { return item instanceof Num; } 52 | public boolean quickIntArr() { return item instanceof Num && Num.isInt(((Num) item).num); } 53 | public boolean quickDepth1() { return item instanceof Primitive; } 54 | public Value[] valuesClone() { 55 | Value[] vs = new Value[ia]; 56 | for (int i = 0; i < ia; i++) vs[i] = item; 57 | return vs; 58 | } 59 | 60 | public int arrInfo() { 61 | switch (item.atomInfo()) { 62 | case Pervasion.ATM_BIT: return Pervasion.ARR_BIT; 63 | case Pervasion.ATM_I32: return Pervasion.ARR_I32; 64 | case Pervasion.ATM_F64: return Pervasion.ARR_F64; 65 | case Pervasion.ATM_CHR: return Pervasion.ARR_C16; 66 | default : return Pervasion.ARR_ANY; 67 | } 68 | } 69 | 70 | public double sum() { 71 | return item.asDouble() * ia; 72 | } 73 | 74 | 75 | public int[] asIntArrClone() { 76 | int vi = item.asInt(); 77 | int[] a = new int[ia]; 78 | for (int i = 0; i < ia; i++) a[i] = vi; 79 | return a; 80 | } 81 | public double[] asDoubleArrClone() { 82 | double[] res = new double[ia]; 83 | double n = item.asDouble(); 84 | for (int i = 0; i < ia; i++) res[i] = n; 85 | return res; 86 | } 87 | public long[] asBitLongs() { 88 | double i = item.asDouble(); 89 | if (i!=0 && i!=1) throw new DomainError("Using array containing "+i+" as boolean array"); 90 | long[] r = new long[BitArr.sizeof(ia)]; 91 | if (i!=0) Arrays.fill(r, -1L); 92 | return r; 93 | } 94 | 95 | public Iterator iterator() { 96 | return new Iterator() { int c = 0; 97 | public boolean hasNext() { 98 | return c < ia; 99 | } 100 | public Value next() { c++; return item; } 101 | }; 102 | } 103 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/Md1Derv.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public class Md1Derv extends Fun { 7 | public final Value f; 8 | public final Md1 op; 9 | public Md1Derv(Value f, Md1 op) { 10 | this.f = f; 11 | this.op = op; 12 | token = op.token; 13 | } 14 | 15 | public Value call(Value x) { 16 | return op.call(f, x, this); 17 | } 18 | public Value call(Value w, Value x) { 19 | return op.call(f, w, x, this); 20 | } 21 | public Value callInv(Value x) { 22 | return op.callInv(f, x); 23 | } 24 | public Value callInvX(Value w, Value x) { 25 | return op.callInvX(f, w, x); 26 | } 27 | public Value callInvW(Value w, Value x) { 28 | return op.callInvW(f, w, x); 29 | } 30 | 31 | public Value under(Value o, Value x) { 32 | return op.under(f, o, x, this); 33 | } 34 | public Value underW(Value o, Value w, Value x) { 35 | return op.underW(f, o, w, x, this); 36 | } 37 | public Value underA(Value o, Value w, Value x) { 38 | return op.underA(f, o, w, x, this); 39 | } 40 | 41 | 42 | public String ln(FmtInfo fi) { 43 | return f.ln(fi)+op.ln(fi); 44 | } 45 | public boolean eq(Value o) { 46 | if (!(o instanceof Md1Derv)) return false; 47 | Md1Derv that = (Md1Derv) o; 48 | return this.op.eq(that.op) && this.f.eq(that.f); 49 | } 50 | public int hashCode() { 51 | return 31*f.hashCode() + op.hashCode(); 52 | } 53 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/Md2Derv.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public class Md2Derv extends Fun { 7 | public final Value f, g; 8 | public final Md2 op; 9 | public Md2Derv(Value f, Value g, Md2 op) { 10 | this.f = f; 11 | this.g = g; 12 | this.op = op; 13 | token = op.token; 14 | } 15 | 16 | public Value call(Value x) { 17 | return op.call(f, g, x, this); 18 | } 19 | public Value call(Value w, Value x) { 20 | return op.call(f, g, w, x, this); 21 | } 22 | public Value callInv(Value x) { 23 | return op.callInv(f, g, x); 24 | } 25 | public Value callInvX(Value w, Value x) { 26 | return op.callInvX(f, g, w, x); 27 | } 28 | public Value callInvW(Value w, Value x) { 29 | return op.callInvW(f, g, w, x); 30 | } 31 | 32 | public Value under(Value o, Value x) { 33 | return op.under(f, g, o, x, this); 34 | } 35 | public Value underW(Value o, Value w, Value x) { 36 | return op.underW(f, g, o, w, x, this); 37 | } 38 | public Value underA(Value o, Value w, Value x) { 39 | return op.underA(f, g, o, w, x, this); 40 | } 41 | 42 | public String ln(FmtInfo fi) { 43 | String wws = g.ln(fi); 44 | if (!(g instanceof Arr) && wws.length() != 1) wws = "("+wws+")"; 45 | return f.ln(fi)+op.ln(fi)+wws; 46 | } 47 | public boolean eq(Value o) { 48 | if (!(o instanceof Md2Derv)) return false; 49 | Md2Derv that = (Md2Derv) o; 50 | return this.op.eq(that.op) && this.f.eq(that.f) && this.g.eq(that.g); 51 | } 52 | public int hashCode() { 53 | int res = op.hashCode(); 54 | res = 31*res + f.hashCode(); 55 | res = 31*res + g.hashCode(); 56 | return res; 57 | } 58 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/Md2HalfDerv.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public class Md2HalfDerv extends Md1 { 7 | public final Value g; 8 | public final Md2 op; 9 | 10 | public Md2HalfDerv(Value g, Md2 op) { 11 | this.g = g; 12 | this.op = op; 13 | } 14 | 15 | public Value derive(Value f) { 16 | return op.derive(f, g); 17 | } 18 | 19 | public String ln(FmtInfo f) { 20 | return op.ln(f)+"("+g.ln(f)+")"; 21 | } 22 | 23 | public boolean eq(Value o) { // reminder: Md2Block has its own Md2HalfDerv 24 | if (!(o instanceof Md2HalfDerv)) return false; 25 | Md2HalfDerv that = (Md2HalfDerv) o; 26 | return g.eq(that.g) && op.eq(that.op); 27 | } 28 | public int hashCode() { 29 | return 31*g.hashCode() + op.hashCode(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/blocks/FunBlock.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.blocks; 2 | 3 | import BQN.*; 4 | import BQN.tokenizer.types.BlockTok; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.*; 7 | 8 | 9 | public class FunBlock extends Fun { 10 | public final BlockTok code; 11 | public final Scope sc; 12 | 13 | public FunBlock(BlockTok t, Scope sc) { 14 | this.sc = sc; 15 | code = t; 16 | } 17 | 18 | public Value call(Value x) { // 𝕊𝕩𝕨··· 19 | return code.exec(sc, null, new Value[]{this, x, Nothing.inst}, 0); 20 | } 21 | 22 | public Value call(Value w, Value x) { // 𝕊𝕩𝕨··· 23 | return code.exec(sc, w, new Value[]{this, x, w}, 0); 24 | } 25 | 26 | 27 | public Value callInv(Value x) { // 𝕊𝕩𝕨··· 28 | Main.printdbg("FunBlock⁼ call", x); 29 | return code.exec(sc, null, new Value[]{this, x, Nothing.inst}, 1); 30 | } 31 | 32 | public Value callInvX(Value w, Value x) { // 𝕊𝕩𝕨··· 33 | Main.printdbg("FunBlock⁼ call", w, x); 34 | return code.exec(sc, w, new Value[]{this, x, w}, 1); 35 | } 36 | public Value callInvW(Value w, Value x) { // 𝕊𝕩𝕨··· 37 | Main.printdbg("FunBlock˜⁼ call", w, x); 38 | return code.exec(sc, w, new Value[]{this, w, x}, 2); 39 | } 40 | 41 | public String ln(FmtInfo f) { return code.toRepr(); } 42 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/blocks/Md1Block.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.blocks; 2 | 3 | import BQN.*; 4 | import BQN.tokenizer.types.BlockTok; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.*; 7 | import BQN.types.callable.Md1Derv; 8 | 9 | 10 | public class Md1Block extends Md1 { 11 | public final BlockTok code; 12 | public final Scope sc; 13 | 14 | public Md1Block(BlockTok t, Scope sc) { 15 | this.sc = sc; 16 | code = t; 17 | } 18 | 19 | public Value derive(Value f) { // ···𝕣𝕗· 20 | if (!code.immediate) return super.derive(f); 21 | Main.printdbg("Md1Block immediate call", f); 22 | return code.exec(sc, null, new Value[]{this, f}, 0); 23 | } 24 | 25 | public Value call(Value f, Value x, Md1Derv derv) { // 𝕊𝕩𝕨𝕣𝕗· 26 | Main.printdbg("Md1Block call", x); 27 | return code.exec(sc, null, new Value[]{derv, x, Nothing.inst, this, f}, 0); 28 | } 29 | 30 | public Value call(Value f, Value w, Value x, Md1Derv derv) { // 𝕊𝕩𝕨𝕣𝕗· 31 | Main.printdbg("Md1Block call", w, x); 32 | return code.exec(sc, w, new Value[]{derv, x, w, this, f}, 0); 33 | } 34 | 35 | public String ln(FmtInfo f) { return code.toRepr(); } 36 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/blocks/Md2Block.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.blocks; 2 | 3 | import BQN.*; 4 | import BQN.tokenizer.types.BlockTok; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.*; 7 | import BQN.types.callable.*; 8 | 9 | 10 | public class Md2Block extends Md2 { 11 | public final BlockTok code; 12 | public final Scope sc; 13 | 14 | public Md2Block(BlockTok t, Scope sc) { 15 | this.sc = sc; 16 | code = t; 17 | } 18 | 19 | public Value derive(Value f, Value g) { // ···𝕣𝕗𝕘 20 | if (!code.immediate) return super.derive(f, g); 21 | Main.printdbg("Md2Block immediate call", f, g); 22 | return code.exec(sc, null, new Value[]{this, f, g}, 0); 23 | } 24 | 25 | public Md1 derive(Value g) { 26 | if (!code.immediate) return super.derive(g); 27 | Main.printdbg("Md2Block immediate half-derive", g); 28 | return new Md2HalfDerv(g, this); 29 | } 30 | 31 | public Value call(Value f, Value g, Value x, Md2Derv derv) { // 𝕊𝕩𝕨𝕣𝕗𝕘 32 | Main.printdbg("Md2Block call", x); 33 | return code.exec(sc, null, new Value[]{derv, x, Nothing.inst, this, f, g}, 0); 34 | } 35 | 36 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { // 𝕊𝕩𝕨𝕣𝕗𝕘 37 | Main.printdbg("Md2Block call", w, x); 38 | return code.exec(sc, w, new Value[]{derv, x, w, this, f, g}, 0); 39 | } 40 | 41 | public String ln(FmtInfo f) { return code.toRepr(); } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/FileNS.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.mut.SimpleMap; 8 | 9 | import java.util.*; 10 | import java.nio.file.*; 11 | 12 | public class FileNS extends SimpleMap { 13 | public String ln(FmtInfo f) { return "(file)"; } 14 | 15 | private final Path path; 16 | public FileNS(Path path) { 17 | this.path = path; 18 | } 19 | 20 | private final Value at = new FB("At") { 21 | public Value call(Value x) { 22 | return new ChrArr(path.resolve(x.asString()).toString()); 23 | } 24 | public Value call(Value w, Value x) { 25 | return new ChrArr(Paths.get(w.asString()).resolve(x.asString()).toString()); 26 | } 27 | }; 28 | 29 | 30 | public Value getv(String s) { 31 | switch (s) { 32 | case "at": return at; 33 | } 34 | throw new ValueError("No key "+s+" in •file"); 35 | } 36 | 37 | public void setv(String s, Value v) { 38 | throw new DomainError("Assigning into •file"); 39 | } 40 | 41 | private abstract class FB extends FnBuiltin { 42 | private final String name; 43 | public FB(String name) { this.name = "(file)."+name; } 44 | public String ln(FmtInfo f) { return name; } 45 | public boolean eq(Value o) { return this==o; } 46 | } 47 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/FnBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public abstract class FnBuiltin extends Fun { 7 | public boolean eq(Value o) { 8 | return this.getClass() == o.getClass(); 9 | } 10 | 11 | public int hashCode() { 12 | return ln(FmtInfo.def).hashCode(); // probably could even pass null and it should work 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/Md1Builtin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public abstract class Md1Builtin extends Md1 { 7 | public boolean eq(Value o) { 8 | return this.getClass() == o.getClass(); 9 | } 10 | 11 | public int hashCode() { 12 | return ln(FmtInfo.def).hashCode(); 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/Md2Builtin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public abstract class Md2Builtin extends Md2 { 7 | public boolean eq(Value o) { 8 | return this.getClass() == o.getClass(); 9 | } 10 | 11 | public int hashCode() { 12 | return ln(FmtInfo.def).hashCode(); 13 | } 14 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/RandNS.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.mut.SimpleMap; 8 | 9 | import java.util.*; 10 | 11 | public class RandNS extends SimpleMap { 12 | public String ln(FmtInfo f) { return "(random generator)"; } 13 | 14 | private final Random r; 15 | public RandNS(long seed) { 16 | r = new Random(seed); 17 | } 18 | 19 | private final Value range = new RB("Range") { 20 | public Value call(Value x) { 21 | int xi = x.asInt(); 22 | if (xi==0) return new Num(r.nextDouble()); 23 | return new Num(r.nextInt(xi)); 24 | } 25 | public Value call(Value w, Value x) { 26 | int[] wi = w.asIntArr(); 27 | int xv = x.asInt(); 28 | int ia = 1; 29 | for (int i : wi) ia*= i; 30 | if (xv==0) { 31 | double[] ra = new double[ia]; 32 | for (int i = 0; i < ia; i++) ra[i] = r.nextDouble(); 33 | return new DoubleArr(ra, wi); 34 | } else { 35 | int[] ra = new int[ia]; 36 | for (int i = 0; i < ia; i++) ra[i] = r.nextInt(xv); 37 | return new IntArr(ra, wi); 38 | } 39 | } 40 | }; 41 | 42 | private final Value deal = new RB("Deal") { 43 | public Value call(Value x) { 44 | return call(x,x); 45 | } 46 | public Value call(Value w, Value x) { 47 | int wi = w.asInt(); 48 | int xi = x.asInt(); 49 | 50 | ArrayList vs = new ArrayList<>(w.ia); 51 | for (int i = 0; i < xi; i++) vs.add(i); 52 | Collections.shuffle(vs, r); 53 | int[] res = new int[wi]; 54 | for (int i = 0; i < wi; i++) res[i] = vs.get(i); 55 | return new IntArr(res); 56 | } 57 | }; 58 | 59 | public Value getv(String s) { 60 | switch (s) { 61 | case "range": return range; 62 | case "deal": return deal; 63 | } 64 | throw new ValueError("No key "+s+" in random generator"); 65 | } 66 | 67 | public void setv(String s, Value v) { 68 | throw new DomainError("Assigning into random generator"); 69 | } 70 | 71 | private abstract class RB extends FnBuiltin { 72 | public final String name; 73 | public RB(String name) { 74 | this.name = "(random generator)."+name; 75 | } 76 | public String ln(FmtInfo f) { return name; } 77 | public boolean eq(Value o) { return this==o; } 78 | } 79 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/AndBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.RankError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | import BQN.types.callable.builtins.md1.CellBuiltin; 9 | 10 | import java.util.Arrays; 11 | 12 | public class AndBuiltin extends FnBuiltin { 13 | public String ln(FmtInfo f) { return "∧"; } 14 | public Value identity() { return Num.ONE; } 15 | 16 | public Value call(Value x) { 17 | if (x.r()==0) throw new RankError("∧: argument cannot be scalar", this); 18 | if (x.ia==0) return x; 19 | if (x.quickIntArr() && x.r()==1) { 20 | int[] is = x.asIntArrClone(); 21 | Arrays.sort(is); 22 | return new IntArr(is, x.shape); 23 | } 24 | Value[] cells = x.r()==1? x.valuesClone() : CellBuiltin.cells(x); 25 | Arrays.sort(cells); 26 | return x.r()==1? Arr.create(cells, x.shape) : GTBuiltin.merge(cells, new int[]{x.shape[0]}, this); 27 | } 28 | 29 | public Pervasion.NN2N dyNum() { return MulBuiltin.DF; } 30 | public Value call(Value w, Value x) { 31 | return MulBuiltin.DF.call(w, x); 32 | } 33 | 34 | public Value callInvX(Value w, Value x) { 35 | return DivBuiltin.DF.call(x, w); 36 | } 37 | public Value callInvW(Value w, Value x) { 38 | return callInvX(x, w); 39 | } 40 | 41 | public static Num reduce(BitArr x) { 42 | x.setEnd(true); 43 | for (long l : x.arr) if (l != ~0L) return Num.ZERO; 44 | return Num.ONE; 45 | } 46 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/AssertBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.*; 5 | import BQN.types.callable.builtins.FnBuiltin; 6 | 7 | public class AssertBuiltin extends FnBuiltin { 8 | public String ln(FmtInfo f) { return "!"; } 9 | 10 | public Value call(Value x) { 11 | if (x.eq(Num.ONE)) return x; 12 | if (x.eq(Num.ZERO)) throw new BQN.errors.AssertionError("", this); 13 | String msg; 14 | try { 15 | msg = Format.outputFmt(x); 16 | } catch (Throwable t) { 17 | msg = x.ln(FmtInfo.def); 18 | } 19 | throw new BQN.errors.AssertionError(msg, this); 20 | } 21 | 22 | public Value call(Value w, Value x) { 23 | if (x.eq(Num.ONE)) return x; 24 | String msg; 25 | try { 26 | msg = Format.outputFmt(w); 27 | } catch (Throwable t) { 28 | msg = w.ln(FmtInfo.def); 29 | } 30 | throw new BQN.errors.AssertionError(msg, this); 31 | } 32 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/CeilingBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | public class CeilingBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "⌈"; } 11 | public Value identity() { return Num.NEGINF; } 12 | 13 | public Value call(Value x) { 14 | if (x instanceof Arr) { 15 | if (x.quickDoubleArr()) { 16 | if (x.quickIntArr()) return x; 17 | double[] xd = x.asDoubleArr(); 18 | ia: { 19 | int[] res = new int[x.ia]; 20 | for (int i = 0; i < res.length; i++) { 21 | double c = xd[i]; 22 | if (c>Integer.MIN_VALUE && c<=Integer.MAX_VALUE) { 23 | int iv = (int) c; 24 | res[i] = iv + (c>0 && c!=iv? 1 : 0); 25 | } else break ia; 26 | } 27 | return new IntArr(res, x.shape); 28 | } 29 | double[] res = new double[x.ia]; 30 | for (int i = 0; i < res.length; i++) res[i] = Math.ceil(xd[i]); 31 | return new DoubleArr(res, x.shape); 32 | } 33 | if (x instanceof ChrArr) { 34 | return new ChrArr(((ChrArr) x).s.toUpperCase(), x.shape); 35 | } 36 | Value[] vs = new Value[x.ia]; 37 | for (int i = 0; i < vs.length; i++) vs[i] = call(x.get(i)); 38 | return new HArr(vs, x.shape); 39 | } else if (x instanceof Num) return new Num(Math.ceil(((Num) x).num)); 40 | else if (x instanceof Char) return ((Char) x).upper(); 41 | else throw new DomainError("⌈: argument contained "+x.humanType(true), this); 42 | } 43 | 44 | public Pervasion.NN2N dyNum() { return DF; } 45 | public static final Pervasion.NN2NpB DF = new Pervasion.NN2NpB() { 46 | public Value on(BigValue w, BigValue x) { return w.i.compareTo(x.i)>0? w : x; } 47 | public double on(double w, double x) { return Math.max(w, x); } 48 | public void on(double w, double[] x, double[] res) { for (int i = 0; i < x.length; i++) res[i] = Math.max(w , x[i]); } 49 | public void on(double[] w, double x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.max(w[i], x ); } 50 | public void on(double[] w, double[] x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.max(w[i], x[i]); } 51 | 52 | public int[] on(int w, int[] x) {int[]res=new int[x.length]; for(int i=0;i 0) System.arraycopy(x.shape, gsh.length, sh, gsh.length, rem); 41 | int diff = rank - x.r(); 42 | int[] off = new int[sh.length]; 43 | for (int i = 0; i < gsh.length; i++) { 44 | int am = gsh[i]; 45 | int s = i < diff? 1 : x.shape[i - diff]; 46 | sh[i] = s - Math.abs(am); 47 | if (sh[i] < 0) sh[i] = 0; 48 | else if (am > 0) off[i] = am; 49 | } 50 | return UpArrowBuiltin.on(sh, off, x); 51 | } 52 | 53 | public Value underW(Value o, Value w, Value x) { 54 | Value v = o instanceof Fun? o.call(call(w, x)) : o; 55 | int[] ls = w.asIntVec(); 56 | int[] sh = x.shape; 57 | for (int i = 0; i < ls.length; i++) { 58 | ls[i] = ls[i]>0? ls[i]-sh[i] : ls[i]+sh[i]; 59 | } 60 | return UpArrowBuiltin.undo(ls, v, x, this); 61 | } 62 | 63 | public Value callInv(Value x) { 64 | if (x.ia==0) throw new DomainError("↓⁼: Argument had 0 items", this); 65 | Value r = x.first(); 66 | if (!call(r).eq(x)) throw new DomainError("↓⁼: Argument isn't a suffix array", this); 67 | return r; 68 | } 69 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/EQBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.*; 5 | import BQN.types.arrs.BitArr; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | 9 | public class EQBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "="; } 11 | public Value identity() { return Num.ONE; } 12 | 13 | public Value call(Value x) { 14 | return Num.of(x.r()); 15 | } 16 | 17 | public static final Pervasion.VV2B DF = new Pervasion.VV2B() { 18 | public Value on(Primitive w, Primitive x) { return w.eq(x)? Num.ONE : Num.ZERO; } 19 | public void on(double w, double[] x, BitArr.BA res) { for (double cx : x) { res.add( w==cx); } } 20 | public void on(double[] w, double x, BitArr.BA res) { for (double cw : w) { res.add(cw== x); } } 21 | public void on(double[] w, double[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]==x[i]); } } 22 | 23 | public void on(int w, int[] x, BitArr.BA res) { for (int cx : x) { res.add( w==cx); } } 24 | public void on(int[] w, int x, BitArr.BA res) { for (int cw : w) { res.add(cw== x); } } 25 | public void on(int[] w, int[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]==x[i]); } } 26 | 27 | public void on(char w, char[] x, BitArr.BA res) { for (char cx : x) { res.add( w==cx); } } 28 | public void on(char[] w, char x, BitArr.BA res) { for (char cw : w) { res.add(cw== x); } } 29 | public void on(char[] w, char[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]==x[i]); } } 30 | 31 | public Value on(boolean w, BitArr x) { if(w)return x; return NotBuiltin.on(x); } 32 | public Value on(BitArr w, boolean x) { if(x)return w; return NotBuiltin.on(w); } 33 | public void on(long[] w, long[] x, long[] res) { for (int i = 0; i < res.length; i++) res[i] = ~w[i]^x[i]; } 34 | }; 35 | 36 | public Value call(Value w, Value x) { 37 | return DF.call(w, x); 38 | } 39 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/EpsBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.RankError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.BitArr; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | import BQN.types.callable.builtins.md1.CellBuiltin; 9 | 10 | import java.util.HashSet; 11 | 12 | public class EpsBuiltin extends FnBuiltin { 13 | public String ln(FmtInfo f) { return "∊"; } 14 | 15 | public Value call(Value x) { 16 | if (x.r() == 0) throw new RankError("∊: argument cannot be scalar", this); 17 | Value[] vs; 18 | BitArr.BA res; 19 | if (x.r() == 1) { 20 | res = new BitArr.BA(x.shape,true); 21 | if (x.quickIntArr()) { 22 | HashSet seen = new HashSet<>(); 23 | for (int c : x.asIntArr()) res.add(seen.add(c)); 24 | return res.finish(); 25 | } 26 | vs = x.values(); 27 | } else { 28 | res = new BitArr.BA(Arr.vecsh(x.shape[0]),true); 29 | vs = CellBuiltin.cells(x); 30 | } 31 | HashSet seen = new HashSet<>(); 32 | for (Value c : vs) res.add(seen.add(c)); 33 | return res.finish(); 34 | } 35 | 36 | public Value call(Value w, Value x) { 37 | if (w.scalar()) { // TODO this _might_ be wrong 38 | Value w0 = w.first(); 39 | for (Value v : x) { 40 | if (v.eq(w0)) return Num.ONE; 41 | } 42 | return Num.ZERO; 43 | } 44 | BitArr.BA res = new BitArr.BA(w.shape,true); 45 | if (w.ia>20 && x.ia>20) { // TODO these (and in ⊐) shouldn't be random numbers 46 | HashSet vs = new HashSet<>(); 47 | for (Value c : x) vs.add(c); 48 | for (Value c : w) res.add(vs.contains(c)); 49 | } else { 50 | if (x.quickIntArr() && w.quickIntArr()) { 51 | int[] xi = x.asIntArr(); 52 | int[] wi = w.asIntArr(); 53 | for (int i = 0; i < w.ia; i++) { 54 | int cw = wi[i]; 55 | boolean b = false; 56 | for (int v : xi) { 57 | if (v == cw) { 58 | b = true; 59 | break; 60 | } 61 | } 62 | res.add(b); 63 | } 64 | } else { 65 | Value[] xv = x.values(); 66 | for (int i = 0; i < w.ia; i++) { 67 | Value cw = w.get(i); 68 | boolean b = false; 69 | for (Value v : xv) { 70 | if (v.eq(cw)) { 71 | b = true; 72 | break; 73 | } 74 | } 75 | res.add(b); 76 | } 77 | } 78 | } 79 | return res.finish(); 80 | } 81 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/EvalBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | public class EvalBuiltin extends FnBuiltin { 9 | public String ln(FmtInfo f) { return "•Eval"; } 10 | 11 | public final Scope sc; 12 | public EvalBuiltin(Scope sc) { 13 | this.sc = sc; 14 | } 15 | 16 | public Value call(Value x) { 17 | return Main.exec(x.asString(), sc, null); 18 | } 19 | 20 | public Value call(Value w, Value x) { 21 | return Main.exec(x.asString(), sc, w.values()); 22 | } 23 | 24 | public static class NewEval extends FnBuiltin { 25 | public String ln(FmtInfo f) { return "•BQN"; } 26 | public final Sys sys; 27 | public NewEval(Sys sys) { 28 | this.sys = sys; 29 | } 30 | 31 | public Value call(Value x) { 32 | return Main.exec(x.asString(), new Scope(sys), null); 33 | } 34 | public Value call(Value w, Value x) { 35 | return Main.exec(x.asString(), new Scope(sys), w.values()); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/FindBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | import BQN.types.callable.builtins.md1.CellBuiltin; 9 | 10 | import java.util.*; 11 | 12 | public class FindBuiltin extends FnBuiltin { 13 | public String ln(FmtInfo f) { return "⍷"; } 14 | 15 | public Value call(Value x) { 16 | if (x.r()==0) throw new DomainError("⍷: argument cannot be a scalar", this); 17 | if (x.ia==0) { 18 | int[] nsh = x.shape.clone(); 19 | nsh[0] = Math.min(nsh[0], 1); 20 | return new EmptyArr(nsh, Num.ZERO); 21 | } 22 | if (x.r() > 1) { 23 | Value[] rcs = call(new HArr(CellBuiltin.cells(x))).values(); 24 | return GTBuiltin.merge(rcs, new int[]{rcs.length}, this); 25 | } 26 | if (x.quickIntArr()) { 27 | HashSet vals = new HashSet<>(); 28 | MutIntArr res = new MutIntArr(10); 29 | for (int c : x.asIntArr()) if (vals.add(c)) res.add(c); 30 | return res.getA(); 31 | } 32 | HashSet vals = new HashSet<>(); 33 | ArrayList res = new ArrayList<>(); 34 | for (Value c : x) if (vals.add(c)) res.add(c); 35 | return Arr.create(res); 36 | } 37 | 38 | public Value call(Value w, Value x) { 39 | if (w.r() != x.r()) throw new RankError("⍷: argument ranks should be equal ("+w.r()+" ≠ "+x.r()+")", this); 40 | BitArr.BC res = new BitArr.BC(x.shape); 41 | if (w.r() == 1) { 42 | if (w instanceof BitArr && x instanceof BitArr) { 43 | long[] al = ((BitArr) w).arr; 44 | long[] wl = ((BitArr) x).arr; 45 | w: for (int ir = 0; ir < x.ia-w.ia+1; ir++) { 46 | for (int ia = 0; ia < w.ia; ia++) { 47 | int iw = ia + ir; 48 | long la = al[ia>>6] >> (ia & 63); 49 | long lw = wl[iw>>6] >> (iw & 63); 50 | if ((la&1) != (lw&1)) continue w; 51 | } 52 | res.set(ir); 53 | } 54 | } else if (w.quickDoubleArr() && x.quickDoubleArr()) { 55 | double[] wd = w.asDoubleArr(); 56 | double[] xd = x.asDoubleArr(); 57 | w: for (int ir = 0; ir < x.ia-w.ia+1; ir++) { 58 | for (int ia = 0; ia < w.ia; ia++) { 59 | if (wd[ia] != xd[ia+ir]) continue w; 60 | } 61 | res.set(ir); 62 | } 63 | } else { 64 | w: for (int ir = 0; ir < x.ia-w.ia+1; ir++) { 65 | for (int ia = 0; ia < w.ia; ia++) { 66 | if (!w.get(ia).eq(x.get(ia+ir))) continue w; 67 | } 68 | res.set(ir); 69 | } 70 | } 71 | } else { 72 | Indexer ind = new Indexer(Indexer.add(Indexer.sub(x.shape, w.shape), 1)); 73 | w: for (int[] inW : ind) { 74 | for (int[] inA : new Indexer(w.shape)) { 75 | Value vA = w.simpleAt(inA); 76 | Value vW = x.simpleAt(Indexer.add(inA, inW)); 77 | if (!vA.eq(vW)) continue w; 78 | } 79 | res.set(Indexer.fromShape(x.shape, inW)); 80 | } 81 | } 82 | return res.finish(); 83 | } 84 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/FloorBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | public class FloorBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "⌊"; } 11 | public Value identity() { return Num.POSINF; } 12 | 13 | public Value call(Value x) { 14 | if (x instanceof Arr) { 15 | if (x.quickDoubleArr()) { 16 | if (x.quickIntArr()) return x; 17 | double[] xd = x.asDoubleArr(); 18 | ia: { 19 | int[] res = new int[x.ia]; 20 | for (int i = 0; i < res.length; i++) { 21 | double c = xd[i]; 22 | if (c>=Integer.MIN_VALUE && c0? x : w; } 51 | public double on(double w, double x) { return Math.min(w, x); } 52 | public void on(double w, double[] x, double[] res) { for (int i = 0; i < x.length; i++) res[i] = Math.min(w , x[i]); } 53 | public void on(double[] w, double x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.min(w[i], x ); } 54 | public void on(double[] w, double[] x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.min(w[i], x[i]); } 55 | 56 | public int[] on(int w, int[] x) {int[]res=new int[x.length]; for(int i=0;i"; } 14 | public Value identity() { return Num.ZERO; } 15 | 16 | public Value call(Value x) { 17 | if (x instanceof Arr && x.ia>0 && !x.quickDepth1()) { 18 | return merge(x.values(), x.shape, this); 19 | } 20 | return x; 21 | } 22 | 23 | public static Value merge(Value[] x, int[] sh, Callable blame) { 24 | assert x.length != 0; 25 | // if (x.length == 0) return new EmptyArr(sh, null); 26 | 27 | Value x0 = x[0]; 28 | int[] sh0 = x0.shape; 29 | int[] resShape = new int[sh0.length + sh.length]; 30 | System.arraycopy(sh, 0, resShape, 0, sh.length); 31 | System.arraycopy(sh0, 0, resShape, sh.length, sh0.length); 32 | 33 | MutVal res = new MutVal(resShape); 34 | 35 | int i = 0; 36 | for (Value c : x) { 37 | if (!Arrays.equals(c.shape, sh0)) { 38 | if (c.r() != sh0.length) throw new RankError(blame+": expected equal ranks of items (shapes "+Main.fArr(x0.shape)+" vs "+Main.fArr(c.shape)+")", blame); 39 | throw new DomainError(blame+": mismatched shapes ("+Main.fArr(sh0)+" vs "+Main.fArr(c.shape)+")", blame); // cannot be more specific due to the wide array of uses for merging 40 | } 41 | res.copy(c, 0, i, c.ia); 42 | i+= x0.ia; 43 | } 44 | return res.get(); 45 | } 46 | 47 | 48 | public Value call(Value w, Value x) { 49 | return LTBuiltin.DF.call(x, w); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/GradeDownBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.Main; 4 | import BQN.errors.DomainError; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.Value; 7 | import BQN.types.arrs.*; 8 | import BQN.types.callable.builtins.FnBuiltin; 9 | import BQN.types.callable.builtins.md1.CellBuiltin; 10 | import BQN.types.callable.builtins.md2.NCellBuiltin; 11 | 12 | import java.util.Arrays; 13 | 14 | public class GradeDownBuiltin extends FnBuiltin { 15 | public String ln(FmtInfo f) { return "⍒"; } 16 | 17 | public Value call(Value x) { 18 | return new IntArr(gradeDown(x)); 19 | } 20 | 21 | 22 | public static int[] gradeDown(Value x) { 23 | if (x.r()==1 && x.ia>0) { 24 | if (x instanceof BitArr) { 25 | long[] xl = ((BitArr) x).arr; 26 | int[] res = new int[x.ia]; int rp = 0; 27 | for (int i = 0; i < res.length; i++) if ((xl[i>>6]>>(i&63)&1)!=0) res[rp++] = i; 28 | for (int i = 0; i < res.length; i++) if ((xl[i>>6]>>(i&63)&1)==0) res[rp++] = i; 29 | return res; 30 | } 31 | if (x.quickIntArr()) { 32 | int[] xi = x.asIntArrClone(); 33 | int[] ri = UDBuiltin.on(xi.length); 34 | if (tmp.length < ri.length) tmp = new int[ri.length]; 35 | System.arraycopy(ri, 0, tmp, 0, ri.length); 36 | rec(xi, tmp, ri, 0, ri.length); 37 | return ri; 38 | } 39 | } 40 | 41 | if (x.r() == 0) throw new DomainError("cannot grade rank 0"); 42 | if (x.r() != 1) return gradeDown(new HArr(CellBuiltin.cells(x))); 43 | 44 | Integer[] na = new Integer[x.ia]; 45 | for (int i = 0; i < na.length; i++) na[i] = i; 46 | Arrays.sort(na, (a, b) -> x.get(b).compareTo(x.get(a))); 47 | 48 | int[] res = new int[na.length]; 49 | for (int i = 0; i < na.length; i++) res[i] = na[i]; 50 | return res; 51 | } 52 | private static int[] tmp = new int[100]; 53 | private static void rec(int[] b, int[] I, int[] O, int s, int e) { 54 | if (e-s<=1) return; 55 | int m = (s+e)/2; 56 | rec(b, O, I, s, m); 57 | rec(b, O, I, m, e); 58 | 59 | int i1 = s; 60 | int i2 = m; 61 | for (int i = s; i < e; i++) { 62 | if (i1=e || b[I[i1]]>=b[I[i2]])) { 63 | O[i] = I[i1]; i1++; 64 | } else { 65 | O[i] = I[i2]; i2++; 66 | } 67 | } 68 | } 69 | 70 | 71 | 72 | public Value call(Value w, Value x) { 73 | if (w.r() > x.r()+1) throw new DomainError("⍒: =𝕨 cannot be greater than =𝕩 ("+Main.fArr(w.shape)+"≡≢𝕨; "+Main.fArr(x.shape)+"≡≢𝕩)", this); 74 | if (w.r() == 0) throw new DomainError("⍒: 𝕨 cannot be a scalar", this); 75 | if (w.r() > 1) { 76 | int xr = x.r()-w.r()+1; 77 | x = new HArr(NCellBuiltin.cells(x, xr), Arrays.copyOf(x.shape, xr)); 78 | w = new HArr(CellBuiltin.cells(w)); 79 | } 80 | for (int i = 0; i < w.ia-1; i++) { 81 | if (w.get(i).compareTo(w.get(i+1)) < 0) throw new DomainError("⍒: 𝕨 must be sorted in descending order", this); 82 | } 83 | Value[] wv = w.values(); 84 | int[] res = new int[x.ia]; 85 | for (int i = 0; i < res.length; i++) { 86 | Value c = x.get(i); 87 | int s = -1, e = wv.length; 88 | while (e-s > 1) { 89 | int m = (s+e) / 2; 90 | if (c.compareTo(wv[m]) > 0) e = m; 91 | else s = m; 92 | } 93 | res[i] = s+1; 94 | } 95 | return new IntArr(res, x.shape); 96 | } 97 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/LEBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.*; 5 | import BQN.types.arrs.BitArr; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | 9 | public class LEBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "≤"; } 11 | 12 | public static final Pervasion.VV2B DF = new Pervasion.VV2B() { 13 | public Value on(Primitive w, Primitive x) { return w.compareTo(x) <= 0? Num.ONE : Num.ZERO; } 14 | public void on(double w, double[] x, BitArr.BA res) { for (double cx : x) { res.add( w <= cx); } } 15 | public void on(double[] w, double x, BitArr.BA res) { for (double cw : w) { res.add(cw <= x); } } 16 | public void on(double[] w, double[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] <= x[i]); } } 17 | 18 | public void on(int w, int[] x, BitArr.BA res) { for (int cx : x) { res.add( w <= cx); } } 19 | public void on(int[] w, int x, BitArr.BA res) { for (int cw : w) { res.add(cw <= x); } } 20 | public void on(int[] w, int[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] <= x[i]); } } 21 | 22 | public void on(char w, char[] x, BitArr.BA res) { for (char cx : x) { res.add( w <= cx); } } 23 | public void on(char[] w, char x, BitArr.BA res) { for (char cw : w) { res.add(cw <= x); } } 24 | public void on(char[] w, char[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] <= x[i]); } } 25 | 26 | public Value on(boolean w, BitArr x) { if(w) return x; return BitArr.s1(x); } 27 | public Value on(BitArr w, boolean x) { if(x) return BitArr.s1(w); return BitArr.not(w); } 28 | public void on(long[] w, long[] x, long[] res) { for (int i = 0; i < res.length; i++) res[i] = (~w[i]) | x[i]; } 29 | }; 30 | 31 | public Value call(Value w, Value x) { 32 | return DF.call(w, x); 33 | } 34 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/LTBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | 10 | public class LTBuiltin extends FnBuiltin { 11 | public String ln(FmtInfo f) { return "<"; } 12 | 13 | public Value call(Value x) { 14 | return SingleItemArr.r0(x); 15 | } 16 | 17 | 18 | public static final Pervasion.VV2B DF = new Pervasion.VV2B() { 19 | public Value on(Primitive w, Primitive x) { return w.compareTo(x) < 0? Num.ONE : Num.ZERO; } 20 | public void on(double w, double[] x, BitArr.BA res) { for (double cx : x) { res.add( w < cx); } } 21 | public void on(double[] w, double x, BitArr.BA res) { for (double cw : w) { res.add(cw < x); } } 22 | public void on(double[] w, double[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] < x[i]); } } 23 | 24 | public void on(int w, int[] x, BitArr.BA res) { for (int cx : x) { res.add( w < cx); } } 25 | public void on(int[] w, int x, BitArr.BA res) { for (int cw : w) { res.add(cw < x); } } 26 | public void on(int[] w, int[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] < x[i]); } } 27 | 28 | public void on(char w, char[] x, BitArr.BA res) { for (char cx : x) { res.add( w < cx); } } 29 | public void on(char[] w, char x, BitArr.BA res) { for (char cw : w) { res.add(cw < x); } } 30 | public void on(char[] w, char[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i] < x[i]); } } 31 | 32 | public Value on(boolean w, BitArr x) { if(w) return BitArr.s0(x); return x; } 33 | public Value on(BitArr w, boolean x) { if(x) return BitArr.not(w); return BitArr.s0(w); } 34 | public void on(long[] w, long[] x, long[] res) { for (int i = 0; i < res.length; i++) res[i] = (~w[i]) & x[i]; } 35 | }; 36 | 37 | public Value call(Value w, Value x) { 38 | return DF.call(w, x); 39 | } 40 | 41 | public Value callInv(Value x) { 42 | if (x.r()!=0 || x instanceof Primitive) throw new DomainError("<⁼: called on "+(x.r()!=0? "array with rank "+x.r() : "atom"), this); 43 | return x.first(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/LTackBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | public class LTackBuiltin extends FnBuiltin { 9 | public String ln(FmtInfo f) { return "⊣"; } 10 | 11 | public Value call(Value x) { return x; } 12 | public Value call(Value w, Value x) { return w; } 13 | 14 | public Value callInv(Value x) { 15 | return x; 16 | } 17 | public Value callInvX(Value w, Value x) { 18 | if (w.eq(x)) return w; 19 | throw new DomainError("⊣⁼: expected 𝕨 and 𝕩 to be equal", this); 20 | } 21 | public Value callInvW(Value w, Value x) { 22 | return w; 23 | } 24 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/LaminateBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | import BQN.types.callable.builtins.md1.CellBuiltin; 8 | 9 | import java.util.Arrays; 10 | 11 | public class LaminateBuiltin extends FnBuiltin { 12 | public String ln(FmtInfo f) { return "≍"; } 13 | 14 | private static final int[] MSH = new int[]{2}; 15 | public Value call(Value w, Value x) { 16 | return GTBuiltin.merge(new Value[]{w, x}, MSH, this); 17 | } 18 | 19 | public Value call(Value x) { 20 | int[] nsh = new int[x.r()+1]; 21 | nsh[0] = 1; 22 | System.arraycopy(x.shape, 0, nsh, 1, x.r()); 23 | return x.ofShape(nsh); 24 | } 25 | 26 | public Value callInv(Value x) { 27 | if (x.r()==0 || x.shape[0]!=1) throw new DomainError("≍⁼: Argument shape should start with 1", this); 28 | return x.ofShape(Arrays.copyOfRange(x.shape, 1, x.shape.length)); 29 | } 30 | 31 | public Value callInvX(Value w, Value x) { 32 | if (x.r()==0) throw new DomainError("≍⁼: 𝕩 cannot be a scalar", this); 33 | Value[] c = CellBuiltin.cells(x); 34 | if (c.length!=2) throw new DomainError("≍⁼: Expected 𝕩 to have 2 cells", this); 35 | if (!c[0].eq(w)) throw new DomainError("≍⁼: 𝕨 didn't match expected", this); 36 | return c[1]; 37 | } 38 | 39 | public Value callInvW(Value w, Value x) { 40 | if (w.r()==0) throw new DomainError("≍˜⁼: 𝕨 cannot be a scalar", this); 41 | Value[] c = CellBuiltin.cells(w); 42 | if (c.length!=2) throw new DomainError("≍˜⁼: Expected 𝕨 to have 2 cells", this); 43 | if (!c[1].eq(x)) throw new DomainError("≍˜⁼: 𝕩 didn't match expected", this); 44 | return c[0]; 45 | } 46 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/LogBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | public class LogBuiltin extends FnBuiltin { // here only to serve as DNF/NF for *⁼ & √˜⁼˜ 9 | public String ln(FmtInfo f) { return "*⁼"; } 10 | 11 | static final double LN2 = Math.log(2); 12 | 13 | public static final NumMV NF = new NumMV() { 14 | public Value call(Num x) { 15 | return new Num(Math.log(x.num)); 16 | } 17 | public void call(double[] res, double[] x) { 18 | for (int i = 0; i < x.length; i++) res[i] = Math.log(x[i]); 19 | } 20 | public Num call(BigValue x) { 21 | if (x.i.signum() <= 0) { 22 | if (x.i.signum() == -1) throw new DomainError("logarithm of negative number"); 23 | return Num.NEGINF; 24 | } 25 | int len = x.i.bitLength(); 26 | if (len<1023) return new Num(Math.log(x.i.doubleValue())); // safe quick path 27 | int shift = len-64; // 64 msb should be enough to get most out of log; safe quick path takes care of bitLength<64 28 | double d = x.i.shiftRight(shift).doubleValue(); 29 | return new Num(Math.log(d) + LN2*shift); 30 | } 31 | }; 32 | public Value call(Value x) { 33 | return numM(NF, x); 34 | } 35 | public Value callInv(Value x) { 36 | return numM(StarBuiltin.NF, x); 37 | } 38 | 39 | public static final Pervasion.NN2N DF = new Pervasion.NN2N() { 40 | public double on(double w, double x) { return Math.log(x) / Math.log(w); } 41 | public void on(double w, double[] x, double[] res) { 42 | double la = Math.log(w); 43 | for (int i = 0; i < x.length; i++) res[i] = Math.log(x[i]) / la; 44 | } 45 | public void on(double[] w, double x, double[] res) { 46 | double lw = Math.log(x); 47 | for (int i = 0; i < w.length; i++) res[i] = lw / Math.log(w[i]); 48 | } 49 | public void on(double[] w, double[] x, double[] res) { 50 | for (int i = 0; i < w.length; i++) res[i] = Math.log(x[i]) / Math.log(w[i]); 51 | } 52 | public Value on(Primitive w, Primitive x) { 53 | if (w instanceof Num && x instanceof BigValue) { 54 | double wd = ((Num) w).num; 55 | double res = ((Num) NF.call(((BigValue) x))).num/Math.log(wd); 56 | if (wd == 2) { // quick path to make sure 2⍟ makes sense 57 | int expected = ((BigValue) x).i.bitLength()-1; 58 | // System.out.println(res+" > "+expected); 59 | if (res < expected) return Num.of(expected); 60 | if (res >= expected+1) { // have to get the double juuuust below expected 61 | long repr = Double.doubleToRawLongBits(expected+1); 62 | repr--; // should be safe as positive int values are always well into the proper double domain 63 | return new Num(Double.longBitsToDouble(repr)); 64 | } 65 | } 66 | return new Num(res); 67 | } else return super.on(w, x); 68 | } 69 | }; 70 | public Value call(Value w, Value x) { 71 | return DF.call(w, x); 72 | } 73 | 74 | @Override public Value callInvX(Value w, Value x) { 75 | return StarBuiltin.DF.call(w, x); 76 | } 77 | @Override public Value callInvW(Value w, Value x) { 78 | return RootBuiltin.DF.call(w, x); 79 | } 80 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/MatchBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | import BQN.types.callable.builtins.FnBuiltin; 6 | 7 | public class MatchBuiltin extends FnBuiltin { 8 | public String ln(FmtInfo f) { return "≡"; } 9 | 10 | public static int lazy(Value x) { 11 | int depth = 0; 12 | while (!(x instanceof Primitive)) { 13 | depth++; 14 | if (x.ia==0) break; 15 | x = x.first(); 16 | } 17 | return depth; 18 | } 19 | public static int full(Value x) { 20 | if (x instanceof Primitive) return 0; 21 | if (x.quickDepth1()) return 1; 22 | int depth = 0; 23 | for (Value v : x) { 24 | depth = Math.max(depth, full(v)); 25 | } 26 | return depth + 1; 27 | } 28 | 29 | public Value call(Value x) { 30 | return Num.of(full(x)); 31 | } 32 | public Value call(Value w, Value x) { 33 | return w.eq(x)? Num.ONE : Num.ZERO; 34 | } 35 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/NEBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.*; 5 | import BQN.types.arrs.BitArr; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | 9 | public class NEBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "≠"; } 11 | public Value identity() { return Num.ZERO; } 12 | 13 | public Value call(Value x) { 14 | if (x.r()==0) return Num.ONE; 15 | return Num.of(x.shape[0]); 16 | } 17 | 18 | 19 | private static final Pervasion.NN2N DFn = new Pervasion.NN2N() { // purely for dyNum 20 | public double on(double w, double x) { return w==x? 0 : 1; } 21 | public void on(double w, double[] x, double[] res) { for (int i = 0; i < x.length; i++) { res[i] = (w !=x[i])?1:0; } } 22 | public void on(double[] w, double x, double[] res) { for (int i = 0; i < w.length; i++) { res[i] = (w[i]!=x )?1:0; } } 23 | public void on(double[] w, double[] x, double[] res) { for (int i = 0; i < w.length; i++) { res[i] = (w[i]!=x[i])?1:0; } } 24 | }; 25 | public Pervasion.NN2N dyNum() { return DFn; } 26 | 27 | public static final Pervasion.VV2B DF = new Pervasion.VV2B() { 28 | public Value on(Primitive w, Primitive x) { return w.eq(x)? Num.ZERO : Num.ONE; } 29 | public void on(double w, double[] x, BitArr.BA res) { for (double cx : x) { res.add( w!=cx); } } 30 | public void on(double[] w, double x, BitArr.BA res) { for (double cw : w) { res.add(cw!= x); } } 31 | public void on(double[] w, double[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]!=x[i]); } } 32 | 33 | public void on(int w, int[] x, BitArr.BA res) { for (int cx : x) { res.add( w!=cx); } } 34 | public void on(int[] w, int x, BitArr.BA res) { for (int cw : w) { res.add(cw!= x); } } 35 | public void on(int[] w, int[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]!=x[i]); } } 36 | 37 | public void on(char w, char[] x, BitArr.BA res) { for (char cx : x) { res.add( w!=cx); } } 38 | public void on(char[] w, char x, BitArr.BA res) { for (char cw : w) { res.add(cw!= x); } } 39 | public void on(char[] w, char[] x, BitArr.BA res) { for (int i = 0; i < w.length; i++) { res.add(w[i]!=x[i]); } } 40 | 41 | public Value on(boolean w, BitArr x) { if (w) return NotBuiltin.on(x); return x; } 42 | public Value on(BitArr w, boolean x) { if (x) return NotBuiltin.on(w); return w; } 43 | public void on(long[] w, long[] x, long[] res) { for (int i = 0; i < res.length; i++) res[i] = w[i]^x[i]; } 44 | }; 45 | 46 | public Value call(Value w, Value x) { 47 | return DF.call(w, x); 48 | } 49 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/NotBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | public class NotBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "¬"; } 11 | public Value identity() { return Num.ONE; } 12 | 13 | public Value call(Value x) { 14 | return on(x, this); 15 | } 16 | public Value callInv(Value x) { 17 | return on(x, this); 18 | } 19 | 20 | public static Value on(Value x, Callable blame) { 21 | if (x instanceof Arr) { 22 | if (x instanceof BitArr) { 23 | BitArr xb = (BitArr) x; 24 | long[] res = new long[xb.arr.length]; 25 | for (int i = 0; i < res.length; i++) res[i] = ~xb.arr[i]; 26 | return new BitArr(res, x.shape); 27 | } 28 | ia: if (x.quickIntArr()) { 29 | int[] xi = x.asIntArr(); 30 | int[] res = new int[xi.length]; 31 | for (int i = 0; i < xi.length; i++) { 32 | int c = xi[i]; 33 | if (c <= -2147483647) break ia; // bck: {x←•IA 𝕩 ⋄ x ≡○¬ 0+x}¨ bounds 34 | res[i] = 1-c; 35 | } 36 | return new IntArr(res, x.shape); 37 | } 38 | 39 | if (x.quickDoubleArr()) { 40 | double[] ds = x.asDoubleArr(); 41 | double[] res = new double[x.ia]; 42 | for (int i = 0; i < ds.length; i++) { 43 | double v = ds[i]; 44 | res[i] = 1 - v; 45 | } 46 | return new DoubleArr(res, x.shape); 47 | } 48 | 49 | Arr o = (Arr) x; 50 | Value[] arr = new Value[o.ia]; 51 | for (int i = 0; i < o.ia; i++) { 52 | arr[i] = on(o.get(i), blame); 53 | } 54 | return new HArr(arr, o.shape); 55 | } else if (x instanceof Num) return Num.of(1-((Num) x).num); 56 | else throw new DomainError("Expected boolean, got "+x.humanType(false), blame); 57 | } 58 | 59 | public static BitArr on(BitArr x) { 60 | BitArr.BC res = BitArr.create(x.shape); 61 | for (int i = 0; i < res.arr.length; i++) res.arr[i] = ~x.arr[i]; 62 | return res.finish(); 63 | } 64 | 65 | public Value call(Value w, Value x) { 66 | return PlusBuiltin.DF.call(MinusBuiltin.DF.call(w, x), Num.ONE); 67 | } 68 | public Value callInvX(Value w, Value x) { 69 | return call(w, x); 70 | } 71 | public Value callInvW(Value w, Value x) { 72 | return MinusBuiltin.DF.scalarX(PlusBuiltin.DF.call(w,x), 1); 73 | } 74 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/PairBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.Main; 4 | import BQN.errors.DomainError; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.*; 7 | import BQN.types.arrs.*; 8 | import BQN.types.callable.builtins.FnBuiltin; 9 | import BQN.types.callable.builtins.md1.CellBuiltin; 10 | 11 | import java.util.Arrays; 12 | 13 | public class PairBuiltin extends FnBuiltin { 14 | public String ln(FmtInfo f) { return "⋈"; } 15 | 16 | public Value call(Value w, Value x) { 17 | if (w instanceof Num && x instanceof Num) { 18 | double wd = w.asDouble(); 19 | double xd = x.asDouble(); 20 | return wd==(int)wd && xd==(int)xd? new IntArr(new int[]{(int)wd,(int)xd}) : new DoubleArr(new double[]{wd,xd}); 21 | } 22 | if (w instanceof Char && x instanceof Char) return new ChrArr(w.asChar()+""+x.asChar()); 23 | return Arr.create(new Value[]{w, x}); 24 | } 25 | 26 | public Value call(Value x) { 27 | if (x instanceof Num) { 28 | double xd = x.asDouble(); 29 | return xd==(int)xd? new IntArr(new int[]{(int)xd}) : new DoubleArr(new double[]{xd}); 30 | } 31 | if (x instanceof Char) return new ChrArr(Character.toString(x.asChar())); 32 | return Arr.create(new Value[]{x}); 33 | } 34 | 35 | public Value callInv(Value x) { 36 | if (x.r()!=1 || x.shape[0]!=1) throw new DomainError("⋈⁼: Argument should be a length 1 vector, but had shape "+Main.fArr(x.shape), this); 37 | return x.get(0); 38 | } 39 | 40 | public Value callInvX(Value w, Value x) { 41 | if (x.r()!=1 || x.shape[0]!=2) throw new DomainError("⋈⁼: 𝕩 must be a length 2 vector, but had shape "+Main.fArr(x.shape), this); 42 | if (!x.get(0).eq(w)) throw new DomainError("⋈⁼: 𝕨 didn't match expected", this); 43 | return x.get(1); 44 | } 45 | 46 | public Value callInvW(Value w, Value x) { 47 | if (w.r()!=1 || w.shape[0]!=2) throw new DomainError("⋈˜⁼: 𝕨 must be a length 2 vector, but had shape "+Main.fArr(w.shape), this); 48 | if (!w.get(1).eq(x)) throw new DomainError("⋈˜⁼: 𝕩 didn't match expected", this); 49 | return w.get(0); 50 | } 51 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/RBoxBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.IntArr; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | import BQN.types.callable.builtins.md1.CellBuiltin; 9 | 10 | import java.util.HashMap; 11 | 12 | public class RBoxBuiltin extends FnBuiltin { 13 | public String ln(FmtInfo f) { return "⊐"; } 14 | 15 | public Value call(Value x) { 16 | HashMap map = new HashMap<>(); 17 | if (x.r() == 0) throw new DomainError("⊐: argument cannot be a scalar", this); 18 | Value[] xv = x.r()==1? x.values() : CellBuiltin.cells(x); 19 | int[] res = new int[xv.length]; 20 | int am = 0; 21 | for (int i = 0; i < xv.length; i++) { 22 | Value c = xv[i]; 23 | Integer prev = map.get(c); 24 | if (prev == null) { 25 | prev = am++; 26 | map.put(c, prev); 27 | } 28 | res[i] = prev; 29 | } 30 | return new IntArr(res); 31 | } 32 | 33 | public Value call(Value w, Value x) { 34 | return on(w, x, this); 35 | } 36 | 37 | public static Value on(Value w, Value x, Callable blame) { 38 | if (x.r() > 1) throw new RankError("⊐: 𝕩 had rank > 1", blame); 39 | if (w.r() > 1) throw new RankError("⊐: 𝕨 had rank > 1", blame); 40 | if (x.ia > 20 && w.ia > 20) { 41 | if (w.quickIntArr() && x.quickIntArr()) { 42 | HashMap map = new HashMap<>(); 43 | int ctr = 0; 44 | for (int v : w.asIntArr()) map.putIfAbsent(v, ctr++); 45 | int[] res = new int[x.ia]; 46 | int[] xi = x.asIntArr(); 47 | for (int i = 0; i < xi.length; i++) { 48 | Integer f = map.get(xi[i]); 49 | res[i] = f==null? w.ia : f; 50 | } 51 | return new IntArr(res, x.shape); 52 | } 53 | HashMap map = new HashMap<>(); 54 | int ctr = 0; 55 | for (Value v : w) map.putIfAbsent(v, ctr++); 56 | int[] res = new int[x.ia]; 57 | ctr = 0; 58 | for (Value v : x) { 59 | Integer f = map.get(v); 60 | res[ctr++] = f==null? w.ia : f; 61 | } 62 | return new IntArr(res, x.shape); 63 | } 64 | int[] res = new int[x.ia]; 65 | int i = 0; 66 | if (w.quickIntArr() && x.quickIntArr()) { 67 | int[] wi = w.asIntArr(); 68 | for (int cx : x.asIntArr()) { 69 | int j = 0; 70 | for (int cw : wi) { 71 | if (cw == cx) break; 72 | j++; 73 | } 74 | res[i++] = j; 75 | } 76 | } else { 77 | Value[] wv = w.values(); 78 | for (Value cx : x) { 79 | int j = 0; 80 | for (Value cw : wv) { 81 | if (cw.eq(cx)) break; 82 | j++; 83 | } 84 | res[i++] = j; 85 | } 86 | } 87 | return new IntArr(res, x.shape); 88 | } 89 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/RBoxUBBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.*; 5 | import BQN.types.Value; 6 | import BQN.types.arrs.IntArr; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | import java.util.HashMap; 10 | 11 | public class RBoxUBBuiltin extends FnBuiltin { 12 | public String ln(FmtInfo f) { return "⊒"; } 13 | 14 | public Value call(Value x) { 15 | if (x.r()==0) throw new DomainError("⊒: rank=0", this); 16 | if (x.r()!=1) throw new NYIError("⊒ on rank≠1", this); 17 | HashMap vs = new HashMap<>(); 18 | int[] res = new int[x.ia]; 19 | int i = 0; 20 | for (Value v : x) { 21 | Integer c = vs.get(v); 22 | if (c==null) { 23 | vs.put(v, 1); 24 | } else { 25 | res[i] = c; 26 | vs.put(v, c+1); 27 | } 28 | i++; 29 | } 30 | return new IntArr(res); 31 | } 32 | 33 | public Value call(Value w, Value x) { 34 | if (x.r()!=1 || w.r()!=1) throw new NYIError("⊒ on rank≠1", this); 35 | HashMap vs = new HashMap<>(); 36 | int i = 0; 37 | for (Value v : w) { 38 | MutIntArr c = vs.get(v); 39 | if (c==null) { 40 | c = new MutIntArr(2); 41 | vs.put(v, c); 42 | } 43 | c.add(i); 44 | i++; 45 | } 46 | int[] res = new int[x.ia]; 47 | i=0; 48 | for (Value v : x) { 49 | MutIntArr c = vs.get(v); 50 | if (c==null || c.pos >= c.sz) res[i] = w.ia; 51 | else res[i] = c.is[c.pos++]; 52 | i++; 53 | } 54 | return new IntArr(res); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/RTackBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | public class RTackBuiltin extends FnBuiltin { 9 | public String ln(FmtInfo f) { return "⊢"; } 10 | 11 | public Value call(Value x) { return x; } 12 | public Value call(Value w, Value x) { return x; } 13 | 14 | public Value callInv(Value x) { 15 | return x; 16 | } 17 | public Value callInvX(Value w, Value x) { 18 | return x; 19 | } 20 | public Value callInvW(Value w, Value x) { 21 | throw new DomainError("⊣˜⁼ is impossible", this); 22 | } 23 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/ReverseBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.Main; 4 | import BQN.errors.*; 5 | import BQN.tools.*; 6 | import BQN.types.*; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | import java.util.Arrays; 10 | 11 | public class ReverseBuiltin extends FnBuiltin { 12 | public String ln(FmtInfo f) { return "⌽"; } 13 | 14 | public Value call(Value x) { 15 | return on(x); 16 | } 17 | public static Value on(Value x) { 18 | if (x instanceof Primitive) return x; 19 | return ((Arr) x).reverseOn(0); 20 | } 21 | public Value callInv(Value x) { 22 | return call(x); 23 | } 24 | 25 | 26 | public Value call(Value w, Value x) { 27 | if (x.r()==0) { 28 | if (w.ia==0) return x; 29 | throw new RankError("⌽: atom 𝕩 is only allowed when ⟨⟩≡𝕨", this); 30 | } 31 | if (w instanceof Primitive) return on(w.asInt(), x); 32 | int[] wi = w.asIntVec(); 33 | if (wi.length > x.r()) throw new DomainError("⌽: length of 𝕨 was greater than rank of 𝕩 ("+(Main.fArr(x.shape))+" ≡ ≢𝕩, "+Main.fArr(wi)+" ≡ 𝕨)", this); 34 | wi = Arrays.copyOf(wi, x.r()); // pads with 0s; also creates a mutable copy for moduloing 35 | if (x.scalar()) return x; // so recursion doesn't have to worry about it 36 | 37 | for (int i = 0; i < wi.length; i++) { 38 | int l = x.shape[i]; 39 | if (l==0) return x; 40 | int c = wi[i]; 41 | c%= l; if (c<0) c+= l; 42 | wi[i] = c; 43 | } 44 | 45 | MutVal res = new MutVal(x.shape, x); 46 | rec(wi, res, x, 0, 0, 0); 47 | return res.get(); 48 | } 49 | 50 | private void rec(int[] w, MutVal res, Value x, int d, int is, int rs) { 51 | int ax = x.shape[d]; 52 | int mv = w[d]; 53 | is*= ax; 54 | rs*= ax; 55 | if (d == x.r()-1) { 56 | res.copy(x, is , rs+ax-mv, mv); 57 | res.copy(x, is+mv, rs , ax-mv); 58 | } else { 59 | for (int i = 0; i < mv; i++) rec(w, res, x, d+1, is+i, rs+i+ax-mv); 60 | for (int i = mv; i < ax; i++) rec(w, res, x, d+1, is+i, rs+i -mv); 61 | } 62 | } 63 | 64 | @Override public Value callInvX(Value w, Value x) { 65 | return call(numM(MinusBuiltin.NF, w), x); 66 | } 67 | 68 | 69 | 70 | public static Value on(int a, Value x) { 71 | if (x.ia==0) return x; 72 | a = Math.floorMod(a, x.shape[0]); 73 | if (a == 0) return x; 74 | int csz = Arr.prod(x.shape, 1, x.r()); 75 | int pA = csz*a; // first part 76 | int pB = x.ia - pA; // second part 77 | 78 | MutVal res = new MutVal(x.shape, x); 79 | res.copy(x, pA, 0, pB); 80 | res.copy(x, 0, pB, pA); 81 | return res.get(); 82 | } 83 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/RootBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.tools.*; 4 | import BQN.types.*; 5 | import BQN.types.callable.builtins.FnBuiltin; 6 | 7 | public class RootBuiltin extends FnBuiltin { 8 | public String ln(FmtInfo f) { return "√"; } 9 | 10 | public static final NumMV NF = new NumMV() { 11 | public Value call(Num x) { 12 | return new Num(Math.sqrt(x.num)); 13 | } 14 | public void call(double[] res, double[] x) { 15 | for (int i = 0; i < x.length; i++) res[i] = Math.sqrt(x[i]); 16 | } 17 | }; 18 | public static final NumMV NFi = new NumMV() { 19 | public Value call(Num x) { 20 | return Num.of(x.num*x.num); 21 | } 22 | public void call(double[] res, double[] x) { 23 | for (int i = 0; i < x.length; i++) res[i] = x[i]*x[i]; 24 | } 25 | }; 26 | public Value call(Value x) { 27 | return numM(NF, x); 28 | } 29 | public Value callInv(Value x) { 30 | return numM(NFi, x); 31 | } 32 | 33 | public static final Pervasion.NN2N DF = new Pervasion.NN2N() { 34 | public double on(double w, double x) { return Math.pow(x, 1/w); } 35 | public void on(double w, double[] x, double[] res) { 36 | double pow = 1/w; 37 | for (int i = 0; i < x.length; i++) res[i] = Math.pow(x[i], pow); 38 | } 39 | public void on(double[] w, double x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.pow(x , 1/w[i]); } 40 | public void on(double[] w, double[] x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.pow(x[i], 1/w[i]); } 41 | }; 42 | public Value call(Value w, Value x) { 43 | return DF.call(w, x); 44 | } 45 | 46 | public Value callInvX(Value w, Value x) { 47 | return StarBuiltin.DF.call(x, w); 48 | } 49 | public Value callInvW(Value w, Value x) { 50 | return LogBuiltin.DF.call(w, x); 51 | } 52 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/ShABuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.RankError; 4 | import BQN.tools.*; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | import BQN.types.callable.builtins.md1.CellBuiltin; 8 | 9 | public class ShABuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "«"; } 11 | 12 | public Value call(Value w, Value x) { 13 | if (x.scalar()) throw new RankError("«: 𝕩 cannot be scalar", this); 14 | if (w.r() > x.r()) throw new RankError("«: rank of 𝕨 cannot exceed =𝕩", this); 15 | JoinBuiltin.check(w, x, this); 16 | MutVal res = new MutVal(x.shape, x); 17 | if (w.ia < x.ia) { 18 | res.copy(x, w.ia, 0, x.ia-w.ia); 19 | res.copy(w, 0, x.ia-w.ia, w.ia); 20 | } else { 21 | res.copy(w, w.ia-x.ia, 0, x.ia); 22 | } 23 | return res.get(); 24 | } 25 | 26 | public Value call(Value x) { 27 | if (x.scalar()) throw new RankError("«: argument cannot be scalar", this); 28 | if (x.ia==0) return x; 29 | MutVal res = new MutVal(x.shape, x); 30 | int csz = CellBuiltin.csz(x); 31 | res.copy(x, csz, 0, x.ia-csz); 32 | res.fill(x.fItem(), x.ia-csz, x.ia); 33 | return res.get(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/ShBBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.RankError; 4 | import BQN.tools.*; 5 | import BQN.types.Value; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | import BQN.types.callable.builtins.md1.CellBuiltin; 8 | 9 | public class ShBBuiltin extends FnBuiltin { 10 | public String ln(FmtInfo f) { return "»"; } 11 | 12 | public Value call(Value w, Value x) { 13 | if (x.scalar()) throw new RankError("»: 𝕩 cannot be scalar", this); 14 | if (w.r() > x.r()) throw new RankError("»: rank of 𝕨 cannot exceed =𝕩", this); 15 | JoinBuiltin.check(w, x, this); 16 | MutVal res = new MutVal(x.shape, x); 17 | int mid = Math.min(w.ia, x.ia); 18 | res.copy(w, 0, 0, mid); 19 | res.copy(x, 0, mid, x.ia-mid); 20 | return res.get(); 21 | } 22 | 23 | public Value call(Value x) { 24 | if (x.scalar()) throw new RankError("»: argument cannot be scalar", this); 25 | if (x.ia==0) return x; 26 | MutVal res = new MutVal(x.shape, x); 27 | int csz = CellBuiltin.csz(x); 28 | res.fill(x.fItem(), 0, csz); 29 | res.copy(x, 0, csz, x.ia-csz); 30 | return res.get(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/StarBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.callable.builtins.FnBuiltin; 7 | 8 | import java.math.BigInteger; 9 | 10 | public class StarBuiltin extends FnBuiltin { 11 | public String ln(FmtInfo f) { return "⋆"; } 12 | public Value identity() { return Num.ONE; } 13 | 14 | public static final NumMV NF = new NumMV() { 15 | public Value call(Num x) { 16 | return new Num(Math.exp(x.num)); 17 | } 18 | public void call(double[] res, double[] x) { 19 | for (int i = 0; i < x.length; i++) res[i] = Math.exp(x[i]); 20 | } 21 | }; 22 | public Value call(Value x) { 23 | return numM(NF, x); 24 | } 25 | public Value callInv(Value x) { 26 | return numM(LogBuiltin.NF, x); 27 | } 28 | 29 | public static final Pervasion.NN2N DF = new Pervasion.NN2N() { 30 | public double on(double w, double x) { 31 | return Math.pow(w, x); 32 | } 33 | public void on(double w, double[] x, double[] res) { for (int i = 0; i < x.length; i++) res[i] = Math.pow(w , x[i]); } 34 | public void on(double[] w, double x, double[] res) { if (x == 2) for (int i = 0; i < w.length; i++) res[i] = w[i]*w[i]; 35 | else for (int i = 0; i < w.length; i++) res[i] = Math.pow(w[i], x ); } 36 | public void on(double[] w, double[] x, double[] res) { for (int i = 0; i < w.length; i++) res[i] = Math.pow(w[i], x[i]); } 37 | 38 | public int[] on(int w, int[] x) { 39 | if (w == -1) { 40 | int[] r = new int[x.length]; 41 | for (int i = 0; i < x.length; i++) r[i] = 1 - ((x[i]&1) << 1); 42 | return r; 43 | } 44 | return null; 45 | } 46 | 47 | public int[] on(int[] w, int x) { 48 | if (x==2) { 49 | int[] r = new int[w.length]; 50 | for (int i = 0; i < w.length; i++) { 51 | int c = w[i]; 52 | if (c > 46340) return null; // ⌊√2*31 53 | r[i] = c*c; 54 | } 55 | return r; 56 | } 57 | return null; 58 | } 59 | 60 | public Value on(BigValue w, BigValue x) { 61 | if (w.i.signum() == 0) return BigValue.ZERO; 62 | if (w.i.equals(BigInteger.ONE)) return BigValue.ONE; 63 | if (w.i.equals(BigValue.MINUS_ONE.i)) return x.i.intValue()%2 == 0? BigValue.ONE : BigValue.MINUS_ONE; 64 | if (x.i.bitLength() > 30) throw new DomainError("⋆: 𝕩 too big to calculate (𝕨 ≡ "+w+"; 𝕩 ≡ "+x+")"); // otherwise intValue might ignore those! 65 | return new BigValue(w.i.pow(x.i.intValue())); 66 | } 67 | }; 68 | 69 | public Pervasion.NN2N dyNum() { return DF; } 70 | public Value call(Value w, Value x) { 71 | return DF.call(w, x); 72 | } 73 | public Value callInvX(Value w, Value x) { 74 | return LogBuiltin.DF.call(w, x); 75 | } 76 | public Value callInvW(Value w, Value x) { 77 | return RootBuiltin.DF.call(x, w); 78 | } 79 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/TallyBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.IntArr; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | public class TallyBuiltin extends FnBuiltin { 10 | 11 | public String ln(FmtInfo f) { return "≢"; } 12 | 13 | public Value call(Value x) { 14 | return new IntArr(x.shape); 15 | } 16 | 17 | public Value call(Value w, Value x) { 18 | return w.eq(x)? Num.ZERO : Num.ONE; 19 | } 20 | 21 | public Value under(Value o, Value x) { 22 | Value v = o instanceof Fun? o.call(call(x)) : o; 23 | int[] sh = v.asIntVec(); 24 | 25 | if (Arr.prod(sh) != x.ia) throw new DomainError("⌾≢ expected equal amount of output & output items", this); 26 | return x.ofShape(sh); 27 | } 28 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/fns/UTackBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.fns; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.DoubleArr; 7 | import BQN.types.callable.builtins.FnBuiltin; 8 | 9 | import java.math.BigInteger; 10 | 11 | public class UTackBuiltin extends FnBuiltin { 12 | public String ln(FmtInfo f) { return "⊥"; } 13 | 14 | public Value call(Value x) { 15 | return call(Num.NUMS[2], x); 16 | } 17 | 18 | public Value callInv(Value x) { 19 | return DTackBuiltin.on(Num.NUMS[2], x, this); 20 | } 21 | public Value callInvX(Value w, Value x) { 22 | return DTackBuiltin.on(w, x, this); 23 | } 24 | 25 | public Value call(Value w, Value x) { 26 | return on(w, x, this); 27 | } 28 | 29 | public static Value on(Value w, Value x, Callable blame) { 30 | if (x.r() == 0) throw new DomainError("A⊥num is pointless", blame); 31 | if (w instanceof BigValue || w.first() instanceof BigValue || x.first() instanceof BigValue) { 32 | if (w.r() == 0) { 33 | BigInteger al = BigValue.bigint(w); 34 | BigInteger res = BigInteger.ZERO; 35 | for (int i = 0; i < x.ia; i++) { 36 | res = res.multiply(al).add(BigValue.bigint(x.get(i))); 37 | } 38 | return new BigValue(res); 39 | } else { 40 | if (x.r() != 1) throw new NYIError(blame+": 1<≠≢𝕩", blame); 41 | if (w.r() != 1) throw new DomainError(blame+": 1<≠≢𝕨", blame); 42 | if (w.ia != x.shape[0]) throw new DomainError(blame+": (≠𝕨) ≠ ≠𝕩", blame); 43 | BigInteger res = BigInteger.ZERO; 44 | for (int i = 0; i < w.ia; i++) { 45 | res = res.multiply(BigValue.bigint(w.get(i))); 46 | res = res.add(BigValue.bigint(x.get(i))); 47 | } 48 | return new BigValue(res); 49 | } 50 | } 51 | if (w instanceof Num) { 52 | double base = w.asDouble(); 53 | if (x.r() == 1) { 54 | double res = 0; 55 | for (int i = 0; i < x.ia; i++) { 56 | res = res*base + x.get(i).asDouble(); 57 | } 58 | return new Num(res); 59 | } else { 60 | double[] d = x.asDoubleArr(); 61 | int[] sh = new int[x.r()-1]; 62 | System.arraycopy(x.shape, 1, sh, 0, x.r() - 1); 63 | int layers = x.shape[0]; 64 | double[] r = new double[x.ia / layers]; 65 | 66 | System.arraycopy(d, 0, r, 0, r.length); 67 | for (int i = 1; i < layers; i++) { 68 | for (int j = 0; j < r.length; j++) { 69 | r[j] = r[j]*base + d[j+r.length*i]; 70 | } 71 | } 72 | 73 | return new DoubleArr(r, sh); 74 | } 75 | } else { 76 | if (w.ia != x.shape[0]) throw new DomainError(blame+": (≠𝕨) ≠ ≠𝕩", blame); 77 | double[] d = x.asDoubleArr(); 78 | double[] bases = w.asDoubleArr(); 79 | int[] sh = new int[x.r()-1]; 80 | System.arraycopy(x.shape, 1, sh, 0, x.r() - 1); 81 | int layers = x.shape[0]; 82 | double[] r = new double[x.ia/layers]; 83 | 84 | System.arraycopy(d, 0, r, 0, r.length); 85 | for (int i = 1; i < layers; i++) { 86 | double base = bases[i]; 87 | for (int j = 0; j < r.length; j++) { 88 | r[j] = r[j]*base + d[j+r.length*i]; 89 | } 90 | } 91 | if (sh.length == 0) return new Num(r[0]); 92 | return new DoubleArr(r, sh); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/ConstBultin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md1Derv; 6 | import BQN.types.callable.builtins.Md1Builtin; 7 | 8 | public class ConstBultin extends Md1Builtin { 9 | public String ln(FmtInfo f) { return "˙"; } 10 | 11 | public Value call(Value f, Value x, Md1Derv derv) { 12 | return f; 13 | } 14 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 15 | return f; 16 | } 17 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/EachLeft.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | import BQN.types.arrs.SingleItemArr; 6 | import BQN.types.callable.Md1Derv; 7 | import BQN.types.callable.builtins.Md1Builtin; 8 | 9 | public class EachLeft extends Md1Builtin { 10 | public String ln(FmtInfo f) { return "ᐵ"; } 11 | 12 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 13 | Value[] n = new Value[w.ia]; 14 | for (int i = 0; i < n.length; i++) { 15 | n[i] = f.call(w.get(i), x); 16 | } 17 | return Arr.create(n, w.shape); 18 | } 19 | 20 | public Value underW(Value f, Value o, Value w, Value x, Md1Derv derv) { 21 | return EachBuiltin.underW(f, o, w, SingleItemArr.r0(x), this); 22 | } 23 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/EachRight.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | import BQN.types.arrs.SingleItemArr; 6 | import BQN.types.callable.Md1Derv; 7 | import BQN.types.callable.builtins.Md1Builtin; 8 | 9 | public class EachRight extends Md1Builtin { 10 | public String ln(FmtInfo f) { return "ᑈ"; } 11 | 12 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 13 | Value[] n = new Value[x.ia]; 14 | for (int i = 0; i < n.length; i++) { 15 | n[i] = f.call(w, x.get(i)); 16 | } 17 | return Arr.create(n, x.shape); 18 | } 19 | 20 | public Value underW(Value f, Value o, Value w, Value x, Md1Derv derv) { 21 | return EachBuiltin.underW(f, o, SingleItemArr.r0(w), x, this); 22 | } 23 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/InsertBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.Main; 4 | import BQN.errors.*; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.Value; 7 | import BQN.types.arrs.*; 8 | import BQN.types.callable.Md1Derv; 9 | import BQN.types.callable.builtins.Md1Builtin; 10 | import BQN.types.callable.builtins.fns.JoinBuiltin; 11 | 12 | import java.util.Arrays; 13 | 14 | public class InsertBuiltin extends Md1Builtin { 15 | public String ln(FmtInfo f) { return "˝"; } 16 | 17 | public Value call(Value f, Value x, Md1Derv derv) { 18 | if (x.r()==0) throw new RankError("˝: argument cannot be a scalar", this); 19 | if (x.ia==0) { 20 | Value id = f.identity(); 21 | int[] csh = Arrays.copyOfRange(x.shape, 1, x.r()); 22 | if (id==null) { 23 | for (int c : csh) if (c==0) return new EmptyArr(csh, null); 24 | if (f instanceof JoinBuiltin && x.r()>1) { // ಠ_ಠ 25 | int[] sh = new int[x.r()-1]; 26 | System.arraycopy(x.shape, 2, sh, 1, x.shape.length-2); 27 | return new EmptyArr(sh, x.fItemS()); 28 | } 29 | throw new DomainError("˝: reducing array with shape "+ Main.fArr(x.shape)+" with a function without an identity value", this); 30 | } 31 | return new SingleItemArr(id, csh); 32 | } 33 | Value[] vs = CellBuiltin.cells(x); 34 | Value c = vs[vs.length-1]; 35 | for (int i = vs.length-2; i >= 0; i--) c = f.call(vs[i], c); 36 | return c; 37 | } 38 | 39 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 40 | if (x.r()==0) throw new RankError("˝: 𝕩 cannot be a scalar", this); 41 | Value[] vs = CellBuiltin.cells(x); 42 | Value c = w; 43 | for (int i = vs.length-1; i >= 0; i--) c = f.call(vs[i], c); 44 | return c; 45 | } 46 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/InvBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.errors.NYIError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.callable.Md1Derv; 7 | import BQN.types.callable.builtins.Md1Builtin; 8 | 9 | public class InvBuiltin extends Md1Builtin { 10 | public String ln(FmtInfo f) { return "⁼"; } 11 | 12 | public Value call(Value f, Value x, Md1Derv derv) { 13 | return f.callInv(x); 14 | } 15 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 16 | return f.callInvX(w, x); 17 | } 18 | 19 | public Value callInv(Value f, Value x) { 20 | return f.call(x); 21 | } 22 | public Value callInvX(Value f, Value w, Value x) { 23 | return f.call(w, x); 24 | } 25 | public Value callInvW(Value f, Value w, Value x) { 26 | return f.callInvW(x, w); 27 | } 28 | 29 | 30 | 31 | 32 | public static Fun invertM(Value f) { 33 | return new Fun() { 34 | public String ln(FmtInfo f) { return "⁼"; } 35 | public Value call(Value x) { 36 | return f.callInv(x); 37 | } 38 | }; 39 | } 40 | 41 | public static Fun invertX(Value f) { 42 | return new Fun() { 43 | public String ln(FmtInfo f) { return "⁼"; } 44 | public Value call(Value w, Value x) { 45 | return f.callInvX(w, x); 46 | } 47 | 48 | public Value callInvX(Value w, Value x) { 49 | return f.call(w, x); 50 | } 51 | }; 52 | } 53 | 54 | public static Fun invertW(Value f) { 55 | return new Fun() { 56 | public String ln(FmtInfo f) { return "˜⁼˜"; } 57 | public Value call(Value w, Value x) { 58 | return f.callInvW(w, x); 59 | } 60 | 61 | public Value callInvW(Value w, Value x) { 62 | return f.call(w, x); 63 | } 64 | }; 65 | } 66 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/ObliqueBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.arrs.*; 7 | import BQN.types.callable.Md1Derv; 8 | import BQN.types.callable.builtins.Md1Builtin; 9 | import BQN.types.callable.builtins.fns.GTBuiltin; 10 | 11 | public class ObliqueBuiltin extends Md1Builtin { 12 | public String ln(FmtInfo f) { return "⍁"; } 13 | 14 | public Value call(Value f, Value x, Md1Derv derv) { 15 | if (x.r() != 2) throw new DomainError("⍁: 𝕩 must be a rank 2 array", this); 16 | int[] sz = x.shape; 17 | int H = sz[0]; 18 | int W = sz[1]; 19 | int szM = Math.max(H, W); 20 | int szm = Math.min(H, W); 21 | int ram = H + W - 1; 22 | if (ram <= 0) return new EmptyArr(EmptyArr.SHAPE0, x.fItemS()); 23 | 24 | Value[] res = new Value[ram]; 25 | 26 | if (x.quickDoubleArr()) { 27 | double[] vals = x.asDoubleArr(); 28 | double[][] rows = new double[ram][]; 29 | for (int i = 0; i < ram; i++) { 30 | rows[i] = new double[i < szm? i + 1 : i >= szM? szm + szM - i - 1 : szm]; 31 | } 32 | int p = 0; 33 | for (int cy = 0; cy < H; cy++) { 34 | for (int cx = 0; cx < W; cx++) { 35 | double v = vals[p++]; 36 | int ri = cx + cy; 37 | int s = ri > W - 2? cy + W - ri - 1 : cy; 38 | rows[ri][s] = v; 39 | } 40 | } 41 | res[0] = f.call(new DoubleArr(rows[0])); 42 | int rrank = res[0].r(); // required rank 43 | for (int i = 0; i < ram; i++) { 44 | Value v = f.call(new DoubleArr(rows[i])); 45 | if (v.r() != rrank) throw new RankError("⍁: 𝔽 must return equal rank arrays", this); 46 | res[i] = v; 47 | } 48 | } else { 49 | Value[] vals = x.values(); 50 | Value[][] rows = new Value[ram][]; 51 | for (int i = 0; i < ram; i++) { 52 | rows[i] = new Value[i < szm? i + 1 : i >= szM? szm + szM - i - 1 : szm]; 53 | } 54 | int p = 0; 55 | for (int cy = 0; cy < H; cy++) { 56 | for (int cx = 0; cx < W; cx++) { 57 | Value v = vals[p++]; 58 | int ri = cx + cy; 59 | int s = ri > W - 2? cy + W - ri - 1 : cy; 60 | rows[ri][s] = v; 61 | } 62 | } 63 | res[0] = f.call(new HArr(rows[0])); 64 | int rrank = res[0].r(); // required rank 65 | for (int i = 0; i < ram; i++) { 66 | Value v = f.call(new HArr(rows[i])); 67 | if (v.r() != rrank) throw new DomainError("⍁: 𝔽 must return equal rank arrays", this); 68 | res[i] = v; 69 | } 70 | } 71 | 72 | return GTBuiltin.merge(res, new int[]{res.length}, this); 73 | } 74 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/OldKeyBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.Main; 4 | import BQN.errors.*; 5 | import BQN.tools.FmtInfo; 6 | import BQN.types.*; 7 | import BQN.types.arrs.HArr; 8 | import BQN.types.callable.Md1Derv; 9 | import BQN.types.callable.builtins.Md1Builtin; 10 | 11 | import java.util.*; 12 | 13 | public class OldKeyBuiltin extends Md1Builtin { 14 | public String ln(FmtInfo f) { return "⌸"; } 15 | 16 | public Value call(Value f, Value x, Md1Derv derv) { 17 | if (f instanceof BQNObj) { 18 | if (x.r() > 1) { 19 | Value[] arr = new Value[x.ia]; 20 | for (int i = 0; i < x.ia; i++) { 21 | arr[i] = ((BQNObj) f).get(x.get(i)); 22 | } 23 | return Arr.create(arr, x.shape); 24 | } 25 | return ((BQNObj) f).get(x); 26 | } 27 | if (f instanceof Fun) { 28 | int i = 0; 29 | HashMap> vals = new HashMap<>(); 30 | ArrayList order = new ArrayList<>(); 31 | for (Value v : x) { 32 | if (!vals.containsKey(v)) { 33 | ArrayList l = new ArrayList<>(); 34 | l.add(Num.of(i)); 35 | vals.put(v, l); 36 | order.add(v); 37 | } else { 38 | vals.get(v).add(Num.of(i)); 39 | } 40 | i++; 41 | } 42 | Value[] res = new Value[order.size()]; 43 | i = 0; 44 | for (Value c : order) { 45 | res[i++] = f.call(c, Arr.create(vals.get(c))); 46 | } 47 | return new HArr(res); 48 | } 49 | throw new DomainError("⌸: 𝔽 must be a function or a map, was "+f.humanType(true), derv); 50 | } 51 | 52 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 53 | if (f instanceof BQNObj) { 54 | ((BQNObj) f).set(w, x); 55 | return x; 56 | } 57 | if (f instanceof Fun) { 58 | if (!Arrays.equals(w.shape, x.shape)) { 59 | if (w.r() != x.r()) throw new RankError("dyadic ⌸ expected 𝕨 & 𝕩 to have equal ranks ("+w.r()+" vs "+x.r()+")", derv); 60 | throw new LengthError("dyadic ⌸ expected 𝕨 & 𝕩 to have equal shapes ("+Main.fArr(w.shape)+" vs "+Main.fArr(x.shape)+")", derv); 61 | } 62 | HashMap> vals = new HashMap<>(); 63 | ArrayList order = new ArrayList<>(); 64 | for (int i = 0; i < w.ia; i++) { 65 | Value k = x.get(i); 66 | Value v = w.get(i); 67 | ArrayList curr = vals.get(k); 68 | if (curr == null) { 69 | ArrayList newArr = new ArrayList<>(); 70 | vals.put(k, newArr); 71 | curr = newArr; 72 | order.add(k); 73 | } 74 | curr.add(v); 75 | } 76 | Value[] res = new Value[order.size()]; 77 | for (int i = 0; i < order.size(); i++) { 78 | Value k = order.get(i); 79 | Value vs = Arr.create(vals.get(k)); 80 | res[i] = f.call(k, vs); 81 | } 82 | return Arr.create(res); 83 | } 84 | throw new DomainError("⌸: 𝔽 must be a function or a map, was "+f.humanType(true), derv); 85 | } 86 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md1/SelfieBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md1; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.Value; 6 | import BQN.types.callable.Md1Derv; 7 | import BQN.types.callable.builtins.Md1Builtin; 8 | import BQN.types.callable.builtins.fns.*; 9 | 10 | public class SelfieBuiltin extends Md1Builtin { 11 | public String ln(FmtInfo f) { return "˜"; } 12 | 13 | public Value call(Value f, Value x, Md1Derv derv) { 14 | return f.call(x, x); 15 | } 16 | public Value call(Value f, Value w, Value x, Md1Derv derv) { 17 | return f.call(x, w); 18 | } 19 | 20 | public static RootBuiltin rb = new RootBuiltin(); 21 | public Value callInv(Value f, Value x) { 22 | if (f instanceof PlusBuiltin) return DivBuiltin.DF.scalarX(x, 2); 23 | if (f instanceof MulBuiltin || f instanceof AndBuiltin) { 24 | rb.token = token; return rb.call(x); 25 | } 26 | if (f instanceof OrBuiltin) { 27 | rb.token = token; return NotBuiltin.on(rb.call(NotBuiltin.on(x, this)), this); 28 | } 29 | throw new DomainError(f+"˜: cannot invert", this); 30 | } 31 | 32 | public Value callInvX(Value f, Value w, Value x) { 33 | return f.callInvW(x, w); 34 | } 35 | 36 | public Value callInvW(Value f, Value w, Value x) { 37 | return f.callInvX(x, w); 38 | } 39 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/AfterBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class AfterBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⟜"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return call(f, g, x, x, derv); 13 | } 14 | 15 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 16 | return f.call(w, g.call(x)); 17 | } 18 | 19 | public Value callInv(Value f, Value g, Value x) { 20 | return f.callInvW(x, g.constant(this, true)); 21 | } 22 | public Value callInvX(Value f, Value g, Value a, Value w) { 23 | return g.callInv(f.callInvX(a, w)); 24 | } 25 | public Value callInvW(Value f, Value g, Value a, Value w) { 26 | return f.callInvW(a, g.call(w)); 27 | } 28 | 29 | public Value under(Value f, Value g, Value o, Value x, Md2Derv derv) { 30 | return f.underA(o, x, g.constant(this, true)); 31 | } 32 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/AmbivalentBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class AmbivalentBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⊘"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return f.call(x); 13 | } 14 | public Value callInv(Value f, Value g, Value x) { 15 | return f.callInv(x); 16 | } 17 | 18 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 19 | return g.call(w, x); 20 | } 21 | public Value callInvW(Value f, Value g, Value w, Value x) { 22 | return g.callInvW(w, x); 23 | } 24 | public Value callInvX(Value f, Value g, Value w, Value x) { 25 | return g.callInvX(w, x); 26 | } 27 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/AtBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.Main; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.arrs.DoubleArr; 7 | import BQN.types.callable.Md2Derv; 8 | import BQN.types.callable.builtins.Md2Builtin; 9 | import BQN.types.callable.builtins.fns.LBoxUBBuiltin; 10 | 11 | public class AtBuiltin extends Md2Builtin { 12 | public String ln(FmtInfo f) { return "@"; } 13 | 14 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 15 | return at(f, g, x, this); 16 | } 17 | 18 | public static Value at(Value f, Value g, Value x, Callable blame) { 19 | int ia = x.ia; 20 | if (g instanceof Fun) { 21 | Value vba = g.call(x); 22 | boolean[] ba = new boolean[ia]; 23 | int matchingCount = 0; 24 | for (int i = 0; i < ia; i++) { 25 | ba[i] = Main.bool(vba.get(i)); 26 | if (ba[i]) matchingCount++; 27 | } 28 | Value fa; 29 | if (f instanceof Fun) { 30 | Value[] matching = new Value[matchingCount]; 31 | int ptr = 0; 32 | for (int i = 0; i < ia; i++) { 33 | if (ba[i]) matching[ptr++] = x.get(i); 34 | } 35 | fa = f.call(Arr.create(matching)); 36 | } else fa = f; 37 | Value[] ra = new Value[ia]; 38 | if (fa.r() == 0) { 39 | Value inner = fa.get(0); 40 | for (int i = 0; i < ia; i++) { 41 | if (ba[i]) ra[i] = inner; 42 | else ra[i] = x.get(i); 43 | } 44 | } else { 45 | int ptr = 0; 46 | for (int i = 0; i < ia; i++) { 47 | if (ba[i]) ra[i] = fa.get(ptr++); 48 | else ra[i] = x.get(i); 49 | } 50 | } 51 | return Arr.create(ra, x.shape); 52 | } else { 53 | 54 | Indexer.PosSh poss = Indexer.poss(g, x.shape, blame); 55 | Value repl; 56 | if (f instanceof Fun) { 57 | Value arg = LBoxUBBuiltin.on(poss, x); 58 | repl = f.call(arg); 59 | } else { 60 | repl = f; 61 | } 62 | return with(x, poss, repl, blame); 63 | } 64 | } 65 | 66 | public static Value with(Value o, Indexer.PosSh poss, Value n, Callable blame) { 67 | if (o.quickDoubleArr() && n.quickDoubleArr()) { 68 | double[] res = o.asDoubleArrClone(); 69 | int[] is = poss.vals; 70 | if (n.r() == 0) { 71 | double f0 = n.first().asDouble(); 72 | // noinspection ForLoopReplaceableByForEach 73 | for (int i = 0; i < is.length; i++) res[is[i]] = f0; 74 | } else { 75 | double[] nd = n.asDoubleArr(); 76 | Arr.eqShapes(n.shape, poss.sh, blame); 77 | for (int i = 0; i < is.length; i++) res[is[i]] = nd[i]; 78 | } 79 | return o.r()==0? Num.of(res[0]) : new DoubleArr(res, o.shape); 80 | } 81 | Value[] res = o.valuesClone(); 82 | int[] is = poss.vals; 83 | if (n.r() == 0) { 84 | Value f0 = n.first(); 85 | // noinspection ForLoopReplaceableByForEach 86 | for (int i = 0; i < is.length; i++) res[is[i]] = f0; 87 | } else { 88 | Arr.eqShapes(n.shape, poss.sh, blame); 89 | for (int i = 0; i < is.length; i++) res[is[i]] = n.get(i); 90 | } 91 | return Arr.create(res, o.shape); 92 | } 93 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/AtopBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class AtopBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "∘"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return f.call(g.call(x)); 13 | } 14 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 15 | return f.call(g.call(w, x)); 16 | } 17 | 18 | 19 | public Value callInv(Value f, Value g, Value x) { 20 | return g.callInv(f.callInv(x)); 21 | } 22 | 23 | public Value callInvX(Value f, Value g, Value w, Value x) { 24 | return g.callInvX(w, f.callInv(x)); 25 | } 26 | public Value callInvW(Value f, Value g, Value w, Value x) { 27 | return g.callInvW(f.callInv(w), x); 28 | } 29 | 30 | public Value under(Value f, Value g, Value o, Value x, Md2Derv derv) { 31 | return g.under(new Fun() { public String ln(FmtInfo fi) { return f.ln(fi); } 32 | public Value call(Value x) { 33 | return f.under(o, x); 34 | } 35 | }, x); 36 | } 37 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/BeforeBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class BeforeBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⊸"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return call(f, g, x, x, derv); 13 | } 14 | 15 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 16 | return g.call(f.call(w), x); 17 | } 18 | 19 | public Value callInv(Value f, Value g, Value x) { 20 | return g.callInvX(f.constant(this, true), x); 21 | } 22 | public Value callInvX(Value f, Value g, Value a, Value w) { 23 | return g.callInvX(f.call(a), w); 24 | } 25 | public Value callInvW(Value f, Value g, Value a, Value w) { 26 | return f.callInv(g.callInvW(a, w)); 27 | } 28 | 29 | public Value under(Value f, Value g, Value o, Value x, Md2Derv derv) { 30 | return g.underW(o, f.constant(this, true), x); 31 | } 32 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/CRepeatBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.Main; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.callable.Md2Derv; 7 | import BQN.types.callable.builtins.Md2Builtin; 8 | 9 | import java.util.ArrayList; 10 | 11 | public class CRepeatBuiltin extends Md2Builtin { 12 | public String ln(FmtInfo f) { return "⍡"; } 13 | 14 | @Override public Value call(Value f, Value g, Value x, Md2Derv derv) { 15 | if (g instanceof Fun) { 16 | ArrayList res = new ArrayList<>(); 17 | Value prev = x; 18 | res.add(prev); 19 | 20 | Value next = f.call(prev); 21 | res.add(next); 22 | while(!Main.bool(g.call(prev, next))) { 23 | prev = next; 24 | next = f.call(prev); 25 | res.add(next); 26 | } 27 | return Arr.create(res); 28 | } else { 29 | int n = g.asInt(); 30 | Value[] res = new Value[n]; 31 | Value curr = x; 32 | for (int i = 0; i < n; i++) { 33 | curr = f.call(curr); 34 | res[i] = curr; 35 | } 36 | return Arr.create(res); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/CatchBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class CatchBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⎊"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | try { 13 | return f.call(x); 14 | } catch (Throwable e) { 15 | return g.call(x); 16 | } 17 | } 18 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 19 | try { 20 | return f.call(w, x); 21 | } catch (Throwable e) { 22 | return g.call(w, x); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/CondBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.*; 5 | import BQN.types.*; 6 | import BQN.types.callable.Md2Derv; 7 | import BQN.types.callable.builtins.Md2Builtin; 8 | import BQN.types.callable.builtins.fns.LBoxUBBuiltin; 9 | 10 | public class CondBuiltin extends Md2Builtin { 11 | public String ln(FmtInfo f) { return "◶"; } 12 | 13 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 14 | return get(f.call(x), g).call(x); 15 | } 16 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 17 | return get(f.call(w, x), g).call(w, x); 18 | } 19 | 20 | private Value get(Value F, Value g) { 21 | if (F instanceof Num) { 22 | int f = F.asInt(); 23 | if (g.r() != 1) throw new RankError("◶: Expected 𝕘 to be a vector, had rank "+g.r(), this); 24 | if (f>=g.ia) throw new LengthError("◶: 𝔽 out of bounds of 𝕘 (𝔽 = "+f+")", this); 25 | if (f<0) return g.get(Indexer.scal(f, g.shape, this)); 26 | return g.get(f); 27 | } 28 | return LBoxUBBuiltin.on(F, g, this); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/DepthBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.errors.*; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.callable.Md2Derv; 7 | import BQN.types.callable.builtins.Md2Builtin; 8 | import BQN.types.callable.builtins.fns.MatchBuiltin; 9 | 10 | public class DepthBuiltin extends Md2Builtin { 11 | public String ln(FmtInfo f) { return "⚇"; } 12 | 13 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 14 | int d = g.asInt(); 15 | if (d < 0) throw new NYIError("negative 𝕘 for ⚇", this); 16 | return on(f, d, x, derv); 17 | } 18 | 19 | public static Value on(Value f, int d, Value w, Fun blame) { 20 | int ld = MatchBuiltin.lazy(w); 21 | if (ld==d || ld <= -d) { 22 | int fd = MatchBuiltin.full(w); 23 | if (d>0 && d!=fd) throw new DomainError(blame+": can't match a depth "+fd+" array", blame); 24 | if (d <= fd) { 25 | return f.call(w); 26 | } 27 | } 28 | if (d>0 && ld < d) throw new DomainError(blame+": can't match a depth "+MatchBuiltin.full(w)+" array", blame); 29 | Value[] res = new Value[w.ia]; 30 | for (int i = 0; i < res.length; i++) { 31 | res[i] = on(f, d, w.get(i), blame); 32 | } 33 | return Arr.create(res, w.shape); 34 | } 35 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/DotBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | import BQN.types.callable.builtins.md1.FoldBuiltin; 8 | 9 | public class DotBuiltin extends Md2Builtin { 10 | public String ln(FmtInfo f) { return "."; } 11 | 12 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 13 | return new FoldBuiltin().derive(f).call(g.call(w, x)); // TODO not lazy 14 | } 15 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/JotUBBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class JotUBBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⍛"; } 10 | 11 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 12 | return g.call(f.call(w), x); 13 | } 14 | 15 | public Value callInvX(Value f, Value g, Value w, Value x) { 16 | return g.callInvX(f.call(w), x); 17 | } 18 | 19 | public Value callInvW(Value f, Value g, Value w, Value x) { 20 | return f.callInv(g.callInvW(w, x)); 21 | } 22 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/ObverseBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class ObverseBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "⍫"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return f.call(x); 13 | } 14 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 15 | return f.call(w, x); 16 | } 17 | 18 | public Value callInv(Value f, Value g, Value x) { 19 | return g.call(x); 20 | } 21 | public Value callInvX(Value f, Value g, Value w, Value x) { 22 | return g.call(w, x); 23 | } 24 | 25 | public Value callInvW(Value f, Value g, Value w, Value x) { // fall-back to 𝔽 26 | return f.callInvW(w, x); 27 | } 28 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/OverBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.Value; 5 | import BQN.types.callable.Md2Derv; 6 | import BQN.types.callable.builtins.Md2Builtin; 7 | 8 | public class OverBuiltin extends Md2Builtin { 9 | public String ln(FmtInfo f) { return "○"; } 10 | 11 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 12 | return f.call(g.call(x)); 13 | } 14 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 15 | return f.call(g.call(w), g.call(x)); 16 | } 17 | 18 | public Value callInvX(Value f, Value g, Value w, Value x) { 19 | return g.callInv(f.callInvX(g.call(w), x)); 20 | } 21 | public Value callInvW(Value f, Value g, Value w, Value x) { 22 | return g.callInv(f.callInvW(w, g.call(x))); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/builtins/md2/UnderBuiltin.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.builtins.md2; 2 | 3 | import BQN.errors.DomainError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.callable.Md2Derv; 7 | import BQN.types.callable.builtins.Md2Builtin; 8 | import BQN.types.callable.builtins.md1.InvBuiltin; 9 | 10 | public class UnderBuiltin extends Md2Builtin { 11 | public String ln(FmtInfo f) { return "⌾"; } 12 | 13 | public Value call(Value f, Value g, Value x, Md2Derv derv) { 14 | return g.under(f, x); 15 | } 16 | public Value callInv(Value f, Value g, Value x) { 17 | return g.under(InvBuiltin.invertM(f), x); 18 | } 19 | 20 | public Value call(Value f, Value g, Value w, Value x, Md2Derv derv) { 21 | return g.under(new BindA(g.call(w), f), x); 22 | } 23 | public Value callInvX(Value f, Value g, Value w, Value x) { 24 | return g.under(new BindA(g.call(w), InvBuiltin.invertX(f)), x); 25 | } 26 | public Value callInvW(Value f, Value g, Value w, Value x) { // structural inverse is not possible; fall back to computational inverse 27 | Value w1 = g.call(w); 28 | Value x1 = g.call(x); 29 | try { 30 | return g.callInv(f.callInvW(w1, x1)); 31 | } catch (DomainError e) { // but add a nice warning about it if a plausible error was received (todo better error management to not require parsing the message?) 32 | String msg = e.getMessage(); 33 | if (msg.contains("doesn't support") && msg.contains("inverting")) { 34 | throw new DomainError(msg + " (possibly caused by using f⌾g˜⁼, which only allows computational inverses)", e.obj); 35 | } throw e; 36 | } 37 | } 38 | 39 | public static class BindA extends Fun { // +todo think about merging with ⊸ 40 | final Value w; 41 | final Value f; 42 | public BindA(Value w, Value f) { 43 | this.w = w; 44 | this.f = f; 45 | } 46 | 47 | public Value call(Value x) { 48 | return f.call(w, x); 49 | } 50 | public Value callInv(Value x) { 51 | return f.callInvX(w, x); 52 | } 53 | 54 | public boolean eq(Value o) { 55 | if (!(o instanceof BindA)) return false; 56 | BindA that = (BindA) o; 57 | return this.w.eq(that.w) && this.f.eq(that.f); 58 | } 59 | public int hashCode() { 60 | return 31*w.hashCode() + f.hashCode(); 61 | } 62 | public String ln(FmtInfo fi) { return f.ln(fi); } 63 | } 64 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/trains/Atop.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.trains; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public class Atop extends Fun { 7 | public final Value g; 8 | public final Value h; 9 | public Atop(Value g, Value h) { 10 | this.g = g; 11 | this.h = h; 12 | } 13 | 14 | public Value call(Value x) { 15 | return g.call(h.call(x)); 16 | } 17 | public Value callInv(Value x) { 18 | return h.callInv(g.callInv(x)); 19 | } 20 | public Value call(Value w, Value x) { 21 | return g.call(h.call(w, x)); 22 | } 23 | 24 | public Value callInvX(Value w, Value x) { 25 | return h.callInvX(w, g.callInv(x)); 26 | } 27 | 28 | public Value callInvW(Value w, Value x) { 29 | return h.callInvW(g.callInv(w), x); 30 | } 31 | 32 | public Value under(Value o, Value x) { 33 | return h.under(new Fun() { public String ln(FmtInfo f) { return g.ln(f); } 34 | public Value call(Value x) { 35 | return g.under(o, x); 36 | } 37 | }, x); 38 | } 39 | 40 | public String ln(FmtInfo f) { 41 | return "("+g.ln(f)+" "+h.ln(f)+")"; 42 | } 43 | 44 | 45 | public boolean eq(Value o) { 46 | if (!(o instanceof Atop)) return false; 47 | Atop that = (Atop) o; 48 | return this.g.eq(that.g) && this.h.eq(that.h); 49 | } 50 | public int hashCode() { 51 | return 31*g.hashCode() + h.hashCode(); 52 | } 53 | } -------------------------------------------------------------------------------- /src/BQN/types/callable/trains/Fork.java: -------------------------------------------------------------------------------- 1 | package BQN.types.callable.trains; 2 | 3 | import BQN.tools.FmtInfo; 4 | import BQN.types.*; 5 | 6 | public class Fork extends Fun { 7 | public final Value f, g, h; 8 | public Fork(Value f, Value g, Value h) { 9 | this.f = f; 10 | this.g = g; 11 | this.h = h; 12 | } 13 | 14 | public Value call(Value x) { 15 | Value r = h.call(x); 16 | Value l = f.call(x); 17 | return g.call(l, r); 18 | } 19 | public Value callInv(Value x) { 20 | Value fc = f.constant(this, false); 21 | if (fc!=null) return h.callInv(g.callInvX(fc, x)); 22 | return f.callInv(g.callInvW(x, h.constant(this, true))); 23 | } 24 | public Value call(Value w, Value x) { 25 | Value r = h.call(w, x); 26 | Value l = f.call(w, x); 27 | return g.call(l, r); 28 | } 29 | public Value callInvX(Value w, Value x) { 30 | return h.callInvX(w, g.callInvX(f.constant(this, true), x)); 31 | } 32 | public Value callInvW(Value w, Value x) { 33 | return h.callInvW(g.callInvX(f.constant(this, true), w), x); 34 | } 35 | 36 | public Value under(Value o, Value x) { 37 | Value cf = f.constant(this, true); 38 | return h.under(new Fun() { public String ln(FmtInfo f) { return g.ln(f); } 39 | public Value call(Value x) { 40 | return g.underW(o, cf, x); 41 | } 42 | }, x); 43 | } 44 | 45 | 46 | public boolean eq(Value o) { 47 | if (!(o instanceof Fork)) return false; 48 | Fork that = (Fork) o; 49 | return this.f.eq(that.f) && this.g.eq(that.g) && this.h.eq(that.h); 50 | } 51 | public int hashCode() { 52 | int res = f.hashCode(); 53 | res = 31*res + g.hashCode(); 54 | res = 31*res + h.hashCode(); 55 | return res; 56 | } 57 | public String ln(FmtInfo fi) { 58 | return "("+f.ln(fi)+" "+g.ln(fi)+" "+h.ln(fi)+")"; 59 | } 60 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/Alias.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.ImplementationError; 5 | import BQN.tools.Body; 6 | import BQN.types.*; 7 | 8 | public class Alias extends Settable { 9 | public final Settable prev; 10 | public final String name; 11 | 12 | public Alias(Settable prev, Body b, int n) { 13 | this.prev = prev; 14 | name = b.nameMap[n]; 15 | } 16 | 17 | public Value get(Scope sc) { 18 | throw new ImplementationError("Reading a left-hand-side namespace"); 19 | } 20 | 21 | public void set(Value x, boolean update, Scope sc, Callable blame) { 22 | prev.set(x, update, sc, blame); 23 | } 24 | 25 | public boolean seth(Value x, Scope sc) { 26 | return prev.seth(x, sc); 27 | } 28 | 29 | public String name(Scope sc) { 30 | return name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/BQN/types/mut/Local.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.ValueError; 5 | import BQN.types.*; 6 | 7 | public class Local extends Settable { 8 | 9 | public final int depth, index; 10 | 11 | public Local(int depth, int index) { 12 | this.depth = depth; 13 | this.index = index; 14 | } 15 | 16 | public Value get(Scope sc) { 17 | Value got = sc.getL(depth, index); 18 | if (got == null) throw new ValueError("Getting value of non-existing variable \""+name(sc)+"\""); 19 | return got; 20 | } 21 | 22 | public void set(Value x, boolean update, Scope sc, Callable blame) { 23 | sc = sc.owner(depth); 24 | if (update ^ sc.vars[index]!=null) { 25 | if (update) { 26 | throw new ValueError("no variable \""+name(sc)+"\" to update", blame); 27 | } else { 28 | if (sc.parent!=null | sc.vars[0]!=Scope.REPL_MARK) throw redefine(name(sc), blame); // allow top-level redeclarations 29 | } 30 | } 31 | sc.vars[index] = x; 32 | } 33 | 34 | public boolean seth(Value x, Scope sc) { 35 | sc.owner(depth).vars[index] = x; 36 | return true; 37 | } 38 | 39 | public static ValueError redefine(String name, Tokenable blame) { 40 | return new ValueError("Cannot redefine \""+name+"\"", blame); 41 | } 42 | 43 | @Override public String name(Scope sc) { 44 | return sc.owner(depth).varNames[index]; 45 | } 46 | @Override protected boolean hasName() { 47 | return true; 48 | } 49 | 50 | public String toString() { 51 | return "loc("+depth+","+index+")"; 52 | } 53 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/MatchSettable.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.DomainError; 5 | import BQN.types.*; 6 | 7 | public class MatchSettable extends Settable { 8 | private final Value v; 9 | 10 | public MatchSettable(Value v) { 11 | this.v = v; 12 | } 13 | 14 | public Value get(Scope sc) { 15 | return v; 16 | } 17 | 18 | public void set(Value x, boolean update, Scope sc, Callable blame) { 19 | if (!x.eq(v)) throw new DomainError("setting a constant to a non-equivalent value", blame); 20 | } 21 | 22 | public boolean seth(Value x, Scope sc) { 23 | return x.eq(v); 24 | } 25 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/Namespace.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.ValueError; 5 | import BQN.tools.*; 6 | import BQN.types.*; 7 | import BQN.types.arrs.ChrArr; 8 | 9 | import java.util.HashMap; 10 | 11 | public class Namespace extends BQNObj { 12 | public final Scope sc; 13 | private final HashMap exports; 14 | public Namespace(Scope sc, HashMap exports) { 15 | this.sc = sc; 16 | this.exports = exports; 17 | } 18 | 19 | public Value get(Value k) { 20 | return get(k.asString()); 21 | } 22 | 23 | public Value get(String k) { 24 | Integer kn = exports.get(k); 25 | if (kn==null) return null; 26 | return sc.vars[kn]; 27 | } 28 | 29 | public void set(Value ko, Value v) { 30 | String k = ko.asString(); 31 | Integer kn = exports.get(k); 32 | if (kn==null) throw new ValueError("Setting non-defined namespace field "+ko); 33 | sc.vars[kn] = v; 34 | } 35 | 36 | public Value[][] kvPair() { 37 | Value[] ks = new Value[exports.size()]; 38 | Value[] vs = new Value[exports.size()]; 39 | final int[] i = {0}; 40 | exports.forEach((k, v) -> { 41 | ks[i[0]++] = new ChrArr(k); 42 | vs[i[0]++] = sc.vars[v]; 43 | }); 44 | return new Value[][]{ks, vs}; 45 | } 46 | 47 | public int size() { 48 | return exports.size(); 49 | } 50 | 51 | public boolean eq(Value o) { 52 | return o instanceof Namespace && ((Namespace) o).sc == sc; 53 | } 54 | 55 | public int hashCode() { 56 | return sc.hashCode(); 57 | } 58 | 59 | public String ln(FmtInfo f) { 60 | if (f.v.contains(this)) return "{...}"; 61 | f.v.add(this); 62 | StringBuilder res = new StringBuilder("{"); 63 | exports.forEach((key, value) -> { 64 | if (res.length() != 1) res.append(" ⋄ "); 65 | String v = sc.vars[value].ln(f); 66 | res.append(key).append("⇐").append(v); 67 | }); 68 | f.v.remove(this); 69 | return res + "}"; 70 | } 71 | public Value pretty(FmtInfo f) { 72 | return Format.str(ln(f)); 73 | } 74 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/Quad.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.*; 4 | import BQN.errors.SyntaxError; 5 | import BQN.types.*; 6 | import BQN.types.arrs.ChrArr; 7 | 8 | public class Quad extends Settable { 9 | 10 | public void set(Value x, boolean update, Scope sc, Callable blame) { // don't care about updating 11 | if (Main.debug) sc.sys.println("[log] "+x); 12 | else sc.sys.println(x); 13 | } 14 | 15 | public Value get(Scope sc) { 16 | return new ChrArr(sc.sys.input()); 17 | } 18 | 19 | public boolean seth(Value x, Scope sc) { 20 | throw new SyntaxError("• cannot be a part of a header"); 21 | } 22 | 23 | public String toString() { 24 | return "•"; 25 | } 26 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/Settable.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.SyntaxError; 5 | import BQN.types.*; 6 | 7 | public abstract class Settable extends Obj { 8 | public abstract Value get(Scope sc); 9 | public abstract void set(Value x, boolean update, Scope sc, Callable blame); 10 | public abstract boolean seth(Value x, Scope sc); // returns if was successful 11 | 12 | public String name(Scope sc) { 13 | throw new SyntaxError("Expected a name"); 14 | } 15 | protected boolean hasName() { 16 | return false; 17 | } 18 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/SettableArr.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.LengthError; 5 | import BQN.types.*; 6 | 7 | public class SettableArr extends Settable { 8 | public final Settable[] arr; 9 | public final int ia; 10 | public SettableArr(Settable[] arr) { 11 | ia = arr.length; 12 | this.arr = arr; 13 | } 14 | 15 | public Arr get(Scope sc) { 16 | Value[] res = new Value[arr.length]; 17 | for (int i = 0; i < ia; i++) res[i] = arr[i].get(sc); 18 | return Arr.create(res); 19 | } 20 | 21 | 22 | public String toString() { 23 | return "vararr"; 24 | } 25 | 26 | 27 | public void set(Value x, boolean update, Scope sc, Callable blame) { 28 | if (x.r() != 1) { 29 | if (x instanceof BQNObj) { 30 | BQNObj ns = (BQNObj) x; 31 | for (Settable c : arr) c.set(ns.getChk(c.name(sc)), update, sc, blame); 32 | return; 33 | } 34 | throw new LengthError((update?'↩':'←')+": scatter rank ≠1"); 35 | } 36 | if (x.ia != ia) throw new LengthError((update?'↩':'←')+": scatter argument lengths not equal"); 37 | 38 | for (int i = 0; i < ia; i++) arr[i].set(x.get(i), update, sc, null); 39 | } 40 | 41 | public boolean seth(Value x, Scope sc) { 42 | if (x.r() != 1) { 43 | if (x instanceof BQNObj) { 44 | BQNObj ns = (BQNObj) x; 45 | for (Settable c : arr) { 46 | Value val = ns.get(c.name(sc)); 47 | if (val==null) return false; 48 | if (!c.hasName() || !c.seth(val, sc)) return false; 49 | } 50 | return true; 51 | } 52 | return false; 53 | } 54 | if (x.ia != ia) return false; 55 | 56 | for (int i = 0; i < ia; i++) if (!arr[i].seth(x.get(i), sc)) return false; 57 | return true; 58 | } 59 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/SettableNS.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.*; 5 | import BQN.types.*; 6 | 7 | public class SettableNS extends Settable { 8 | Value[] keys; 9 | Settable[] vals; 10 | public SettableNS(Settable[] vals, Value keys) { 11 | this.keys = keys.values(); 12 | this.vals = vals; 13 | } 14 | 15 | public Value get(Scope sc) { 16 | throw new SyntaxError("Modified assignment on namespace not allowed"); 17 | } 18 | 19 | public void set(Value x, boolean update, Scope sc, Callable blame) { 20 | if (!(x instanceof BQNObj)) throw new DomainError("Expected to assign to a namespace", blame); 21 | BQNObj ns = (BQNObj) x; 22 | for (int i = 0; i < keys.length; i++) { 23 | vals[i].set(ns.getChk(keys[i].asString()), update, sc, blame); 24 | } 25 | } 26 | 27 | public boolean seth(Value x, Scope sc) { 28 | if (!(x instanceof BQNObj)) throw new DomainError("Expected to assign to a namespace"); 29 | BQNObj ns = (BQNObj) x; 30 | for (int i = 0; i < keys.length; i++) { 31 | Value key = keys[i]; 32 | Value val = ns.get(key); 33 | if (val == null) return false; 34 | if (!vals[i].seth(val, sc)) return false; 35 | } 36 | return true; 37 | } 38 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/SimpleMap.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.errors.SyntaxError; 4 | import BQN.tools.FmtInfo; 5 | import BQN.types.*; 6 | import BQN.types.arrs.ChrArr; 7 | 8 | public abstract class SimpleMap extends BQNObj { 9 | public Value get(Value k) { 10 | return getv(k.asString()); 11 | } 12 | 13 | public abstract Value getv(String s); 14 | public abstract void setv(String s, Value v); 15 | 16 | public void set(Value k, Value v) { 17 | setv(k.asString(), v); 18 | } 19 | 20 | public Value[][] kvPair() { 21 | throw new SyntaxError("getting entries of "+this); 22 | } 23 | 24 | public int size() { 25 | throw new SyntaxError("getting size of "+this); 26 | } 27 | 28 | public boolean eq(Value o) { 29 | return this==o; 30 | } 31 | 32 | public int hashCode() { 33 | return 0; 34 | } 35 | 36 | public Value pretty(FmtInfo f) { 37 | return new ChrArr(ln(f)); 38 | } 39 | } -------------------------------------------------------------------------------- /src/BQN/types/mut/Variable.java: -------------------------------------------------------------------------------- 1 | package BQN.types.mut; 2 | 3 | import BQN.Scope; 4 | import BQN.errors.*; 5 | import BQN.types.*; 6 | 7 | public class Variable extends Settable { 8 | 9 | public final String name; 10 | 11 | public Variable(String name) { 12 | this.name = name; 13 | } 14 | 15 | public Value get(Scope sc) { 16 | Value got = sc.get(name); 17 | if (got == null) throw new ValueError("getting value of non-existing variable \""+name+"\""); 18 | return got; 19 | } 20 | 21 | public void set(Value x, boolean update, Scope sc, Callable blame) { 22 | if (update) { 23 | sc.update(name, x); 24 | } else { 25 | if (sc.varMap().containsKey(name)) throw new SyntaxError("Cannot redefine \""+name+"\"", blame); 26 | sc.set(name, x); 27 | } 28 | } 29 | 30 | public boolean seth(Value x, Scope sc) { 31 | sc.set(name, x); 32 | return true; 33 | } 34 | 35 | public String name(Scope sc) { 36 | return name; 37 | } 38 | protected boolean hasName() { 39 | return true; 40 | } 41 | 42 | public String toString() { 43 | return "var("+name+")"; 44 | } 45 | } -------------------------------------------------------------------------------- /test/assignment: -------------------------------------------------------------------------------- 1 | a↩6 # err 2 | a←1⋄a←5 # err 3 | a←1⋄a↩6⋄a # 6 4 | 5 | 2←2 # err 6 | a‿2←2‿5 # err 7 | 8 | a‿b←1 # err 9 | ⟨a⟩←1 # err 10 | a←b←1 ⋄ a‿b⊢←1 # err 11 | 12 | ⟨a‿b,c⟩‿d←⟨1‿2,3⟩‿4 ⋄ a‿b‿c‿d # 1‿2‿3‿4 13 | ⟨a‿b,c⟩‿d←⟨1‿2,3⟩‿4 ⋄ ⟨a‿b,c⟩‿d+↩1 ⋄ a‿b‿c‿d # 2‿3‿4‿5 14 | a‿b‿c‿d←↕4 ⋄ ⟨a‿b,c⟩‿d↩⟨4‿5,6⟩‿7 ⋄ a‿b‿c‿d # 4‿5‿6‿7 15 | 16 | 17 | a+a←4 # 8 18 | a×b+a‿b←10‿1 # 110‿20 19 | 20 | 21 | a+↩5 # err 22 | a←1⋄a+↩5 # 6 23 | a←1⋄a+↩5⋄a # 6 24 | a←1⋄a+a+↩4 # 10 25 | 26 | b←1 ⋄ {F←{b+𝕩} ⋄ r←F⎊'e' 𝕩 ⋄ b←10 ⋄ r∾F⎊'e' 𝕩}0 # 'e'‿10 -------------------------------------------------------------------------------- /test/eq: -------------------------------------------------------------------------------- 1 | # mixed 2 | ≡´⟨+,1⟩ # 0 3 | ≡´⟨¨,1⟩ # 0 4 | ≡´⟨⚇,1⟩ # 0 5 | ≡´⟨+,⚇⟩ # 0 6 | ≡´⟨¨,⚇⟩ # 0 7 | ≡´⟨+,¨⟩ # 0 8 | 9 | # fns 10 | ≡´⟨+,+⟩ # 1 11 | ≡´⟨+,-⟩ # 0 12 | F←{𝕩} ⋄ f≡f # 1 13 | F←{𝕩} ⋄ G←{𝕩} ⋄ f≡g # 0 14 | 15 | 16 | # trains 17 | ≡´⟨+-×,+-×⟩ # 1 18 | ≡´⟨+-×,+-÷⟩ # 0 19 | ≡´⟨+-×,++×⟩ # 0 20 | ≡´⟨+-×,--×⟩ # 0 21 | ≡´⟨+-,+-⟩ # 1 22 | ≡´⟨+-,--⟩ # 0 23 | ≡´⟨+-,++⟩ # 0 24 | ≡´⟨·+-,+-⟩ # 1 25 | 26 | # 1-modifiers 27 | ≡´⟨¨,¨⟩ # 1 28 | ≡´⟨˝,´⟩ # 0 29 | ≡´⟨-´,-´⟩ # 1 30 | ≡´⟨-´,-˝⟩ # 0 31 | ≡´⟨+¨,-¨⟩ # 0 32 | _f←{𝔽𝕩} ⋄ f≡f # 1 33 | _f←{𝔽𝕩} ⋄ _g←{𝔽𝕩} ⋄ f≡g # 0 34 | 35 | # 2-modifiers 36 | ≡´⟨∘,∘⟩ # 1 37 | ≡´⟨∘,⟜⟩ # 0 38 | ≡´⟨-∘+,-∘+⟩ # 1 39 | ≡´⟨-∘+,-⟜+⟩ # 0 40 | ≡´⟨-∘+,+∘+⟩ # 0 41 | ≡´⟨-∘+,-∘-⟩ # 0 42 | ≡´⟨-∘+,-(∘+)⟩ # 1 43 | ≡´⟨-∘+,-(⟜+)⟩ # 0 44 | ≡´⟨-∘+,-(∘-)⟩ # 0 45 | ≡´⟨-∘+,+(∘+)⟩ # 0 46 | ≡´⟨∘+,∘+⟩ # 1 47 | ≡´⟨∘+,⟜+⟩ # 0 48 | ≡´⟨∘+,∘-⟩ # 0 49 | _f_←{𝔽𝔾𝕩} ⋄ f≡f # 1 50 | _f_←{𝔽𝔾𝕩} ⋄ _g_←{𝔽𝔾𝕩} ⋄ f≡g # 0 51 | _f_←{𝔽𝔾𝕩} ⋄ ≡´⟨_f_-,_f_-⟩ # 1 52 | _f_←{𝔽𝔾𝕩} ⋄ ≡´⟨_f_-,_f_+⟩ # 0 53 | _f_←{𝔽𝔾𝕩} ⋄ _g_←{𝔽𝔾𝕩} ⋄ ≡´⟨_f_-,_g_-⟩ # 0 -------------------------------------------------------------------------------- /test/export: -------------------------------------------------------------------------------- 1 | 2 | # basic blocks 3 | {b←1 ⋄ a⇐b}.a # 1 4 | {b←1 ⋄ a⇐b}.b # err 5 | {x‿y⇐5‿6}.x # 5 6 | {x‿y⇐5‿6}.y # 6 7 | 8 | # functions/modifiers 9 | ({b←𝕩 ⋄ a⇐b ⋄ c⇐10} 5).c # 10 10 | ({b←𝕩 ⋄ a⇐b ⋄ c⇐10} 5).b # err 11 | {b←𝕩 ⋄ a⇐b ⋄ c←1 ⋄ c⇐10} 5 # err 12 | {𝕩⇐1} # err 13 | {𝕗⇐1} # err 14 | {𝕣⇐1} # err 15 | 16 | # export lines 17 | ({𝕊a‿b: a⇐} 5‿6).a # 5 18 | ({𝕊a‿b: a⇐} 5‿6).b # err 19 | ({𝕊a‿b: a‿b⇐} 5‿6).a # 5 20 | ({𝕊a‿b: a‿b⇐} 5‿6).b # 6 21 | {⇐x} # err 22 | a←1 ⋄ {a⇐} # err 23 | 24 | 25 | { ⋄ b‿c⇐ ⋄ a⇐2 ⋄ b←1+a ⋄ F←{b+↩1} ⋄ c←b‿"str" ⋄ } -------------------------------------------------------------------------------- /test/namespaces: -------------------------------------------------------------------------------- 1 | 2 | ⟨a, b, c⟩ ← {a⇐1 ⋄ b⇐2 ⋄ c⇐"ab"} ⋄ a‿b‿c # 1‿2‿"ab" 3 | ⟨a, b, c, d⟩ ← {a⇐1 ⋄ b⇐2 ⋄ c⇐"ab"} ⋄ err 4 | ⟨alias⇐a, b, c0‿c1⇐c⟩ ← {a⇐1 ⋄ b⇐2 ⋄ c⇐"ab"} ⋄ alias‿b‿c0‿c1 # 1‿2‿'a'‿'b' 5 | ⟨⟩ ← {a⇐1 ⋄ b⇐2 ⋄ c⇐"ab"} ⋄ 1 # 1 6 | ⟨d⟩ ← {a⇐1 ⋄ b⇐2 ⋄ c⇐"ab"} ⋄ 1 # err 7 | 8 | {⟨a⟩:a+1; 0} {a⇐10} # 11 9 | {⟨a⟩:a+1; 0} {b⇐10} # 0 10 | {⟨al⇐a⟩:al+1; 0} {a⇐10} # 11 11 | {⟨al⇐a⟩:al+1; 0} {b⇐10} # 0 12 | 10{𝕨𝕊⟨⟩: 𝕨+1} {a⇐10} # 11 -------------------------------------------------------------------------------- /test/shape: -------------------------------------------------------------------------------- 1 | # sanity check 2 | 2‿3⥊↕4 # >⟨0‿1‿2,3‿0‿1⟩ 3 | 5⥊3 # 3‿3‿3‿3‿3 4 | 3⥊↕10 # 0‿1‿2 5 | 5⥊1‿2 # 1‿2‿1‿2‿1 6 | ⟨⟩⥊1‿2‿3 # <1 7 | 8 | # general 9 | ∘‿0⥊↕10 # err 10 | ⌊‿0⥊↕10 # err 11 | ↑‿0⥊↕10 # err 12 | ⌽‿0⥊↕10 # err 13 | ⟨∘⟩⥊2‿3‿4⥊↕24 # ↕24 14 | ⟨⌊⟩⥊2‿3‿4⥊↕24 # ↕24 15 | ⟨↑⟩⥊2‿3‿4⥊↕24 # ↕24 16 | ⟨⌽⟩⥊2‿3‿4⥊↕24 # ↕24 17 | 2‿∘‿4⥊↕24 # 2‿3‿4⥊↕24 18 | 2‿⌊‿4⥊↕24 # 2‿3‿4⥊↕24 19 | 2‿↑‿4⥊↕24 # 2‿3‿4⥊↕24 20 | 2‿⌽‿4⥊↕24 # 2‿3‿4⥊↕24 21 | ⟨∘⟩⥊⟨⟩ # ⟨⟩ 22 | ⟨⌊⟩⥊⟨⟩ # ⟨⟩ 23 | ⟨↑⟩⥊⟨⟩ # ⟨⟩ 24 | ⟨⌽⟩⥊⟨⟩ # ⟨⟩ 25 | 26 | # ∘ 27 | ∘‿2⥊↕10 # 5‿2⥊↕10 28 | 2‿∘⥊↕10 # 2‿5⥊↕10 29 | ∘‿2⥊↕9 # err 30 | ∘‿1⥊3 # 1‿1⥊3 31 | ∘‿2⥊3 # err 32 | ∘‿3⥊⟨⟩ # 0‿3⥊⟨⟩ 33 | 34 | # ↑ 35 | ↑‿3⥊↕4 # 2‿3⥊0‿1‿2‿3‿0‿0 36 | ↑‿3⥊⟨⟩ # 0‿3⥊⟨⟩ 37 | ↑‿3⥊4 # 1‿3⥊4‿0‿0 38 | ↑‿3⥊<¨↕10 # 4‿3⥊12↑<¨↕10 # whatever that is.. 39 | 40 | # ⌊ 41 | ⌊‿4⥊↕10 # 2‿4⥊↕10 42 | ⌊‿5⥊↕10 # 2‿5⥊↕10 43 | ⌊‿5⥊↕3 # 0‿5⥊0 44 | ⌊‿5⥊0 # 0‿5⥊0 45 | 46 | # ⌽ 47 | ⌽‿3⥊↕10 # 4‿3⥊↕10 48 | 3‿⌽⥊↕10 # 3‿4⥊↕10 49 | 10‿⌽⥊↕3 # 10‿1⥊↕3 -------------------------------------------------------------------------------- /test/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dbqn 2 | eval ← (1≤≠)◶{𝕩:•BQN}‿{⍎⊑𝕩}•args # use 1st argument as the interpreter 3 | err←"err" 4 | { 𝕊path: 5 | lns ← ('#'⊸∊¨∧'#'≠(⊑1↑⊢)¨)⊸/ •FLines path 6 | 7 | msgs←∾{ 8 | p←⊑𝕩⊐'#' 9 | src ← p↑𝕩 10 | src ↩ {𝕩/˜¬∧`⌾⌽' '=𝕩} src 11 | got ← Eval⎊"err" src 12 | exp ← ⍎(p+1)↓𝕩 13 | got ≡◶{⟨"`"∾src∾"`: got "∾𝕨∾", expected "∾𝕩⟩}‿⟨⟩○(1⊸⍕) exp 14 | }¨ lns 15 | (0=≠)◶{𝕩:•Out path∾": "∾(⍕lns-○≠msgs)∾" / "∾⍕≠lns}‿{𝕩:•Out path∾": Passed all "∾(⍕≠lns)∾" tests"} msgs 16 | {•Out" "∾𝕩}¨msgs 17 | }¨ •path⊸∾¨ ⟨"assignment","headers","shape","eq","export","namespaces","tk"⟩ -------------------------------------------------------------------------------- /test/tk: -------------------------------------------------------------------------------- 1 | # numbers 2 | 12.0 ≡ ⍎"12" # 1 3 | 12.0 ≡ ⍎"12e0" # 1 4 | 12.0 ≡ ⍎"12." # 1 5 | 12.0 ≡ ⍎"12.e0" # 1 6 | 12.0 ≡ ⍎"1.2e1" # 1 7 | 12.0 ≡ ⍎".12e2" # 1 8 | 0.12 ≡ ⍎".12" # 1 9 | 0.0 ≡ ⍎"0" # 1 10 | 0.0 ≡ ⍎"0e¯9" # 1 11 | 0.0 ≡ ⍎"0e0" # 1 12 | 0.0 ≡ ⍎"0e9" # 1 13 | 0.0 ≡ ⍎"0." # 1 14 | 0.0 ≡ ⍎".0" # 1 15 | (-12.0) ≡ ⍎"¯12" # 1 16 | (-12.0) ≡ ⍎"¯12.0" # 1 17 | (-12.0) ≡ ⍎"¯1.2e1" # 1 18 | (-0.12) ≡ ⍎"¯1.2e¯1" # 1 19 | (-10.0) ≡ ⍎"¯1e1" # 1 20 | 123 ≡ ⍎"12_3" # 1 21 | 1.23 ≡ ⍎"1.2_3" # 1 22 | ⍎"2e" # err 23 | ⍎"2.e" # err 24 | ⍎"2.0e" # err 25 | ⍎"2e¯" # err 26 | ⍎"2.e¯" # err 27 | ⍎"2.0e¯" # err 28 | ⍎"¯" # err 29 | 30 | # characters 31 | ⍎"'4'" # '4' 32 | ⍎"'45'" # err 33 | ⍎"'45' "# err 34 | ⍎"'𝕩'" # err 35 | ⍎"'4" # err 36 | ⍎"'" # err 37 | ⍎"𝕒" # err 38 | ⍎¯1↓"𝕩" # err 39 | ⍎1↓"𝕩" # err 40 | 41 | # bigints 42 | (•Big 5) ≡ ⍎ "5L" # 1 43 | (•Big 123456) ≡ ⍎ "123_456L" # 1 44 | (•Big -5) ≡ ⍎"¯5L" # 1 45 | (1+×´10⥊•Big 2*10) ≡ ⍎"1267650600228229401496703205377L" # 1 46 | 47 | # strands 48 | ⍎"1‿2" # ⟨1,2⟩ 49 | ⍎"1‿2‿3" # ⟨1,2,3⟩ 50 | ⍎"1‿2‿" # err 51 | ⍎"‿2‿3" # err 52 | ⍎"1‿‿2" # err 53 | ⍎"‿" # err 54 | ⍎"1‿←‿2" # err 55 | ⍎"1‿↩‿2" # err 56 | ⍎"⟨1,‿,2⟩"# err 57 | ⍎"⟨1,2,⟩" # ⟨1,2⟩ 58 | ⍎"⟨,1,2⟩" # ⟨1,2⟩ 59 | ⍎"⟨1,,2⟩" # ⟨1,2⟩ 60 | ⍎"+⟜1‿2‿3 40‿50‿60" # ⟨41,52,63⟩ 61 | 62 | # variables 63 | a←3 ⋄ _A_ # 3 64 | ab←1 ⋄ 1+a_B # 2 -------------------------------------------------------------------------------- /test/types: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env dbqn 2 | 3 | EQ ← ≡○•HASH # not using just ≡ because NaN is annoying 4 | 5 | T ← EQ◶{•←"Expected `"∾(1⍕𝕨)∾"` and `"∾(1⍕𝕩)∾"` to be equal"}‿⟨⟩ 6 | 7 | CL ← {𝕩↑˜⊑𝕩⊐'.'}⌾⌽ •Class 8 | 9 | "BitArr"T CL 0‿1 10 | "BitArr"T CL 10•DR 0‿1 11 | "IntArr"T CL 12•DR 0‿1 12 | "DoubleArr"T CL 11•DR 0‿1 13 | 14 | Tps ← { 15 | r ← ⟨11•DR 𝕩⟩ 16 | r∾↩ 𝕨◶{<12•DR 𝕩}‿{<12•DR 𝕩}‿{(∧´0=1|𝕩)◶⟨⟩‿{<12•DR 𝕩}𝕩} 𝕩 17 | r∾↩ 𝕨◶⟨⟩ ‿{<10•DR 𝕩}‿{(∧´ 𝕩∊↕2)◶⟨⟩‿{<10•DR 𝕩}𝕩} 𝕩 18 | (⊢≡1⌽⊢)◶{𝕩:•←"failed type conversion"}‿⟨⟩ r 19 | r 20 | } 21 | 22 | 23 | •rl←0 24 | a0_1 ← 1 Tps •Rand 200⥊2 25 | b0_1 ← 1 Tps •Rand 200⥊2 26 | ma ← ⟨a0_1 ⋄ 2 Tps 5+•Rand 200⥊10⟩ 27 | ta ← (∾ma) ∾ 2 Tps 5.5+•Rand 200⥊10 28 | 29 | scd ← "⋆⁼"<⊸∾ "+-×÷|<≤=≥>≠⋆∨∧⌊⌈√¬" 30 | _err ← { Fn _𝕣: 31 | # Fn⎊{•←"ERROR "∾(1⍕fn)∾": "∾(" "∾1⍕𝕨)⊢⊘∾" 𝕊 "∾1⍕𝕩 ⋄ "err"} 32 | Fn⎊"err" 33 | } 34 | # dyadic AA 35 | { 𝕊 f: 36 | Fc ← F _err 37 | r ← a0_1 Fc⌜ b0_1 38 | c ← r EQ¨ <⊑r 39 | ∧´∘⥊◶{•←(1⍕f)∾": failed AA"∾∾' '∾¨∾¨<˘1⍕¨𝕩}‿1 c 40 | }¨⍎¨ scd ∾ "/∊∾≍⊔" 41 | 42 | 43 | # dyadic As&sA vs AA 44 | { 𝕊 f: 45 | { 𝕊 dir: 46 | Fc ← (dir⊑⟨F⋄F˜⟩) _err 47 | { 𝕊s: 48 | { 𝕊ca: 49 | a ← (≠ca) ⥊ s 50 | (a EQ○(ca⊸Fc) s)◶{𝕩:•←(1⍕f)∾": failed scalar "∾(dir⊑"𝕩"‿"𝕨")∾" ≡ "∾1⍕s}‿⟨⟩ 0 51 | }¨ ta 52 | }¨ 0‿1‿2‿2.5 53 | }¨ 0‿1 54 | }¨⍎¨ scd 55 | 56 | # dyadic As & sA vs different types 57 | { 𝕊 f: 58 | { 𝕊 dir: 59 | Fc ← (dir⊑⟨F⋄F˜⟩) _err 60 | ma { a 𝕊 s: 61 | r ← a Fc¨ s 62 | c ← r EQ¨ <⊑r 63 | ∧´◶{𝕩:•←(1⍕f)∾": failed scalar "∾(dir⊑"𝕩"‿"𝕨")∾" ≡ "∾(1⍕s)∾"; "∾(dir⊑"𝕨"‿"𝕩")∾" is"∾ ∾' '∾¨ c ¬⊸/ CL¨ a}‿1 c 64 | }⌜ 0‿1‿2‿2.5 65 | }¨ 0‿1 66 | }¨⍎¨ scd 67 | 68 | # monadic 69 | { 𝕊 f: 70 | Fc ← F _err 71 | { 𝕊 a: 72 | (a EQ○Fc 11•DR a)◶{𝕩:•←(1⍕f)∾": failed monadic "∾CL a}‿⟨⟩ 0 73 | }¨ ta 74 | }¨⟨ 75 | 9⊸↑, 1000⊸↑ ⋄ ¯9⊸↑, ¯1000⊸↑ 76 | 9⊸↓, 1000⊸↓ ⋄ ¯9⊸↓, ¯1000⊸↓ 77 | 0⊸∾, 1⊸∾, 2⊸∾, 2.5⊸∾ ⋄ ∾⟜0, ∾⟜1, ∾⟜2, ∾⟜2.5 78 | 4‿5⊸⥊, 100‿100⊸⥊, 20⊸⥊, 10⊸⥊, 1000⊸⥊ 79 | ⍉4‿5⊸⥊ ⋄ <˘4‿5⊸⥊ ⋄ {><˘4‿5⥊𝕩} 80 | 10⊸⊑ ⋄ (⥊¨3‿4)⊸⊑ ⋄ 3⊸⊏ ⋄ 3‿4⊸⊏ ⋄ 10‿10⊸⥊ ⋄ ⊏⟜(↕20) ⋄ (↕20)⊸⊏ ⋄ (⌽↕20)⊸⊏ 81 | ⥊, ⌽, /, ∊, ⍷, ⍋, ⍒, ⊔ 82 | +´, ×´, ⌊´, ⌈´, ∨´, ∧´, ≠´ 83 | +`, ×`, ⌊`, ⌈`, ∨`, ∧`, ≠` 84 | ⟩ ∾ ⍎¨ "+-×÷|=≠⋆∨∧⌊⌈√¬" --------------------------------------------------------------------------------