├── .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 | ⟩ ∾ ⍎¨ "+-×÷|=≠⋆∨∧⌊⌈√¬"
--------------------------------------------------------------------------------