├── proto ├── APLP5 ├── code │ └── .thisisafolder ├── data │ ├── drawgolfed │ ├── draw │ ├── iKeExample │ ├── multTable │ ├── rects │ └── ma ├── example.pde ├── Img.pde ├── Mouse.pde └── APLP5.pde ├── APL ├── app ├── err ├── APLApp │ ├── data │ │ └── APL385+.ttf │ ├── code │ │ └── sketch.properties │ ├── stuff.pde │ └── AndroidManifest.xml ├── APL │ └── build ├── build8 ├── readme.md └── convert.py ├── docs ├── l1.png ├── p1.png ├── p2.png └── chars.txt ├── REPL ├── AndroidIDE ├── sketch.properties ├── data │ ├── APL385+.ttf │ ├── Ldef.txt │ ├── help_kb.txt │ ├── def │ ├── help_c.txt │ └── parse.js ├── code │ └── sketch.properties ├── TextReciever.pde ├── AndroidManifest.xml ├── readme.md ├── Drawable.pde ├── GUI.pde └── ROText.pde ├── fds ├── src └── APL │ ├── types │ ├── Tokenable.java │ ├── dimensions │ │ ├── DimMFn.java │ │ ├── DimMMop.java │ │ ├── DimDFn.java │ │ ├── DimDMop.java │ │ ├── DimMDop.java │ │ ├── DimDDop.java │ │ ├── Pick.java │ │ ├── DervDimMop.java │ │ ├── DervDimDop.java │ │ ├── Brackets.java │ │ └── DervDimFn.java │ ├── Callable.java │ ├── functions │ │ ├── Builtin.java │ │ ├── builtins │ │ │ ├── AbstractSet.java │ │ │ ├── fns │ │ │ │ ├── TallyBuiltin.java │ │ │ │ ├── FormatBuiltin.java │ │ │ │ ├── UShoeBuiltin.java │ │ │ │ ├── GradeDownBuiltin.java │ │ │ │ ├── LTackBuiltin.java │ │ │ │ ├── RTackBuiltin.java │ │ │ │ ├── CommaBarBuiltin.java │ │ │ │ ├── GradeUpBuiltin.java │ │ │ │ ├── DShoeBuiltin.java │ │ │ │ ├── GEBuiltin.java │ │ │ │ ├── LEBuiltin.java │ │ │ │ ├── SquadBuiltin.java │ │ │ │ ├── FlipBuiltin.java │ │ │ │ ├── LShoeStileBuiltin.java │ │ │ │ ├── DepthBuiltin.java │ │ │ │ ├── ExpandBuiltin.java │ │ │ │ ├── EvalBuiltin.java │ │ │ │ ├── CeilingBuiltin.java │ │ │ │ ├── FloorBuiltin.java │ │ │ │ ├── GTBuiltin.java │ │ │ │ ├── LTBuiltin.java │ │ │ │ ├── EllipsisBuiltin.java │ │ │ │ ├── SemiUBBuiltin.java │ │ │ │ ├── PlusBuiltin.java │ │ │ │ ├── EQBuiltin.java │ │ │ │ ├── NEBuiltin.java │ │ │ │ ├── MinusBuiltin.java │ │ │ │ ├── MergeBuiltin.java │ │ │ │ ├── DivBuiltin.java │ │ │ │ ├── RootBuiltin.java │ │ │ │ ├── TransposeBuiltin.java │ │ │ │ ├── OrBuiltin.java │ │ │ │ ├── AndBuiltin.java │ │ │ │ ├── RShoeUBBuiltin.java │ │ │ │ ├── RandBuiltin.java │ │ │ │ ├── FindBuiltin.java │ │ │ │ ├── StarBuiltin.java │ │ │ │ ├── LShoeBuiltin.java │ │ │ │ ├── NorBuiltin.java │ │ │ │ ├── NandBuiltin.java │ │ │ │ ├── ExclBuiltin.java │ │ │ │ ├── RShoeBuiltin.java │ │ │ │ ├── EpsilonBuiltin.java │ │ │ │ └── TildeBuiltin.java │ │ │ ├── dops │ │ │ │ ├── DotBuiltin.java │ │ │ │ ├── JotUBBuiltin.java │ │ │ │ ├── ObverseBuiltin.java │ │ │ │ ├── JotDiaeresisBuiltin.java │ │ │ │ ├── CRepeatBuiltin.java │ │ │ │ ├── OverBuiltin.java │ │ │ │ ├── DualBuiltin.java │ │ │ │ └── JotBuiltin.java │ │ │ ├── DerivedSet.java │ │ │ ├── QuoteQuad.java │ │ │ ├── Quad.java │ │ │ ├── mops │ │ │ │ ├── EachLeft.java │ │ │ │ ├── EachRight.java │ │ │ │ ├── SelfieBuiltin.java │ │ │ │ ├── InvertBuiltin.java │ │ │ │ ├── ScanBuiltin.java │ │ │ │ ├── ObliqueBuiltin.java │ │ │ │ └── TableBuiltin.java │ │ │ └── SetBuiltin.java │ │ ├── FunArr.java │ │ ├── ArrFun.java │ │ ├── userDefined │ │ │ ├── UserDefined.java │ │ │ ├── Dfn.java │ │ │ ├── Dmop.java │ │ │ └── Ddop.java │ │ ├── DerivedMop.java │ │ ├── DerivedDop.java │ │ ├── trains │ │ │ ├── Fork.java │ │ │ └── Atop.java │ │ ├── Mop.java │ │ └── Dop.java │ ├── Null.java │ ├── Settable.java │ ├── Variable.java │ ├── SimpleMap.java │ ├── arrs │ │ ├── Rank0Arr.java │ │ ├── Shape1Arr.java │ │ ├── ChrArr.java │ │ ├── EmptyArr.java │ │ └── HArr.java │ ├── Primitive.java │ ├── APLMap.java │ ├── Char.java │ ├── Obj.java │ └── StrMap.java │ ├── errors │ ├── IncorrectArgsError.java │ ├── NotErrorError.java │ ├── ValueError.java │ ├── DomainError.java │ ├── NYIError.java │ ├── RankError.java │ ├── LengthError.java │ ├── SyntaxError.java │ ├── ImplementationError.java │ └── APLError.java │ ├── Type.java │ ├── tokenizer │ ├── types │ │ ├── ScopeTok.java │ │ ├── DiamondTok.java │ │ ├── SetTok.java │ │ ├── ColonTok.java │ │ ├── SemiTok.java │ │ ├── CommentTok.java │ │ ├── DColonTok.java │ │ ├── OpTok.java │ │ ├── ErrTok.java │ │ ├── BigTok.java │ │ ├── BacktickTok.java │ │ ├── NameTok.java │ │ ├── StrTok.java │ │ ├── NumTok.java │ │ ├── ChrTok.java │ │ ├── BasicLines.java │ │ ├── DfnTok.java │ │ ├── ParenTok.java │ │ ├── TokArr.java │ │ ├── BracketTok.java │ │ └── LineTok.java │ └── Token.java │ └── SimpleIndexer.java ├── .gitignore ├── readme.md └── LICENSE /proto: -------------------------------------------------------------------------------- 1 | proto←{⊃0⍴⊂⍵} 2 | -------------------------------------------------------------------------------- /APLP5/code/.thisisafolder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /APL: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | java -jar APL.jar "$@" -------------------------------------------------------------------------------- /app/err: -------------------------------------------------------------------------------- 1 | APL/build: line 4: cd: src: No such file or directory 2 | -------------------------------------------------------------------------------- /docs/l1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/APL/HEAD/docs/l1.png -------------------------------------------------------------------------------- /docs/p1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/APL/HEAD/docs/p1.png -------------------------------------------------------------------------------- /docs/p2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/APL/HEAD/docs/p2.png -------------------------------------------------------------------------------- /REPL: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rlwrap -s99999 -H.history java -ea -jar APL.jar "$@" -r -------------------------------------------------------------------------------- /AndroidIDE/sketch.properties: -------------------------------------------------------------------------------- 1 | mode=Android 2 | mode.id=processing.mode.android.AndroidMode 3 | -------------------------------------------------------------------------------- /fds: -------------------------------------------------------------------------------- 1 | fds ← { 2 | ⎕IO ← 0 3 | '|',⍨ '|', {⍺,'|',⍵}/{{⍺,' ',⍵}/⍕¨⍵}¨ ⍵∘{⍴(⊃⍣⍵)⍺}¨⍳≡⍵ 4 | } 5 | -------------------------------------------------------------------------------- /AndroidIDE/data/APL385+.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/APL/HEAD/AndroidIDE/data/APL385+.ttf -------------------------------------------------------------------------------- /app/APLApp/data/APL385+.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dzaima/APL/HEAD/app/APLApp/data/APL385+.ttf -------------------------------------------------------------------------------- /AndroidIDE/code/sketch.properties: -------------------------------------------------------------------------------- 1 | mode=Java 2 | component=app 3 | mode.id=processing.mode.java.JavaMode 4 | -------------------------------------------------------------------------------- /app/APLApp/code/sketch.properties: -------------------------------------------------------------------------------- 1 | mode=Java 2 | component=app 3 | mode.id=processing.mode.java.JavaMode 4 | -------------------------------------------------------------------------------- /APLP5/data/drawgolfed: -------------------------------------------------------------------------------- 1 | P←P5⋄P.size←,⍨700⋄G←P.G⋄a←l←⍬ 2 | P.draw←{G.bg'd'⋄G.stroke←9 3 | {P.LM.P:←l,←P.mpos 4 | ×≢l:a⊢←⍵⋄l⊢←⍬}G.ln a,⊂l} 5 | P.kp←{a↓⍨←-×≢a} -------------------------------------------------------------------------------- /src/APL/types/Tokenable.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public interface Tokenable { 6 | Token getToken(); 7 | } -------------------------------------------------------------------------------- /app/APL/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -f APL.jar 3 | rm -rf src/build/APL 4 | cd src 5 | mkdir -p build 6 | javac -Xmaxerrs 1000 -d ./build $(find APL -name '*.java') -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimMFn.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.Value; 4 | 5 | public interface DimMFn { 6 | Value call (Value w, int dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimMMop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.*; 4 | 5 | public interface DimMMop { 6 | Value call (Obj aa, Value w, int dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimDFn.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.Value; 4 | 5 | public interface DimDFn { 6 | Value call (Value a, Value w, DervDimFn dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimDMop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.*; 4 | 5 | public interface DimDMop { 6 | Value call (Obj aa, Value a, Value w, int dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimMDop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.*; 4 | 5 | public interface DimMDop { 6 | Value call (Obj aa, Obj ww, Value w, int dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DimDDop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.types.*; 4 | 5 | public interface DimDDop { 6 | Value call (Obj aa, Obj ww, Value a, Value w, int dim); 7 | } -------------------------------------------------------------------------------- /src/APL/types/Callable.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.Scope; 4 | 5 | public abstract class Callable extends Obj { 6 | final public Scope sc; 7 | protected Callable(Scope sc) { 8 | this.sc = sc; 9 | } 10 | } -------------------------------------------------------------------------------- /src/APL/errors/IncorrectArgsError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class IncorrectArgsError extends APLError { 6 | public IncorrectArgsError(String s, Callable fun, Tokenable cause) { 7 | super(s, fun, cause); 8 | } 9 | } -------------------------------------------------------------------------------- /AndroidIDE/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 | -------------------------------------------------------------------------------- /src/APL/errors/NotErrorError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.Obj; 4 | 5 | public class NotErrorError extends APLError { 6 | 7 | public NotErrorError(String msg, Obj cause) { 8 | super(msg); 9 | this.cause = cause; 10 | } 11 | } -------------------------------------------------------------------------------- /src/APL/Type.java: -------------------------------------------------------------------------------- 1 | package APL; 2 | 3 | public enum Type { 4 | array('N'), var('V'), nul('V'), gettable('#'), 5 | fn('F'), mop('M'), dop('D'), 6 | set('←'), dim('@'); 7 | 8 | public final char chr; 9 | 10 | Type(char chr) { 11 | this.chr = chr; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/types/functions/Builtin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.Scope; 4 | import APL.types.Fun; 5 | 6 | public abstract class Builtin extends Fun { 7 | protected Builtin(Scope sc) { 8 | super(sc); 9 | } 10 | protected Builtin() { 11 | super(null); 12 | } 13 | } -------------------------------------------------------------------------------- /AndroidIDE/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| | | -------------------------------------------------------------------------------- /src/APL/tokenizer/types/ScopeTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.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/APL/tokenizer/types/DiamondTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.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 null; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/SetTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class SetTok extends Token { 6 | public SetTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return "←"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/ColonTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class ColonTok extends Token { 6 | public ColonTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return ":"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/SemiTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class SemiTok extends Token { 6 | public SemiTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return ";"; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/CommentTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.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 null; 12 | } 13 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/DColonTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class DColonTok extends Token { 6 | public DColonTok(String line, int spos, int epos) { 7 | super(line, spos, epos); 8 | } 9 | 10 | @Override public String toRepr() { 11 | return "::"; 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | APL.jar 2 | out 3 | src/build 4 | 5 | .idea 6 | APL.iml 7 | .history 8 | 9 | 10 | app/APL/src/ 11 | app/build/ 12 | app/APLApp/android/ 13 | APLP5/code/APL8.jar 14 | app/APLApp/code/APL8\.jar 15 | AndroidIDE/code/APL8\.jar 16 | AndroidIDE/data/temp/ 17 | AndroidIDE/android/ 18 | app/err 19 | *.apk 20 | AndroidIDE/build/ 21 | 22 | 23 | -------------------------------------------------------------------------------- /APLP5/data/draw: -------------------------------------------------------------------------------- 1 | P5.size ← 500 500 2 | G ← P5.G 3 | all ← ⍬ 4 | ln ← ⍬ 5 | P5.draw ← { 6 | G.bg 'd2' 7 | G.stroke ← 'f00' 8 | P5.lm.p: ln,←P5.mpos 9 | G.fill ← '6' 10 | 3 G.line all,⊂ln 11 | } 12 | P5.LM.r ← { 13 | all,←⊂ln 14 | ln⊢← ⍬ 15 | } 16 | P5.kp ← { 17 | "Escape"≡⍵: P5.exit 0 18 | (×≢all) ∧ 1 0 0 0 0 'z'≡⍺,⍵: all⊢←¯1↓all 19 | } -------------------------------------------------------------------------------- /src/APL/errors/ValueError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class ValueError extends APLError { 6 | public ValueError(String s) { 7 | super(s); 8 | } 9 | public ValueError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public ValueError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | } -------------------------------------------------------------------------------- /app/build8: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -f APLApp/code/APL8.jar 3 | cd APL 4 | rm -rf src/build/APL 5 | cd src 6 | mkdir -p build 7 | javac -Xmaxerrs 1000 --release 8 -d ./build $(find APL -name '*.java') 8 | cd build 9 | jar cvfe APL.jar APL.Main * > /dev/null 10 | cp APL.jar ../../../APLApp/code/APL8.jar 11 | cp APL.jar ../../../../AndroidIDE/code/APL8.jar 12 | mv APL.jar ../../../../APLP5/code/APL8.jar -------------------------------------------------------------------------------- /src/APL/errors/DomainError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class DomainError extends APLError { 6 | public DomainError(String s) { 7 | super(s); 8 | } 9 | public DomainError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public DomainError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | } -------------------------------------------------------------------------------- /src/APL/errors/NYIError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class NYIError extends APLError { // AKA LazyError 6 | public NYIError(String s) { 7 | super(s); 8 | } 9 | public NYIError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public NYIError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | } -------------------------------------------------------------------------------- /src/APL/errors/RankError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class RankError extends APLError { 6 | // public RankError(String s) { 7 | // super(s); 8 | // } 9 | public RankError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public RankError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | } -------------------------------------------------------------------------------- /src/APL/errors/LengthError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class LengthError extends APLError { 6 | // public LengthError(String s) { 7 | // super(s); 8 | // } 9 | public LengthError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public LengthError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/OpTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class OpTok extends Token { 6 | public final String op; 7 | 8 | public OpTok(String line, int spos, int epos, String op) { 9 | super(line, spos, epos); 10 | 11 | this.op = op; 12 | } 13 | 14 | @Override public String toRepr() { 15 | return op; 16 | } 17 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/ErrTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class ErrTok extends Token { 6 | public ErrTok(String raw, int spos, int epos) { 7 | super(raw, spos, epos); 8 | } 9 | public ErrTok(String raw, int onepos) { 10 | super(raw, onepos, onepos+1); 11 | } 12 | 13 | @Override public String toRepr() { 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/BigTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | import APL.types.BigValue; 5 | 6 | public class BigTok extends Token { 7 | public final BigValue val; 8 | public BigTok(String line, int spos, int epos, BigValue val) { 9 | super(line, spos, epos); 10 | this.val = val; 11 | } 12 | @Override public String toRepr() { 13 | return source(); 14 | } 15 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/AbstractSet.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins; 2 | 3 | import APL.Type; 4 | import APL.types.*; 5 | 6 | public abstract class AbstractSet extends Callable { 7 | public AbstractSet() { 8 | super(null); 9 | } 10 | 11 | public abstract Obj callObj(Obj a, Obj w, boolean update); 12 | 13 | @Override 14 | public Type type() { 15 | return Type.set; 16 | } 17 | } -------------------------------------------------------------------------------- /AndroidIDE/data/help_kb.txt: -------------------------------------------------------------------------------- 1 | = - evaluate/save 2 | ⇧ - shift (caps letters, select with «») 3 | C - clear input field 4 | M - go to matching bracket 5 | 6 | K - open virtual keyboard 7 | # - default layout 8 | A - layout with a-z 9 | N - layout with numbers at top-level 10 | F - extra function layout 11 | X - close tab (saves where applicable) 12 | 13 | ↶↷ - undo/redo 14 | ▲▼ - move up/down or trough REPL history 15 | ^C/^V - copy/paste -------------------------------------------------------------------------------- /APLP5/data/iKeExample: -------------------------------------------------------------------------------- 1 | ⍝ idea stolen from https://github.com/JohnEarnest/ok/tree/gh-pages/ike 2 | ⎕IO←0 3 | P5.size ← 800 800 4 | G ← P5.G 5 | cols ← P5.col¨ '002b36' '073642' '586e75' '657b83' '839496' '93a1a1' 'eee8d5' 'fdf6e3' 'b58900' 'cb4b16' 'dc322f' 'd33682' '6c71c4' '268bd2' '2aa198' '859900' 6 | is ← ∘.{√ +/ ×⍨ ⍺,⍵}⍨⍳400 7 | P5.smooth←0 8 | P5.draw ← { 9 | (0 0,P5.size) G.img P5.img (⊖⍪⊢) (⌽,⊢) (16| ⌊ 4÷⍨is+P5.fc) ⊇ cols 10 | ⎕←P5.fps 11 | 0=60|P5.fc:⎕gc 12 | } -------------------------------------------------------------------------------- /APLP5/example.pde: -------------------------------------------------------------------------------- 1 | // example class for an APL object 2 | class Example extends SimpleMap { 3 | void setv(String k, Obj v) { 4 | String s = k.toLowerCase(); 5 | switch (s) { 6 | default: throw new DomainError("setting non-existing key "+s+" for ______"); 7 | } 8 | } 9 | Obj getv(String k) { 10 | String s = k.toLowerCase(); 11 | switch (s) { 12 | default: return NULL; 13 | } 14 | } 15 | String name() { return "______"; } 16 | } 17 | -------------------------------------------------------------------------------- /src/APL/errors/SyntaxError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class SyntaxError extends APLError { 6 | public SyntaxError(String s) { 7 | super(s); 8 | } 9 | public SyntaxError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public SyntaxError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | 16 | public static void must(boolean b, String msg) { 17 | if (!b) throw new SyntaxError(msg); 18 | } 19 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/BacktickTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class BacktickTok extends Token { 6 | private final LineTok val; 7 | 8 | public BacktickTok(String raw, int spos, int epos, Token val) { 9 | super(raw, spos, epos); 10 | this.val = LineTok.inherit(val); 11 | } 12 | 13 | @Override public String toRepr() { 14 | return "`" + val.toRepr(); 15 | } 16 | 17 | public LineTok value() { 18 | return val; 19 | } 20 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/NameTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | public class NameTok extends Token { 6 | public final String name; 7 | 8 | public NameTok(String line, int spos, int epos, String name) { 9 | super(line, spos, epos); 10 | this.name = name; 11 | } 12 | 13 | @Override public String toTree(String p) { 14 | return p+"name: " + name + "\n"; 15 | } 16 | 17 | @Override public String toRepr() { 18 | return name; 19 | } 20 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/TallyBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | public class TallyBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "≢"; 9 | } 10 | 11 | 12 | public Value call(Value w) { 13 | if (w.rank==0) return Num.ONE; 14 | return Num.of(w.shape[0]); 15 | } 16 | public Value call(Value a, Value w) { 17 | return a.equals(w)? Num.ZERO : Num.ONE; 18 | } 19 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/StrTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.Main; 4 | import APL.tokenizer.Token; 5 | import APL.types.arrs.ChrArr; 6 | 7 | public class StrTok extends Token { 8 | public final ChrArr val; 9 | public final String parsed; 10 | 11 | public StrTok(String line, int spos, int epos, String str) { 12 | super(line, spos, epos); 13 | parsed = str; 14 | this.val = Main.toAPL(str); 15 | } 16 | 17 | @Override public String toRepr() { 18 | return source(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/APL/errors/ImplementationError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.types.*; 4 | 5 | public class ImplementationError extends APLError { 6 | public ImplementationError(String s) { 7 | super(s); 8 | } 9 | public ImplementationError(String s, Tokenable fun) { 10 | super(s, fun); 11 | } 12 | public ImplementationError(String s, Callable fun, Tokenable cause) { 13 | super(s, fun, cause); 14 | } 15 | public ImplementationError(Throwable t) { 16 | super(t.getMessage()); 17 | initCause(t); 18 | } 19 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/NumTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | import APL.types.Num; 5 | 6 | public class NumTok extends Token { 7 | public final Num num; 8 | 9 | public NumTok(String line, int spos, int epos, double d) { 10 | super(line, spos, epos); 11 | this.num = new Num(d); 12 | } 13 | 14 | @Override public String toTree(String p) { 15 | return p+"num : " + num + "\n"; 16 | } 17 | 18 | @Override public String toRepr() { 19 | return source(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/DotBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.*; 5 | import APL.types.functions.builtins.mops.ReduceBuiltin; 6 | 7 | public class DotBuiltin extends Dop { 8 | @Override public String repr() { 9 | return "."; 10 | } 11 | 12 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 13 | Fun wwf = isFn(ww, '⍹'); 14 | return new ReduceBuiltin().derive(aa).call(wwf.call(a, w)); // TODO not lazy 15 | } 16 | } -------------------------------------------------------------------------------- /APLP5/data/multTable: -------------------------------------------------------------------------------- 1 | ⎕io←0 2 | P5.size ← ,⍨500 3 | g←P5.G 4 | P5.smooth←0 5 | P5.draw ← { 6 | n ← P5.mx 7 | ⍝ n ← ⌊⍢(.5×) P5.mx ⍝ alternative n definition to exclude odd numbers - floor under division by 2 8 | v ← n| ∘.×⍨ 1…n-1 9 | ⍝ another interesting pattern (try different values than 3 there) 10 | ⍝ v ← n| ∘.((3××) + +×-)⍨ 1…n-1 11 | 12 | ⍝ (0 0,P5.size) g.img P5.img -1+ {(65536×⍵)+(256×255-⍵)+255} ⌊.5+ (255÷n) × v ⍝ - a less optimized version of the below 13 | (0 0,P5.size) g.img P5.img -1+ 255 × 257 + 256× ⌊.5+ (255÷n) × v 14 | 15 | ⎕←P5.fps 16 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/ChrTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.Main; 4 | import APL.tokenizer.Token; 5 | import APL.types.*; 6 | 7 | public class ChrTok extends Token { 8 | public final Value val; 9 | public final String parsed; 10 | 11 | public ChrTok(String line, int spos, int epos, String str) { 12 | super(line, spos, epos); 13 | parsed = str; 14 | 15 | if (str.length() == 1) val = Char.of(str.charAt(0)); 16 | else val = Main.toAPL(str); 17 | } 18 | 19 | @Override public String toRepr() { 20 | return source(); 21 | } 22 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/FormatBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Main; 4 | import APL.types.Value; 5 | import APL.types.arrs.ChrArr; 6 | import APL.types.functions.Builtin; 7 | 8 | public class FormatBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍕"; 11 | } 12 | 13 | 14 | 15 | public Value call(Value w) { 16 | if (w.rank == 1) { 17 | w = w.squeeze(); 18 | if (w instanceof ChrArr) return Main.toAPL(w.asString()); 19 | } 20 | return Main.toAPL(w.toString()); 21 | } 22 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/BasicLines.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class BasicLines extends TokArr { 6 | public BasicLines(String line, int spos, int epos, ArrayList tokens) { 7 | super(line, spos, epos, tokens); 8 | } 9 | 10 | @Override public String toRepr() { 11 | StringBuilder s = new StringBuilder(); 12 | boolean tail = false; 13 | for (var v : tokens) { 14 | if (tail) s.append("\n"); 15 | s.append(v.toRepr()); 16 | tail = true; 17 | } 18 | return s.toString(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/UShoeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | import java.util.*; 7 | 8 | public class UShoeBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "∩"; 11 | } 12 | 13 | 14 | 15 | public Value call(Value a, Value w) { 16 | var res = new ArrayList(); 17 | HashSet ws = new HashSet<>(Arrays.asList(w.values())); 18 | for (Value v : a) if (ws.contains(v)) res.add(v); 19 | return Arr.create(res); 20 | } 21 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/DerivedSet.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins; 2 | 3 | import APL.types.*; 4 | 5 | public class DerivedSet extends AbstractSet { 6 | 7 | private final SetBuiltin s; 8 | private final Fun f; 9 | 10 | public DerivedSet(SetBuiltin s, Fun f) { 11 | this.s = s; 12 | this.f = f; 13 | } 14 | 15 | @Override public Obj callObj(Obj a, Obj w, boolean update) { 16 | s.callObj(a, f.call((Value) ((Settable) a).get(), (Value) w), update); 17 | return w; 18 | } 19 | 20 | public String toString() { 21 | return f.repr()+"←"; 22 | } 23 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/DfnTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import java.util.List; 4 | 5 | public class DfnTok extends TokArr { 6 | 7 | public DfnTok(String line, int spos, int epos, List tokens) { 8 | super(line, spos, tokens); 9 | end(epos); 10 | } 11 | 12 | @Override public String toRepr() { 13 | StringBuilder s = new StringBuilder("{"); 14 | boolean tail = false; 15 | for (var v : tokens) { 16 | if (tail) s.append(" ⋄ "); 17 | s.append(v.toRepr()); 18 | tail = true; 19 | } 20 | s.append("}"); 21 | return s.toString(); 22 | } 23 | } -------------------------------------------------------------------------------- /src/APL/types/Null.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.Type; 4 | import APL.types.arrs.SingleItemArr; 5 | 6 | public class Null extends Primitive { 7 | public static final Null NULL = new Null(); 8 | private Null() { } 9 | 10 | @Override 11 | public String toString() { 12 | return "⎕NULL"; 13 | } 14 | 15 | @Override 16 | public Type type() { 17 | return Type.nul; 18 | } 19 | 20 | @Override 21 | public Value ofShape(int[] sh) { 22 | return SingleItemArr.maybe(this, sh); 23 | } 24 | 25 | @Override public int hashCode() { 26 | return 387678968; // random yay 27 | } 28 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/QuoteQuad.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | 6 | public class QuoteQuad extends Settable { 7 | private final Scope sc; 8 | public QuoteQuad(Scope sc) { 9 | super(null); 10 | this.sc = sc; 11 | } 12 | 13 | public void set(Obj v, Callable blame) { 14 | sc.sys.print(v.toString()); 15 | } 16 | 17 | @Override 18 | public Obj get() { 19 | return Main.toAPL(sc.sys.input()); 20 | } 21 | public Type type() { 22 | return Type.gettable; 23 | } 24 | 25 | public String toString() { 26 | return "⍞"; 27 | } 28 | } -------------------------------------------------------------------------------- /src/APL/types/Settable.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.Type; 4 | import APL.errors.ValueError; 5 | 6 | public abstract class Settable extends Obj { 7 | final Obj v; 8 | protected Settable(Obj v) { 9 | this.v = v; 10 | } 11 | @Override 12 | public Type type() { 13 | return v == null? Type.var : v.type(); 14 | } 15 | public abstract void set(Obj v, Callable blame); 16 | public Obj get() { 17 | if (v == null) throw new ValueError("trying to get value of non-existing settable", this); 18 | return v; 19 | } 20 | public Obj getOrThis() { 21 | if (v == null) return this; 22 | return v; 23 | } 24 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/Quad.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | 6 | public class Quad extends Settable { 7 | private final Scope sc; 8 | public Quad(Scope sc) { 9 | super(null); 10 | this.sc = sc; 11 | } 12 | 13 | public void set(Obj v, Callable blame) { 14 | sc.sys.println((Main.debug? "[log] " : "")+v); 15 | } 16 | 17 | @Override 18 | public Obj get() { 19 | return Main.exec(sc.sys.input(), sc); 20 | } 21 | public Type type() { 22 | return Type.gettable; 23 | } 24 | 25 | public String toString() { 26 | return "⎕"; 27 | } 28 | } -------------------------------------------------------------------------------- /app/APLApp/stuff.pde: -------------------------------------------------------------------------------- 1 | void exec() { 2 | try { 3 | resVal = APL.Main.exec(program.replace("α", "⍺").replace("ω", "⍵"), global); 4 | res = resVal.toString(); 5 | } catch (Throwable e) { 6 | System.err.println("Error executing APL:"); 7 | e.printStackTrace(); 8 | res = e.getMessage(); 9 | if (res == null) res = e.toString(); 10 | } 11 | resSize = th; 12 | textSize(resSize); 13 | while (textWidth(res) > 5*w) { 14 | textSize(--resSize); 15 | if (resSize < 0) { 16 | resSize = th; 17 | break; 18 | } 19 | } 20 | } 21 | void thr() { 22 | new Error().printStackTrace(); 23 | delay(3000); 24 | throw null; 25 | } 26 | -------------------------------------------------------------------------------- /src/APL/tokenizer/types/ParenTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import java.util.List; 4 | 5 | public class ParenTok extends TokArr { 6 | public final boolean hasDmd; 7 | 8 | public ParenTok(String line, int spos, int epos, List tokens, boolean hasDmd) { 9 | super(line, spos, tokens); 10 | this.hasDmd = hasDmd; 11 | end(epos); 12 | } 13 | 14 | @Override public String toRepr() { 15 | StringBuilder s = new StringBuilder("("); 16 | boolean tail = false; 17 | for (var v : tokens) { 18 | if (tail) s.append(" ⋄ "); 19 | s.append(v.toRepr()); 20 | tail = true; 21 | } 22 | s.append(")"); 23 | return s.toString(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/GradeDownBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Scope; 4 | import APL.types.Value; 5 | import APL.types.arrs.DoubleArr; 6 | import APL.types.functions.Builtin; 7 | 8 | public class GradeDownBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍒"; 11 | } 12 | 13 | public GradeDownBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | public Value call(Value w) { 18 | double[] res = new double[w.ia]; 19 | int IO = sc.IO; 20 | Integer[] na = w.gradeDown(); 21 | for (int i = 0; i < na.length; i++) { 22 | res[i] = na[i]+IO; 23 | } 24 | return new DoubleArr(res); 25 | } 26 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/LTackBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.Value; 5 | import APL.types.functions.Builtin; 6 | 7 | public class LTackBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "⊣"; 10 | } 11 | 12 | 13 | 14 | public Value call(Value w) { return w; } 15 | public Value call(Value a, Value w) { return a; } 16 | 17 | public Value callInv(Value w) { 18 | return w; 19 | } 20 | public Value callInvW(Value a, Value w) { 21 | throw new DomainError("⊣⍣¯1 is impossible", this); 22 | } 23 | public Value callInvA(Value a, Value w) { 24 | return a; 25 | } 26 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/RTackBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.Value; 5 | import APL.types.functions.Builtin; 6 | 7 | public class RTackBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "⊢"; 10 | } 11 | 12 | 13 | 14 | public Value call(Value w) { return w; } 15 | public Value call(Value a, Value w) { return w; } 16 | 17 | public Value callInv(Value w) { 18 | return w; 19 | } 20 | public Value callInvW(Value a, Value w) { 21 | return w; 22 | } 23 | public Value callInvA(Value a, Value w) { 24 | throw new DomainError("⊢⍨⍣¯1 is impossible", this); 25 | } 26 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/EachLeft.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.Rank0Arr; 5 | import APL.types.functions.*; 6 | 7 | public class EachLeft extends Mop { 8 | @Override public String repr() { 9 | return "ᐵ"; 10 | } 11 | 12 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 13 | Fun ff = isFn(f); 14 | Value[] n = new Value[a.ia]; 15 | for (int i = 0; i < n.length; i++) n[i] = ff.call(a.get(i), w); 16 | return Arr.createL(n, a.shape); 17 | } 18 | 19 | public Value underW(Obj aa, Obj o, Value a, Value w, DerivedMop derv) { 20 | return EachBuiltin.underW(isFn(aa), o, a, new Rank0Arr(w), this); 21 | } 22 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [docs](https://github.com/dzaima/APL/blob/master/docs/chars.txt) | [differences from Dyalog APL](https://github.com/dzaima/APL/blob/master/docs/differences.txt) 2 | 3 | An APL re-implementation in Java. 4 | 5 | `./build` to build, `./REPL` to start a REPL. 6 | 7 | [Android app](https://github.com/dzaima/APL/tree/master/AndroidIDE) 8 | 9 | # Processing integration 10 | 11 | [docs](https://github.com/dzaima/APL/blob/master/APLP5/docs) 12 | 13 | 1. run `convert.py` in the folder `app` 14 | 2. run `APLP5` in [Processing](https://processing.org) 15 | 16 | To choose what file to run as APL, in `void settings` change the `args` array (or export & pass an actual argument) with the filename. Some examples are given in the folder `data`. -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/CommaBarBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.Value; 4 | import APL.types.functions.Builtin; 5 | 6 | public class CommaBarBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "⍪"; 9 | } 10 | 11 | 12 | 13 | public Value call(Value w) { 14 | if (w.rank==1) return w.ofShape(new int[]{w.shape[0], 1}); 15 | if (w.rank==0) return w.ofShape(new int[]{1, 1}); 16 | int tsz = 1; 17 | for (int i = 1; i < w.shape.length; i++) tsz*= w.shape[i]; 18 | return w.ofShape(new int[]{w.shape[0], tsz}); 19 | } 20 | 21 | public Value call(Value a, Value w) { 22 | return CatBuiltin.cat(a, w, 0, this); 23 | } 24 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/EachRight.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.Rank0Arr; 5 | import APL.types.functions.*; 6 | 7 | public class EachRight extends Mop { 8 | @Override public String repr() { 9 | return "ᑈ"; 10 | } 11 | 12 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 13 | Fun ff = isFn(f); 14 | Value[] n = new Value[w.ia]; 15 | for (int i = 0; i < n.length; i++) n[i] = ff.call(a, w.get(i)); 16 | return Arr.createL(n, w.shape); 17 | } 18 | 19 | public Value underW(Obj aa, Obj o, Value a, Value w, DerivedMop derv) { 20 | return EachBuiltin.underW(isFn(aa), o, new Rank0Arr(a), w, this); 21 | } 22 | } -------------------------------------------------------------------------------- /app/APLApp/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/GradeUpBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Scope; 4 | import APL.types.Value; 5 | import APL.types.arrs.DoubleArr; 6 | import APL.types.functions.Builtin; 7 | 8 | public class GradeUpBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍋"; 11 | } 12 | 13 | public GradeUpBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | public Value call(Value w) { 18 | double[] res = new double[w.ia]; 19 | int IO = sc.IO; 20 | Integer[] na = w.gradeUp(); 21 | for (int i = 0; i < na.length; i++) { 22 | res[i] = na[i]+IO; 23 | } 24 | return new DoubleArr(res); 25 | } 26 | 27 | // TODO dyadic ⍋ & ⍒ 28 | } -------------------------------------------------------------------------------- /AndroidIDE/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 -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/DShoeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | import java.util.*; 7 | 8 | @SuppressWarnings("Convert2Diamond") // convert.py chokes if not 9 | public class DShoeBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "∪"; 12 | } 13 | 14 | 15 | 16 | public Value call(Value w) { 17 | var res = new LinkedHashSet(Arrays.asList(w.values())); 18 | return Arr.create(res.toArray(new Value[0])); 19 | } 20 | 21 | public Value call(Value a, Value w) { 22 | var m = new LinkedHashSet(Arrays.asList(a.values())); 23 | m.addAll(Arrays.asList(w.values())); 24 | return Arr.create(m.toArray(new Value[0])); 25 | } 26 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/JotUBBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.*; 5 | 6 | public class JotUBBuiltin extends Dop { 7 | @Override public String repr() { 8 | return "⍛"; 9 | } 10 | 11 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 12 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 13 | return wwf.call(aaf.call(a), w); 14 | } 15 | 16 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 17 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 18 | return wwf.callInvW(aaf.call(a), w); 19 | } 20 | 21 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { 22 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 23 | return aaf.callInv(wwf.callInvA(a, w)); 24 | } 25 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/TokArr.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.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 pos, List tokens) { 11 | super(line, pos); 12 | this.tokens = tokens; 13 | } 14 | 15 | TokArr(String line, int spos, int epos, List tokens) { 16 | super(line, spos, epos); 17 | this.tokens = tokens; 18 | } 19 | 20 | public String toTree(String p) { 21 | StringBuilder r = new StringBuilder(); 22 | r.append(p).append(this.getClass().getCanonicalName()); 23 | r.append(' ').append(spos).append('-').append(epos); 24 | r.append('\n'); 25 | p+= " "; 26 | for (Token t : tokens) r.append(t.toTree(p)); 27 | return r.toString(); 28 | } 29 | } -------------------------------------------------------------------------------- /app/readme.md: -------------------------------------------------------------------------------- 1 | # Android calculator-ish app (old app; new version [here](https://github.com/dzaima/APL/tree/master/AndroidIDE)) 2 | 3 | Uses The fonts [APL385](http://apl385.com/fonts/index.htm) and [DejaVu Sans Mono](https://dejavu-fonts.github.io). 4 | 5 | To build the APL Android app, 6 | 1. run `convert.py` in the folder `app` 7 | 2. Open `app/APLApp` in Processing, change mode to android and change line 113 in `APLApp` to `/*` 8 | 3. Export from Processing to change the minimum SDK version to 24; For IntelliJ IDEA: 9 | - open with "use auto-import" checked 10 | - file → project structure → Project SDK = 1.8 11 | - build → build project 12 | - project structure → facets → Android-Gradle (app) → Flavors → Min Sdk version → 24 13 | - build → generate signed APK → whatever 14 | 15 | Alternatively, you can just run it in Processings Java mode just fine. -------------------------------------------------------------------------------- /src/APL/types/Variable.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.*; 4 | import APL.errors.ValueError; 5 | 6 | public class Variable extends Settable { 7 | 8 | private final Scope sc; 9 | public final String name; 10 | 11 | public Variable(Scope sc, String name) { 12 | super(sc.get(name)); 13 | this.sc = sc; 14 | this.name = name; 15 | } 16 | 17 | public Obj get() { 18 | if (v == null) throw new ValueError("trying to get value of non-existing variable "+name, this); 19 | return v; 20 | } 21 | 22 | @Override 23 | public void set(Obj v, Callable blame) { 24 | sc.set(name, v); 25 | } 26 | public void update(Obj v) { 27 | sc.update(name, v); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | if (Main.debug) return v == null? "var:"+name : "var:"+v; 33 | return v == null? "var:"+name : v.toString(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/APL/types/SimpleMap.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.errors.SyntaxError; 4 | 5 | public abstract class SimpleMap extends APLMap { 6 | @Override public Obj getRaw(Value k) { 7 | return getv(k.asString()); 8 | } 9 | 10 | public abstract Obj getv(String s); 11 | public abstract void setv(String s, Obj v); 12 | 13 | @Override public void set(Value k, Obj v) { 14 | setv(k.asString(), v); 15 | } 16 | 17 | @Override public Arr allValues() { 18 | throw new SyntaxError("getting list of values of "+name()); 19 | } 20 | 21 | @Override public Arr allKeys() { 22 | throw new SyntaxError("getting list of keys of "+name()); 23 | } 24 | 25 | @Override public Arr kvPair() { 26 | throw new SyntaxError("getting entries of "+name()); 27 | } 28 | 29 | @Override public int size() { 30 | throw new SyntaxError("getting size of "+name()); 31 | } 32 | } -------------------------------------------------------------------------------- /AndroidIDE/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/APL/tokenizer/types/BracketTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.errors.DomainError; 4 | 5 | import java.util.List; 6 | 7 | public class BracketTok extends TokArr { 8 | public final boolean array; 9 | 10 | public BracketTok(String line, int spos, int epos, List tokens, boolean hasDmd) { 11 | super(line, spos, tokens); 12 | array = tokens.size()>=2 || hasDmd; 13 | end(epos); 14 | if (tokens.size()==0 && hasDmd) throw new DomainError("[⋄] is not valid syntax", this); 15 | } 16 | 17 | @Override public String toRepr() { 18 | StringBuilder s = new StringBuilder("["); 19 | boolean tail = false; 20 | for (var v : tokens) { 21 | if (tail) s.append(" ⋄ "); 22 | s.append(v.toRepr()); 23 | tail = true; 24 | } 25 | s.append("]"); 26 | return s.toString(); 27 | } 28 | 29 | public String toString() { 30 | return "[...]"; 31 | } 32 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/ObverseBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.*; 5 | 6 | public class ObverseBuiltin extends Dop { 7 | @Override public String repr() { 8 | return "⍫"; 9 | } 10 | 11 | 12 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 13 | Fun aaf = isFn(aa, '⍶'); 14 | return aaf.call(w); 15 | } 16 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 17 | Fun aaf = isFn(aa, '⍶'); 18 | return aaf.call(a, w); 19 | } 20 | 21 | public Value callInv(Obj aa, Obj ww, Value w) { 22 | Fun wwf = isFn(ww, '⍹'); 23 | return wwf.call(w); 24 | } 25 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 26 | Fun wwf = isFn(ww, '⍹'); 27 | return wwf.call(a, w); 28 | } 29 | 30 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { // fall-back to ⍶ 31 | Fun aaf = isFn(aa, '⍶'); 32 | return aaf.callInvA(a, w); 33 | } 34 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/Token.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer; 2 | 3 | import APL.types.Tokenable; 4 | 5 | public abstract class Token implements Tokenable { 6 | public final String raw; 7 | public final int spos; // incl 8 | public int epos; // excl 9 | public static final int EPOS_DEF = -12345; 10 | protected Token(String raw, int spos) { 11 | this.raw = raw; 12 | this.spos = spos; 13 | epos = EPOS_DEF; 14 | } 15 | 16 | public Token(String raw, int spos, int epos) { 17 | this.raw = raw; 18 | this.spos = spos; 19 | this.epos = epos; 20 | } 21 | 22 | protected void end(int i) { 23 | assert epos == EPOS_DEF; 24 | epos = i; 25 | } 26 | 27 | @Override public Token getToken() { 28 | return this; 29 | } 30 | public String toTree(String p) { 31 | p+= " "; 32 | return p + this.getClass().getCanonicalName() + ' '+ spos + '-' + epos + '\n'; 33 | } 34 | public abstract String toRepr(); 35 | 36 | public String source() { 37 | return raw.substring(spos, epos); 38 | } 39 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/SetBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins; 2 | 3 | import APL.errors.SyntaxError; 4 | import APL.types.*; 5 | import APL.types.functions.VarArr; 6 | 7 | public class SetBuiltin extends AbstractSet { 8 | public final static SetBuiltin inst = new SetBuiltin(); 9 | 10 | public String toString() { 11 | return "←"; 12 | } 13 | 14 | 15 | 16 | 17 | public Obj callObj(Obj a, Obj w, boolean update) { 18 | if (!(a instanceof Settable)) throw new SyntaxError(a + " isn't settable", a); 19 | Settable as = (Settable) a; 20 | if (update) { 21 | if (a instanceof Variable) ((Variable) a).update(w); 22 | else if (a instanceof VarArr) ((VarArr) a).set(w, true); 23 | else as.set(w, this); // throw new SyntaxError("can't set", a); todo? 24 | } else { 25 | as.set(w, this); 26 | } 27 | return w; 28 | } 29 | 30 | public Obj callObj(Fun f, Obj a, Value w) { 31 | callObj(a, f.call((Value) ((Settable) a).get(), w), true); 32 | return w; 33 | } 34 | } -------------------------------------------------------------------------------- /src/APL/types/functions/FunArr.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.types.*; 4 | 5 | public class FunArr extends Fun { 6 | private final Obj[] os; 7 | 8 | public FunArr(Obj[] os) { 9 | this.os = os; 10 | } 11 | 12 | @Override public String repr() { 13 | StringBuilder res = new StringBuilder("("); 14 | boolean first = true; 15 | for (Obj o : os) { 16 | if (first) first = false; 17 | else res.append("⋄"); 18 | res.append(o.toString()); 19 | } 20 | res.append(")"); 21 | return res.toString(); 22 | } 23 | 24 | @Override public Value call(Value w) { 25 | Value[] vs = new Value[os.length]; 26 | for (int i = 0; i < os.length; i++) { 27 | vs[i] = ((Fun) os[i]).call(w); 28 | } 29 | return Arr.create(vs); 30 | } 31 | 32 | @Override public Value call(Value a, Value w) { 33 | Value[] vs = new Value[os.length]; 34 | for (int i = 0; i < os.length; i++) { 35 | vs[i] = ((Fun) os[i]).call(a, w); 36 | } 37 | return Arr.create(vs); 38 | } 39 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/SelfieBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | 7 | public class SelfieBuiltin extends Mop { 8 | @Override public String repr() { 9 | return "⍨"; 10 | } 11 | 12 | 13 | 14 | public Value call(Obj f, Value w, DerivedMop derv) { 15 | if (f instanceof Fun) return ((Fun)f).call(w, w); 16 | return (Value) f; 17 | } 18 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 19 | if (f instanceof Fun) return ((Fun)f).call(w, a); 20 | return (Value) f; 21 | } 22 | 23 | @Override public Value callInvW(Obj f, Value a, Value w) { 24 | if (f instanceof Fun) return ((Fun) f).callInvA(w, a); 25 | throw new DomainError("A⍨ cannot be inverted", this); 26 | } 27 | 28 | @Override public Value callInvA(Obj f, Value a, Value w) { 29 | if (f instanceof Fun) return ((Fun) f).callInvW(w, a); 30 | throw new DomainError("A⍨ cannot be inverted", this); 31 | } 32 | } -------------------------------------------------------------------------------- /APLP5/data/rects: -------------------------------------------------------------------------------- 1 | ⎕IO←0 2 | P5.size ← 500 500 ⍝ P5.dw (P5.dh-50) 3 | G ← P5.G 4 | rs ← ⍬ 5 | click ← 0 6 | pin ← 0 7 | LM MM RM ← P5.lm P5.mm P5.rm 8 | held ← ⍬ 9 | P5.draw ← { 10 | G.bg '222' 11 | cin ← anyin P5.mpos 12 | 1 0≡cin pin: P5.cursor ← 'hand' 13 | 0 1≡cin pin: P5.cursor ← 'arrow' 14 | pin⊢← cin 15 | G.rect rs 16 | G.fill←'d2' 17 | LM.p ∧ ~click: G.rect LM.s , P5.mpos 18 | MM.p ∧ ⍬≢held: rs⊢← ({⊂ {⍵+4⍴P5.mpos-P5.pmpos} @ (⍳4) ⊃ ⍵} @ held) rs 19 | } 20 | sort ← { , ⍉↑ <¨ ↓⍉ 2 2⍴ ⍵ } 21 | 22 | MM.c ← { 23 | anyin P5.mpos:← held⊢← ⊃⌽ ⍸ P5.mpos∘in ¨ rs 24 | held⊢← ⍬ 25 | } 26 | LM.c ← { 27 | click⊢← anyin ⍵: { 28 | i ← ⊃⌽ ⍸ ⍵∘in ¨ rs 29 | rs[i] ← ((256⊥255 , ?3⌿255) @ 4) i⊃rs 30 | }⍵ 31 | } 32 | LM.r ← { 33 | ~click: { 34 | ∧ 2 < ⌊/ | LM.s-P5.mpos: rs,←⊂ (sort LM.s , P5.mpos), P5.col 'd2' 35 | }⍬ 36 | } 37 | RM.c ← { 38 | anyin ⍵: { 39 | i ← ⊃⌽ ⍸ ⍵∘in ¨ rs 40 | rs⊢← (i ≠ ⍳≢rs) ⌿ rs 41 | }⍵ 42 | } 43 | 44 | anyin ← {∨ ⍵∘in ¨ rs} 45 | in ← { 46 | x y ← ⍺ 47 | sx sy ex ey ← 4↑⍵ 48 | (x > sx) ∧ (x < ex) ∧ (y > sy) ∧ (y < ey) 49 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/Pick.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.Scope; 4 | import APL.types.*; 5 | import APL.types.functions.builtins.dops.AtBuiltin; 6 | import APL.types.functions.builtins.fns.RShoeUBBuiltin; 7 | 8 | public class Pick extends Settable { 9 | private final Variable var; 10 | private final Value val; 11 | private final Value idx; 12 | private final int IO; 13 | private final Brackets obj; 14 | 15 | public Pick(Variable var, Brackets where, Scope sc) { 16 | super(null); 17 | this.var = var; 18 | this.val = (Value) var.get(); 19 | this.idx = where.val; 20 | this.obj = where; 21 | this.IO = sc.IO; 22 | } 23 | 24 | @Override 25 | public void set(Obj v, Callable blame) { 26 | var.update(AtBuiltin.at(v, idx, val, IO, blame)); 27 | } 28 | 29 | public Obj get() { 30 | return RShoeUBBuiltin.on(idx, val, IO, obj); 31 | } 32 | 33 | public Obj getOrThis() { 34 | return get(); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return var.name+"["+ val +"]"; 40 | } 41 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/APL/types/dimensions/DervDimMop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.Scope; 4 | import APL.errors.SyntaxError; 5 | import APL.types.*; 6 | import APL.types.functions.*; 7 | 8 | public class DervDimMop extends Mop { 9 | private final Mop f; 10 | private final int dim; 11 | 12 | public DervDimMop(Mop f, Integer dim, Scope sc) { 13 | super(sc); 14 | this.f = f; 15 | if (dim == null) this.dim = 0; 16 | else if (dim < 0) this.dim = dim; 17 | else this.dim = dim - sc.IO; 18 | this.token = f.token; 19 | 20 | } 21 | 22 | @Override public Value call(Obj aa, Value a, Value w, DerivedMop derv) { 23 | if (!(f instanceof DimDMop)) throw new SyntaxError("Attempt to call function dyadically that doesn't support dimension specification", a); 24 | return ((DimDMop) f).call(aa, a, w, dim); 25 | } 26 | 27 | @Override public Value call(Obj aa, Value w, DerivedMop derv) { 28 | if (!(f instanceof DimMMop)) throw new SyntaxError("Attempt to call function monadically that doesn't support dimension specification", w); 29 | return ((DimMMop) f).call(aa, w, dim); 30 | } 31 | 32 | @Override public String repr() { 33 | return f.repr()+"["+dim+"]"; 34 | } 35 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/JotDiaeresisBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.*; 5 | 6 | public class JotDiaeresisBuiltin extends Dop { 7 | @Override public String repr() { 8 | return "⍤"; 9 | } 10 | 11 | 12 | 13 | @Override 14 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 15 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 16 | return aaf.call(wwf.call(a, w)); 17 | } 18 | 19 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 20 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 21 | return aaf.call(wwf.call(w)); 22 | } 23 | 24 | public Value callInv(Obj aa, Obj ww, Value w) { 25 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 26 | return aaf.call(wwf.call(w)); 27 | } 28 | 29 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 30 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 31 | return wwf.callInvW(a, aaf.callInv(w)); 32 | } 33 | 34 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { 35 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 36 | return wwf.callInvA(aaf.callInv(a), w); 37 | } 38 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/CRepeatBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class CRepeatBuiltin extends Dop { 10 | @Override public String repr() { 11 | return "⍡"; 12 | } 13 | 14 | public CRepeatBuiltin(Scope sc) { 15 | super(sc); 16 | } 17 | 18 | @Override public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 19 | Fun aaf = isFn(aa, '⍶'); 20 | if (ww instanceof Fun) { 21 | ArrayList res = new ArrayList<>(); 22 | Value prev = w; 23 | res.add(prev); 24 | 25 | Value next = aaf.call(prev); 26 | res.add(next); 27 | Fun wwf = (Fun) ww; 28 | while(!Main.bool(wwf.call(prev, next))) { 29 | prev = next; 30 | next = aaf.call(prev); 31 | res.add(next); 32 | } 33 | return Arr.create(res); 34 | } else { 35 | int n = ((Value) ww).asInt(); 36 | Value[] res = new Value[n]; 37 | Value curr = w; 38 | for (int i = 0; i < n; i++) { 39 | curr = aaf.call(curr); 40 | res[i] = curr; 41 | } 42 | return Arr.create(res); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DervDimDop.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.Scope; 4 | import APL.errors.SyntaxError; 5 | import APL.types.*; 6 | import APL.types.functions.*; 7 | 8 | public class DervDimDop extends Dop { 9 | private final Dop f; 10 | private final int dim; 11 | 12 | @Override public String repr() { 13 | return f.repr()+"["+dim+"]"; 14 | } 15 | 16 | public DervDimDop(Dop f, Integer dim, Scope sc) { 17 | super(sc); 18 | this.f = f; 19 | if (dim == null) this.dim = 0; 20 | else if (dim < 0) this.dim = dim; 21 | else this.dim = dim - sc.IO; 22 | this.token = f.token; 23 | 24 | } 25 | 26 | @Override 27 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 28 | if (!(f instanceof DimDDop)) throw new SyntaxError("Attempt to call function dyadically that doesn't support dimension specification", a); 29 | return ((DimDDop) f).call(aa, ww, a, w, dim); 30 | } 31 | 32 | @Override 33 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 34 | if (!(f instanceof DimMDop)) throw new SyntaxError("Attempt to call function monadically that doesn't support dimension specification", w); 35 | return ((DimMDop) f).call(aa, ww, w, dim); 36 | } 37 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/GEBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.BitArr; 6 | import APL.types.functions.Builtin; 7 | 8 | 9 | public class GEBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "≥"; 12 | } 13 | 14 | 15 | 16 | private static final D_NNeB DNF = new D_NNeB() { 17 | public boolean on(double a, double w) { 18 | return a >= w; 19 | } 20 | public void on(BitArr.BA res, double a, double[] w) { 21 | for (double cw : w) res.add(a >= cw); 22 | } 23 | public void on(BitArr.BA res, double[] a, double w) { 24 | for (double ca : a) res.add(ca >= w); 25 | } 26 | public void on(BitArr.BA res, double[] a, double[] w) { 27 | for (int i = 0; i < a.length; i++) res.add(a[i] >= w[i]); 28 | } 29 | public Value call(BigValue a, BigValue w) { 30 | return a.i.compareTo(w.i) >= 0? Num.ONE : Num.ZERO; 31 | } 32 | }; 33 | 34 | public Value call(Value a, Value w) { 35 | return numChrD(DNF, (ca, cw) -> ca>=cw? Num.ONE : Num.ZERO, 36 | (ca, cw) -> { throw new DomainError("comparing "+ ca.humanType(true)+" and "+cw.humanType(true), this); }, 37 | a, w); 38 | } 39 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/LEBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.BitArr; 6 | import APL.types.functions.Builtin; 7 | 8 | 9 | public class LEBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "≤"; 12 | } 13 | 14 | 15 | 16 | private static final D_NNeB DNF = new D_NNeB() { 17 | public boolean on(double a, double w) { 18 | return a <= w; 19 | } 20 | public void on(BitArr.BA res, double a, double[] w) { 21 | for (double cw : w) res.add(a <= cw); 22 | } 23 | public void on(BitArr.BA res, double[] a, double w) { 24 | for (double ca : a) res.add(ca <= w); 25 | } 26 | public void on(BitArr.BA res, double[] a, double[] w) { 27 | for (int i = 0; i < a.length; i++) res.add(a[i] <= w[i]); 28 | } 29 | public Value call(BigValue a, BigValue w) { 30 | return a.i.compareTo(w.i) <= 0? Num.ONE : Num.ZERO; 31 | } 32 | }; 33 | 34 | public Value call(Value a, Value w) { 35 | return numChrD(DNF, (ca, cw) -> ca<=cw? Num.ONE : Num.ZERO, 36 | (ca, cw) -> { throw new DomainError("comparing "+ ca.humanType(true)+" and "+cw.humanType(true), this); }, 37 | a, w); 38 | } 39 | } -------------------------------------------------------------------------------- /src/APL/types/arrs/Rank0Arr.java: -------------------------------------------------------------------------------- 1 | package APL.types.arrs; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | 6 | public class Rank0Arr extends Arr { 7 | public final static int[] SHAPE = new int[0]; 8 | public final Value item; 9 | 10 | public Rank0Arr(Value item) { 11 | super(SHAPE, 1, 0); 12 | this.item = item; 13 | } 14 | 15 | @Override 16 | public int[] asIntArrClone() { 17 | return new int[]{item.asInt()}; 18 | } 19 | 20 | @Override 21 | public int asInt() { 22 | throw new DomainError("Using a shape 1 array as integer", this); 23 | } 24 | 25 | @Override 26 | public Value get(int i) { 27 | return item; 28 | } 29 | 30 | @Override 31 | public String asString() { 32 | if (item instanceof Char) return String.valueOf(((Char) item).chr); 33 | throw new DomainError("Using array containing "+item.humanType(true)+" as string", this); 34 | } 35 | 36 | public Value prototype() { 37 | return item.prototype(); 38 | } 39 | 40 | public Value safePrototype() { 41 | return item.safePrototype(); 42 | } 43 | 44 | @Override 45 | public Value ofShape(int[] sh) { 46 | return SingleItemArr.maybe(item, sh); 47 | } 48 | 49 | @Override 50 | public Value[] valuesCopy() { 51 | return new Value[]{item}; 52 | } 53 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/SquadBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.util.Arrays; 9 | 10 | public class SquadBuiltin extends Builtin { 11 | @Override public String repr() { 12 | return "⌷"; 13 | } 14 | 15 | public SquadBuiltin(Scope sc) { 16 | super(sc); 17 | } 18 | 19 | public Value call(Value w) { 20 | if (w instanceof Arr) return w; 21 | if (w instanceof APLMap) return ((APLMap) w).kvPair(); 22 | throw new DomainError("⍵ not array nor map", this, w); 23 | } 24 | 25 | public Value call(Value a, Value w) { 26 | int[] p = a.asIntVec(); 27 | int al = p.length; 28 | int wl = w.shape.length; 29 | if (al > wl) throw new RankError("⌷: expected (≢⍺) ≤ ≢⍴⍵ ("+al+" = ≢⍺; "+ Main.formatAPL(w.shape)+" ≡ ⍴⍵)", this, a); 30 | int sz = 1; 31 | for (int i = al; i < wl; i++) sz*= w.shape[i]; 32 | int off = 0; 33 | for (int i = 0; i < al; i++) { 34 | int d = p[i]-sc.IO; 35 | off+= d; 36 | if (d<0 || d>=w.shape[i]) throw new LengthError("⌷: index out-of-bounds", this, a); 37 | off*= i>=al-1? sz : w.shape[i+1]; 38 | } 39 | return w.cut(off, sz, Arrays.copyOfRange(w.shape, al, wl)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/FlipBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.dimensions.*; 6 | import APL.types.functions.Builtin; 7 | 8 | public class FlipBuiltin extends Builtin implements DimMFn, DimDFn { 9 | @Override public String repr() { 10 | return "⊖"; 11 | } 12 | 13 | 14 | @Override public Value call(Value w, int dim) { 15 | return ((Arr) w).reverseOn(dim); 16 | } 17 | @Override public Value call(Value w) { 18 | if (w instanceof Primitive) return w; 19 | return ((Arr) w).reverseOn(0); 20 | } 21 | @Override public Value callInv(Value w) { 22 | return call(w); 23 | } 24 | 25 | @Override public Value call(Value a, Value w) { 26 | if (a instanceof Primitive) return ReverseBuiltin.on(a.asInt(), 0, w); 27 | throw new DomainError("A⊖B not implemented for non-scalar A", this); 28 | } 29 | 30 | @Override public Value call(Value a, Value w, DervDimFn dims) { 31 | int dim = dims.singleDim(w.rank); 32 | if (a instanceof Primitive) return ReverseBuiltin.on(a.asInt(), w.rank-dim-1, w); 33 | throw new DomainError("A⊖[n]B not implemented for non-scalar A", this); 34 | } 35 | 36 | @Override public Value callInvW(Value a, Value w) { 37 | return call(numM(MinusBuiltin.NF, a), w); 38 | } 39 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/LShoeStileBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.RankError; 4 | import APL.types.Value; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.util.*; 9 | 10 | public class LShoeStileBuiltin extends Builtin { 11 | 12 | @Override public Value call(Value a, Value w) { 13 | HashMap counts = new HashMap<>(); 14 | for (Value ca : a) counts.put(ca, 0); 15 | for (Value cw : w) { 16 | Integer pv = counts.get(cw); 17 | if (pv != null) counts.put(cw, pv + 1); 18 | } 19 | double[] res = new double[a.ia]; 20 | int i = 0; 21 | for (Value ca : a) { 22 | res[i] = counts.get(ca); 23 | i++; 24 | } 25 | return DoubleArr.safe(res, a.shape); 26 | } 27 | 28 | @Override public Value call(Value w) { 29 | if (w.rank != 1) throw new RankError("⍧: rank of argument must be 1", this, w); 30 | HashSet encountered = new HashSet<>(); 31 | BitArr.BA res = new BitArr.BA(w.shape); 32 | for (Value cv : w) { 33 | if (encountered.contains(cv)) res.add(false); 34 | else { 35 | encountered.add(cv); 36 | res.add(true); 37 | } 38 | } 39 | return res.finish(); 40 | } 41 | 42 | @Override public String repr() { 43 | return "⍧"; 44 | } 45 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/DepthBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.*; 5 | import APL.types.functions.Builtin; 6 | 7 | public class DepthBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "≡"; 10 | } 11 | 12 | 13 | public static int lazy(Value w) { 14 | int depth = 0; 15 | while (!(w instanceof Primitive)) { 16 | w = w.first(); 17 | depth++; 18 | } 19 | return depth; 20 | } 21 | public static int full(Value w) { 22 | if (w instanceof Primitive) return 0; 23 | if (w instanceof DoubleArr || w instanceof ChrArr || w instanceof BitArr) return 1; 24 | boolean first = true; 25 | boolean uneven = false; 26 | int sub = 0; 27 | for (Value v : w) { 28 | int cd = full(v); 29 | if (cd < 0) { 30 | uneven = true; 31 | cd = -cd; 32 | } 33 | if (first) { 34 | first = false; 35 | sub = cd; 36 | } else if (sub != cd) { 37 | sub = Math.max(sub, cd); 38 | uneven = true; 39 | } 40 | } 41 | sub++; 42 | return uneven? -sub : sub; 43 | } 44 | 45 | public Value call(Value w) { 46 | return Num.of(full(w)); 47 | } 48 | public Value call(Value a, Value w) { 49 | return a.equals(w)? Num.ONE : Num.ZERO; 50 | } 51 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/Brackets.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.*; 4 | import APL.tokenizer.types.*; 5 | import APL.types.*; 6 | import APL.types.functions.builtins.fns.UpArrowBuiltin; 7 | 8 | public class Brackets extends Callable { 9 | 10 | public final Value val; 11 | 12 | public Brackets(Value val) { 13 | super(null); 14 | this.val = val; 15 | } 16 | 17 | public Integer toInt() { 18 | return val==null? null : val.asInt(); 19 | } 20 | public int[] toInts() { 21 | return val==null? null : val.asIntVec(); 22 | } 23 | 24 | @Override 25 | public Type type() { 26 | return Type.dim; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "["+val+"]"; 32 | } 33 | 34 | public static Obj of(BracketTok t, Scope sc) { 35 | if (t.array) { 36 | Value[] lns = new Value[t.tokens.size()]; 37 | for (int i = 0; i < t.tokens.size(); i++) { 38 | LineTok tk = t.tokens.get(i); 39 | lns[i] = Main.vexec(tk, sc); 40 | } 41 | return UpArrowBuiltin.merge(lns, new int[]{lns.length}, t); 42 | } else { 43 | if (t.tokens.size() == 0) return new Brackets(null); 44 | assert t.tokens.size() == 1; // t.array is true if size>1 45 | Value res = Main.vexec(t.tokens.get(0), sc); 46 | return new Brackets(res); 47 | } 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/ExpandBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.*; 4 | import APL.types.*; 5 | import APL.types.functions.Builtin; 6 | 7 | public class ExpandBuiltin extends Builtin { 8 | public String repr() { 9 | return "⍀"; 10 | } 11 | 12 | public Value call(Value a, Value w) { 13 | if (a.rank != 1) throw new RankError("⍀: ⍺ bust be of rank 1", this, a); 14 | if (w.rank >= 2) throw new NYIError("⍀: rank 2 or more ⍵", this, w); 15 | Value pr = null; 16 | int[] is = a.asIntArr(); // vectorness checked before 17 | int ram = 0; 18 | int iam = 0; 19 | for (int v : is) { 20 | ram+= Math.max(1, Math.abs(v)); 21 | iam+= v>0? 1 : 0; 22 | } 23 | if (iam != w.ia) throw new DomainError("⍀: required input amount ("+iam+") not equal to given ("+w.ia+")", this); 24 | Value[] res = new Value[ram]; 25 | int rp = 0; 26 | int ip = 0; 27 | 28 | for (int v : is) { 29 | if (v <= 0) { 30 | if (pr == null) pr = w.safePrototype(); 31 | v = Math.max(1, -v); 32 | for (int i = 0; i < v; i++) res[rp++] = pr; 33 | } else { 34 | Value c = w.get(ip); 35 | for (int i = 0; i < v; i++) { 36 | res[rp++] = c; 37 | } 38 | ip++; 39 | } 40 | } 41 | 42 | return Arr.create(res); 43 | } 44 | } -------------------------------------------------------------------------------- /src/APL/types/functions/ArrFun.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.tokenizer.types.BacktickTok; 6 | import APL.types.*; 7 | import APL.types.arrs.SingleItemArr; 8 | 9 | public class ArrFun extends Primitive { 10 | 11 | private final Obj f; 12 | 13 | public ArrFun(Fun f) { 14 | this.f = f; 15 | } 16 | 17 | public ArrFun(BacktickTok t, Scope sc) { 18 | f = Main.exec(t.value(), sc); 19 | if (!(f instanceof Fun) && !(f instanceof Mop) && !(f instanceof Dop)) { 20 | throw new DomainError("can't arrayify " + f.humanType(true), this); 21 | } 22 | } 23 | 24 | public Obj obj() { 25 | return f; 26 | } 27 | 28 | @Override public Value ofShape(int[] sh) { 29 | return SingleItemArr.maybe(this, sh); 30 | } 31 | 32 | @Override public String toString() { 33 | if (f instanceof Fun) return "`"+((Fun) f).repr(); 34 | if (f instanceof Mop) return "`"+((Mop) f).repr(); 35 | if (f instanceof Dop) return "`"+((Dop) f).repr(); 36 | throw new InternalError("unexpected `"+f.humanType(false)); 37 | } 38 | 39 | @Override public int hashCode() { 40 | return f.hashCode(); 41 | } 42 | 43 | @Override public boolean equals(Obj o) { 44 | if (!(o instanceof ArrFun)) return false; 45 | ArrFun w = (ArrFun) o; 46 | return w.f.equals(f); 47 | } 48 | } -------------------------------------------------------------------------------- /src/APL/types/functions/userDefined/UserDefined.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.userDefined; 2 | 3 | import APL.*; 4 | import APL.tokenizer.Token; 5 | import APL.tokenizer.types.*; 6 | import APL.types.Obj; 7 | 8 | public class UserDefined { 9 | public static Obj of(DfnTok ts, Scope sc) { 10 | Type type = funType(ts, true); 11 | switch (type) { 12 | case fn : return new Dfn(ts, sc); 13 | case mop: return new Dmop(ts, sc); 14 | case dop: return new Ddop(ts, sc); 15 | default : throw new IllegalStateException(); 16 | } 17 | } 18 | private static Type funType(TokArr i, boolean first) { 19 | Type type = Type.fn; 20 | if (!(i instanceof DfnTok) || first) for (Token t : i.tokens) { 21 | if (t instanceof OpTok) { 22 | String op = ((OpTok) t).op; 23 | if (op.equals("⍶")) type = Type.mop; 24 | else if (op.equals("⍹")) return Type.dop; 25 | } else if (t instanceof TokArr) { 26 | Type n = funType((TokArr) t, false); 27 | if (n == Type.mop) type = Type.mop; 28 | else if (n.equals(Type.dop)) return Type.dop; 29 | } else if (t instanceof BacktickTok) { 30 | Type n = funType(((BacktickTok) t).value(), false); 31 | if (n == Type.mop) type = Type.mop; 32 | else if (n.equals(Type.dop)) return Type.dop; 33 | } 34 | } 35 | return type; 36 | } 37 | } -------------------------------------------------------------------------------- /src/APL/types/Primitive.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.errors.DomainError; 4 | 5 | public abstract class Primitive extends Value { 6 | private static final int[] SHAPE = new int[0]; 7 | 8 | public Primitive() { 9 | super(SHAPE, 1, 0); 10 | } 11 | 12 | @Override 13 | public final Value get(int i) { 14 | return this; 15 | } 16 | 17 | public final Value first() { 18 | return this; 19 | } 20 | 21 | @Override 22 | public int[] asIntArrClone() { 23 | throw new DomainError("Using " + this.oneliner() + " as integer array", this); 24 | } 25 | @Override 26 | public int[] asIntVec() { 27 | throw new DomainError("Using " + this.oneliner() + " as integer vector", this); 28 | } 29 | 30 | @Override 31 | public int asInt() { 32 | throw new DomainError("Using " + this.oneliner() + " as integer", this); 33 | } 34 | 35 | @Override 36 | public String asString() { 37 | throw new DomainError("Using " + this.oneliner() + " as string", this); 38 | } 39 | 40 | public final Value prototype() { 41 | Value v = safePrototype(); 42 | if (v==null) throw new DomainError("Getting prototype of "+this, this); 43 | return v; 44 | } 45 | public Value safePrototype() { 46 | return null; 47 | } 48 | 49 | @Override public Value squeeze() { // primitives are already pretty squeezed 50 | return this; 51 | } 52 | } -------------------------------------------------------------------------------- /src/APL/types/APLMap.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.Main; 4 | import APL.types.arrs.SingleItemArr; 5 | 6 | public abstract class APLMap extends Primitive { 7 | 8 | public MapPointer get(Value k) { 9 | return new MapPointer(this, k); 10 | } 11 | 12 | public abstract Obj getRaw(Value k); 13 | 14 | public Obj getRaw(String k) { 15 | return getRaw(Main.toAPL(k)); 16 | } 17 | public MapPointer get(String k) { 18 | return get(Main.toAPL(k)); 19 | } 20 | 21 | abstract public void set(Value k, Obj v); 22 | abstract public Arr allValues(); 23 | abstract public Arr allKeys(); 24 | abstract public Arr kvPair(); 25 | abstract public int size(); 26 | 27 | public static class MapPointer extends Settable { 28 | private final APLMap map; 29 | private final Value k; 30 | 31 | MapPointer(APLMap map, Value k) { 32 | super(map.getRaw(k)); 33 | this.map = map; 34 | this.k = k; 35 | } 36 | 37 | @Override 38 | public void set(Obj v, Callable blame) { 39 | map.set(k, v); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | if (Main.debug) return v == null? "map@"+k : "ptr@"+k+":"+v; 45 | return v == null? "map@"+k : v.toString(); 46 | } 47 | } 48 | 49 | @Override 50 | public Value ofShape(int[] sh) { 51 | return SingleItemArr.maybe(this, sh); 52 | } 53 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/EvalBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | import APL.types.functions.*; 7 | 8 | public class EvalBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍎"; 11 | } 12 | 13 | public EvalBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | public Value call(Value w) { 18 | Obj o = callObj(w); 19 | if (o instanceof Value) return (Value) o; 20 | throw new DomainError("⍎: was expected to return an array, got "+o.humanType(true), this); 21 | } 22 | public Obj callObj(Value w) { 23 | if (w instanceof ArrFun) return ((ArrFun) w).obj(); 24 | return Main.exec(w.asString(), sc); 25 | } 26 | public Value call(Value a, Value w) { 27 | Obj o = callObj(a, w); 28 | if (o instanceof Value) return (Value) o; 29 | throw new DomainError("⍎: was expected to return an array, got "+o.humanType(true), this); 30 | } 31 | public Obj callObj(Value a, Value w) { 32 | if (a instanceof ArrFun) { 33 | Obj obj = ((ArrFun) a).obj(); 34 | if (!(obj instanceof Fun)) throw new DomainError("⍎: ⍺ must be `function, was "+obj.humanType(true), this); 35 | return ((Fun) obj).callObj(w); 36 | } else { 37 | throw new DomainError("⍎: Expected ⍺ to be an arrayified function", this, a); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /APLP5/Img.pde: -------------------------------------------------------------------------------- 1 | class APLImg extends SimpleMap { 2 | PImage img; 3 | Arr size, px; 4 | Num w, h; 5 | APLImg(PImage img) { 6 | this.img = img; 7 | w = new Num(img.width ); 8 | h = new Num(img.height); 9 | size = new DoubleArr(new double[]{img.width, img.height}); 10 | } 11 | 12 | void setv(String k, Obj v) { 13 | String s = k.toLowerCase(); 14 | switch (s) { 15 | default: throw new DomainError("setting non-existing key "+s+" for APLImg"); 16 | } 17 | } 18 | Obj getv(String k) { 19 | String s = k.toLowerCase(); 20 | switch (s) { 21 | case "w": case "width" : return w; 22 | case "h": case "height": return h; 23 | case "dimensions": case "size": case "sz": return size; 24 | case "mat": case "pixels": 25 | if (px != null) return px; 26 | int ia = img.pixels.length; 27 | double[] vals = new double[ia]; 28 | for (int i = 0; i < ia; i++) { 29 | vals[i] = img.pixels[i]; 30 | } 31 | return new DoubleArr(vals, new int[]{img.height, img.width}); 32 | case "save": return new Fun() { 33 | public Value call(Value w) { 34 | img.save(w.asString()); 35 | return Num.ONE; 36 | } 37 | public String repr() { 38 | return "APLImg.save"; 39 | } 40 | }; 41 | default: return NULL; 42 | } 43 | } 44 | String toString() { return "APLImg"; } 45 | } 46 | -------------------------------------------------------------------------------- /src/APL/types/functions/DerivedMop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.builtins.mops.TableBuiltin; 5 | 6 | public class DerivedMop extends Fun { 7 | private final Obj aa; 8 | private final Mop op; 9 | DerivedMop(Obj aa, Mop op) { 10 | this.aa = aa; 11 | this.op = op; 12 | token = op.token; 13 | } 14 | 15 | public Value call(Value w) { 16 | return op.call(aa, w, this); 17 | } 18 | public Value call(Value a, Value w) { 19 | return op.call(aa, a, w, this); 20 | } 21 | public Obj callObj(Value w) { 22 | return op.callObj(aa, w, this); 23 | } 24 | public Obj callObj(Value a, Value w) { 25 | return op.callObj(aa, a, w, this); 26 | } 27 | public Value callInv(Value w) { 28 | return op.callInv(aa, w); 29 | } 30 | public Value callInvW(Value a, Value w) { 31 | return op.callInvW(aa, a, w); 32 | } 33 | public Value callInvA(Value a, Value w) { 34 | return op.callInvA(aa, a, w); 35 | } 36 | 37 | @Override public String repr() { 38 | return op instanceof TableBuiltin? "∘."+aa.toString() : aa.toString()+op.repr(); 39 | } 40 | 41 | public Value under(Obj o, Value w) { 42 | return op.under(aa, o, w, this); 43 | } 44 | public Value underW(Obj o, Value a, Value w) { 45 | return op.underW(aa, o, a, w, this); 46 | } 47 | public Value underA(Obj o, Value a, Value w) { 48 | return op.underA(aa, o, a, w, this); 49 | } 50 | } -------------------------------------------------------------------------------- /APLP5/Mouse.pde: -------------------------------------------------------------------------------- 1 | class MouseButton extends SimpleMap { 2 | int m; 3 | Num sX = Num.ZERO, sY = Num.ZERO; 4 | Arr sPos = new DoubleArr(new double[]{0, 0}); 5 | Num pressed = Num.ZERO; 6 | Num ppressed = Num.ZERO; 7 | Fun cH, rH; 8 | MouseButton(int id) { 9 | m = id; 10 | } 11 | void draw() { 12 | ppressed = pressed; 13 | boolean p = mousePressed && mouseButton == m; 14 | pressed = p? Num.ONE : Num.ZERO; 15 | if (ppressed == Num.ZERO && p) { 16 | sX = mx; 17 | sY = my; 18 | sPos = mpos; 19 | call(cH, mpos); 20 | } 21 | else if (ppressed == Num.ONE && !p) { 22 | call(rH, sPos, mpos); 23 | } 24 | } 25 | void setv(String k, Obj v) { 26 | String s = k.toLowerCase(); 27 | switch (s) { 28 | // callbacks 29 | case "clicked" : case "c": cH = (Fun) v; break; 30 | case "released": case "r": rH = (Fun) v; break; 31 | default: throw new DomainError("setting non-existing key "+s+" for Mouse"); 32 | } 33 | } 34 | Obj getv(String k) { 35 | String s = k.toLowerCase(); 36 | switch (s) { 37 | case "sx": case "startx": return sX; 38 | case "sy": case "starty": return sY; 39 | case "sp": case "s": case "startpos": return sPos; 40 | case "p": case "pressed": return pressed; 41 | case "pp": case "ppressed": return ppressed; 42 | default: return NULL; 43 | } 44 | } 45 | String toString() { return m==LEFT?"P5.lm":m==RIGHT?"P5.rm":"P5.mm"; } 46 | } 47 | -------------------------------------------------------------------------------- /src/APL/types/functions/DerivedDop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.types.*; 4 | 5 | public class DerivedDop extends Fun { 6 | private final Obj aa, ww; 7 | private final Dop op; 8 | DerivedDop(Obj aa, Obj ww, Dop op) { 9 | this.aa = aa; 10 | this.ww = ww; 11 | this.op = op; 12 | token = op.token; 13 | } 14 | 15 | public Value call(Value w) { 16 | return op.call(aa, ww, w, this); 17 | } 18 | public Value call(Value a, Value w) { 19 | return op.call(aa, ww, a, w, this); 20 | } 21 | public Obj callObj(Value w) { 22 | return op.callObj(aa, ww, w, this); 23 | } 24 | public Obj callObj(Value a, Value w) { 25 | return op.callObj(aa, ww, a, w, this); 26 | } 27 | public Value callInv(Value w) { 28 | return op.callInv(aa, ww, w); 29 | } 30 | public Value callInvW(Value a, Value w) { 31 | return op.callInvW(aa, ww, a, w); 32 | } 33 | public Value callInvA(Value a, Value w) { 34 | return op.callInvA(aa, ww, a, w); 35 | } 36 | @Override public String repr() { 37 | String wws = ww.toString(); 38 | if (!(ww instanceof Arr) && wws.length() != 1) wws = "("+wws+")"; 39 | return aa.toString()+op.repr()+wws; 40 | } 41 | 42 | public Value under(Obj o, Value w) { 43 | return op.under(aa, ww, o, w, this); 44 | } 45 | public Value underW(Obj o, Value a, Value w) { 46 | return op.underW(aa, ww, o, a, w, this); 47 | } 48 | public Value underA(Obj o, Value a, Value w) { 49 | return op.underA(aa, ww, o, a, w, this); 50 | } 51 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/CeilingBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | public class CeilingBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "⌈"; 9 | } 10 | 11 | 12 | 13 | public Value identity() { 14 | return Num.NEGINF; 15 | } 16 | 17 | private static final NumMV NF = new NumMV() { 18 | public Value call(Num w) { 19 | return w.ceil(); 20 | } 21 | public void call(double[] res, double[] a) { 22 | for (int i = 0; i < a.length; i++) res[i] = Math.ceil(a[i]); 23 | } 24 | }; 25 | public Value call(Value w) { 26 | return numChrM(NF, Char::upper, w); 27 | } 28 | 29 | private static final D_NNeN DNF = new D_NNeN() { 30 | public double on(double a, double w) { 31 | return Math.max(a, w); 32 | } 33 | public void on(double[] res, double a, double[] w) { 34 | for (int i = 0; i < w.length; i++) res[i] = Math.max(a, w[i]); 35 | } 36 | public void on(double[] res, double[] a, double w) { 37 | for (int i = 0; i < a.length; i++) res[i] = Math.max(a[i], w); 38 | } 39 | public void on(double[] res, double[] a, double[] w) { 40 | for (int i = 0; i < a.length; i++) res[i] = Math.max(a[i], w[i]); 41 | } 42 | public Value call(BigValue a, BigValue w) { 43 | return a.compareTo(w)>0? a : w; 44 | } 45 | }; 46 | public Value call(Value a0, Value w0) { 47 | return numD(DNF, a0, w0); 48 | } 49 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/FloorBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | public class FloorBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "⌊"; 9 | } 10 | 11 | 12 | 13 | public Value identity() { 14 | return Num.POSINF; 15 | } 16 | 17 | private static final NumMV NF = new NumMV() { 18 | public Value call(Num w) { 19 | return w.floor(); 20 | } 21 | public void call(double[] res, double[] a) { 22 | for (int i = 0; i < a.length; i++) res[i] = Math.floor(a[i]); 23 | } 24 | }; 25 | public Value call(Value w) { 26 | return numChrM(NF, Char::lower, w); 27 | } 28 | 29 | private static final D_NNeN DNF = new D_NNeN() { 30 | public double on(double a, double w) { 31 | return Math.min(a, w); 32 | } 33 | public void on(double[] res, double a, double[] w) { 34 | for (int i = 0; i < w.length; i++) res[i] = Math.min(a, w[i]); 35 | } 36 | public void on(double[] res, double[] a, double w) { 37 | for (int i = 0; i < a.length; i++) res[i] = Math.min(a[i], w); 38 | } 39 | public void on(double[] res, double[] a, double[] w) { 40 | for (int i = 0; i < a.length; i++) res[i] = Math.min(a[i], w[i]); 41 | } 42 | public Value call(BigValue a, BigValue w) { 43 | return a.compareTo(w)>0? w : a; 44 | } 45 | }; 46 | public Value call(Value a0, Value w0) { 47 | return numD(DNF, a0, w0); 48 | } 49 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/GTBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.BitArr; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.util.Arrays; 9 | 10 | 11 | public class GTBuiltin extends Builtin { 12 | @Override public String repr() { 13 | return ">"; 14 | } 15 | 16 | 17 | 18 | private static final D_NNeB DNF = new D_NNeB() { 19 | public boolean on(double a, double w) { 20 | return a > w; 21 | } 22 | public void on(BitArr.BA res, double a, double[] w) { 23 | for (double cw : w) res.add(a > cw); 24 | } 25 | public void on(BitArr.BA res, double[] a, double w) { 26 | for (double ca : a) res.add(ca > w); 27 | } 28 | public void on(BitArr.BA res, double[] a, double[] w) { 29 | for (int i = 0; i < a.length; i++) res.add(a[i] > w[i]); 30 | } 31 | public Value call(BigValue a, BigValue w) { 32 | return a.i.compareTo(w.i) > 0? Num.ONE : Num.ZERO; 33 | } 34 | }; 35 | 36 | public Value call(Value a, Value w) { 37 | return numChrD(DNF, (ca, cw) -> ca>cw? Num.ONE : Num.ZERO, 38 | (ca, cw) -> { throw new DomainError("comparing "+ ca.humanType(true)+" and "+cw.humanType(true), this); }, 39 | a, w); 40 | } 41 | 42 | public Value call(Value w) { 43 | var order = w.gradeDown(); 44 | Value[] res = new Value[order.length]; 45 | Arrays.setAll(res, i -> w.get(order[i])); 46 | return Arr.create(res); 47 | } 48 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/LTBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.BitArr; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.util.Arrays; 9 | 10 | 11 | public class LTBuiltin extends Builtin { 12 | @Override public String repr() { 13 | return "<"; 14 | } 15 | 16 | 17 | 18 | private static final D_NNeB DNF = new D_NNeB() { 19 | public boolean on(double a, double w) { 20 | return a < w; 21 | } 22 | public void on(BitArr.BA res, double a, double[] w) { 23 | for (double cw : w) res.add(a < cw); 24 | } 25 | public void on(BitArr.BA res, double[] a, double w) { 26 | for (double ca : a) res.add(ca < w); 27 | } 28 | public void on(BitArr.BA res, double[] a, double[] w) { 29 | for (int i = 0; i < a.length; i++) res.add(a[i] < w[i]); 30 | } 31 | public Value call(BigValue a, BigValue w) { 32 | return a.i.compareTo(w.i) < 0? Num.ONE : Num.ZERO; 33 | } 34 | }; 35 | 36 | public Value call(Value a, Value w) { 37 | return numChrD(DNF, (ca, cw) -> ca { throw new DomainError("comparing "+ ca.humanType(true)+" and "+cw.humanType(true), this); }, 39 | a, w); 40 | } 41 | 42 | public Value call(Value w) { 43 | var order = w.gradeUp(); 44 | Value[] res = new Value[order.length]; 45 | Arrays.setAll(res, i -> w.get(order[i])); 46 | return Arr.create(res); 47 | } 48 | } -------------------------------------------------------------------------------- /src/APL/types/arrs/Shape1Arr.java: -------------------------------------------------------------------------------- 1 | package APL.types.arrs; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | 6 | public class Shape1Arr extends Arr { 7 | private static final int[] SHAPE = new int[]{1}; 8 | private final Value item; 9 | 10 | public Shape1Arr(Value item) { 11 | super(SHAPE, 1, 1); 12 | this.item = item; 13 | } 14 | 15 | @Override 16 | public int[] asIntArrClone() { 17 | return new int[]{item.asInt()}; 18 | } 19 | 20 | @Override 21 | public int asInt() { 22 | throw new DomainError("Using a shape 1 array as integer", this); 23 | } 24 | 25 | @Override 26 | public Value get(int i) { 27 | return item; 28 | } 29 | 30 | @Override 31 | public String asString() { 32 | if (item instanceof Char) return String.valueOf(((Char)item).chr); 33 | throw new DomainError("Using array containing "+item.humanType(true)+" as string", this); 34 | } 35 | 36 | public Value prototype() { 37 | return item.prototype(); 38 | } 39 | public Value safePrototype() { 40 | return item.safePrototype(); 41 | } 42 | @Override 43 | public Value ofShape(int[] sh) { 44 | return SingleItemArr.maybe(item, sh); 45 | } 46 | 47 | @Override 48 | public Value[] valuesCopy() { 49 | return new Value[]{item}; 50 | } 51 | 52 | @Override 53 | public boolean quickDoubleArr() { 54 | return item instanceof Num; 55 | } 56 | 57 | @Override 58 | public double[] asDoubleArr() { 59 | return new double[]{ ((Num) item).num }; 60 | } 61 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/EllipsisBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.math.BigInteger; 9 | 10 | public class EllipsisBuiltin extends Builtin { 11 | @Override public String repr() { 12 | return "…"; 13 | } 14 | 15 | 16 | 17 | public Value call(Value a, Value w) { 18 | if (a instanceof BigValue || w instanceof BigValue) { 19 | BigInteger al = BigValue.bigint(a); 20 | BigInteger wl = BigValue.bigint(w); 21 | BigInteger size = al.subtract(wl).abs().add(BigInteger.ONE); 22 | int isize = BigValue.safeInt(size); 23 | if (isize==Integer.MAX_VALUE) throw new DomainError("…: expected range too large ("+a+"…"+w+")", this, w); 24 | 25 | Value[] arr = new Value[isize]; 26 | BigInteger c = al; 27 | BigInteger dir = al.compareTo(wl) < 0? BigInteger.ONE : BigValue.MINUS_ONE.i; 28 | for (int i = 0; i < isize; i++) { 29 | arr[i] = new BigValue(c); 30 | c = c.add(dir); 31 | } 32 | return new HArr(arr); 33 | } 34 | int ai = a.asInt(); 35 | int wi = w.asInt(); 36 | double[] arr = new double[Math.abs(ai-wi)+1]; 37 | if (ai>wi) { 38 | for (int i = 0; i < arr.length; i++) { 39 | arr[i] = ai - i; 40 | } 41 | } else { 42 | for (int i = 0; i < arr.length; i++) { 43 | arr[i] = ai + i; 44 | } 45 | } 46 | return new DoubleArr(arr); 47 | } 48 | } -------------------------------------------------------------------------------- /APLP5/data/ma: -------------------------------------------------------------------------------- 1 | ⎕IO←0 2 | ⎕VI←1 3 | ⎕PP←6 4 | G←P5.G 5 | P5.smooth←0 6 | P5.size ← ,⍨ 200 7 | sz ← ,⍨ 200 8 | 9 | ⍝ sqr ← (-⍥(×⍨) ⍮ 2××)/ 10 | sqr ← ((-/ *∘2) ⍮ 2××/) 11 | AM ← 40 ⍝ iteration amount 12 | b2c ← 4278190080 + 65793× 13 | CL ← { ⍝ 0-1 hue to RGB 14 | I ← 3|⍵×3 15 | p ← ⌊256×1|I 16 | P ← 255-p 17 | off ← 4278190080 ⍝ 0xff000000 18 | R G B ← 65536 256 1 19 | I<1:← off + (P×B) + (p×R) 20 | I<2:← off + (P×R) + (p×G) 21 | I<3:← off + (P×G) + (p×B) 22 | } 23 | 24 | j ← { ⍝ julia 25 | R←3⍴⊂⍬ 26 | C←0 27 | mp ← ¯1.5 + 3×P5.mpos ÷ P5.size 28 | ⍝ mp ← 1 2○ .1×P5.fc 29 | { 30 | C+←1 31 | r ← mp + sqr 2↑⍵ 32 | ⍝ o←∨/2<|r 33 | o ← 4<+/ ×⍨ r 34 | R⊢← R ,¨ (⊂(⍴⊃f)⍴CL C×.04) ,⍨ f ← o∘⌿¨ ¯2↑⍵ 35 | (~o)∘⌿¨ r,¯2↑⍵ 36 | }⍣AM ⊢ ,¨ {(¯1.5 + 3×⍵÷sz) , ⍵}⍳sz 37 | (0 0,P5.size) G.img P5.img (2⊃R) @ (2↑R) ⊢ sz⍴ b2c 0 38 | ⎕←P5.fps 39 | } 40 | 41 | 42 | op ← 0 0 43 | zm ← ÷128 ⍝ 1 44 | PS ← (⌽⍳sz)-.5×sz 45 | m ← { ⍝ mandelbrot 46 | P5.lm.p: op+← zm×(P5.pmpos - P5.mpos) × sz÷P5.size 47 | add ← (zm × PS)+op 48 | 49 | Rc Ry Rx←3⍴⊂⍬ 50 | C←0 51 | bc ic ← 0 ⍬ 52 | { 53 | S A P ← ⍵ 54 | C+← 1 55 | r ← A + sqr S 56 | o ← 4<+/ r*2 57 | ⍱o:← r A P 58 | cx cy ← o∘⌿¨ P 59 | Ry⍮← cy 60 | Rx⍮← cx 61 | Rc⍮← (⍴cx)⍴CL C×.04 62 | bc+← 1 63 | (~o)∘⌿¨¨ r A P 64 | }⍣AM ⊢ ,¨¨ (2⍴⊂ sz⍴0) add (⍳sz) 65 | (0 0,P5.size) G.img P5.img (∊Rc) @ (∊¨ Rx Ry) ⊢ sz⍴ b2c 0 66 | ⍝ ⎕←⎕PFR 67 | ⎕←P5.fps bc (∊ic) 68 | } 69 | P5.sc ← { 70 | zm÷←2*⍵ 71 | } 72 | P5.draw ← m 73 | P5.rm.c ← { 74 | P5.draw ← j 75 | } 76 | P5.mm.c ← { 77 | P5.draw ← m 78 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/SemiUBBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | public class SemiUBBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍮"; 11 | } 12 | 13 | 14 | 15 | @Override 16 | public Value call(Value w) { 17 | return new Shape1Arr(w); 18 | } 19 | 20 | public Value call(Value a, Value w) { 21 | if (a instanceof Num && w instanceof Num) { 22 | return new DoubleArr(new double[]{((Num) a).num, ((Num) w).num}); 23 | } 24 | if (a instanceof Char && w instanceof Char) { 25 | return new ChrArr(((Char) a).chr +""+ ((Char) w).chr); 26 | } 27 | return Arr.create(new Value[]{a, w}); 28 | } 29 | 30 | public Value callInv(Value w) { 31 | if (w.rank!=1 || w.shape[0]!=1) throw new DomainError("monadic ⍮⍣¯1 only works on shape 1 arrays", this, w); 32 | return w.first(); 33 | } 34 | 35 | public Value callInvW(Value a, Value w) { 36 | if (w.rank!=1 || w.shape[0]!=2) throw new DomainError("dyadic ⍮⍣¯1 only works on shape 2 arrays", this, w); 37 | if (!w.get(0).equals(a)) throw new DomainError("dyadic ⍮⍣¯1 expected ⍺≡⊃⍵", this, w); 38 | return w.get(1); 39 | } 40 | public Value callInvA(Value a, Value w) { 41 | if (a.rank!=1 || a.shape[0]!=2) throw new DomainError("dyadic ⍮⍨⍣¯1 only works on shape 2 ⍺ arrays", this, a); 42 | if (!a.get(1).equals(w)) throw new DomainError("dyadic ⍮⍨⍣¯1 expected ⍵≡⊃⌽⍺", this, a); 43 | return a.get(0); 44 | } 45 | } -------------------------------------------------------------------------------- /src/APL/SimpleIndexer.java: -------------------------------------------------------------------------------- 1 | package APL; 2 | 3 | import java.util.Iterator; 4 | 5 | public class SimpleIndexer implements Iterable { // todo this is horrible (or at least i think so, i can't be bothered to understand it) 6 | private final int[] shape; 7 | private final int[] chosen; 8 | private final int[] shapeTP; 9 | private final int len; 10 | 11 | public SimpleIndexer(int[] shape, int[] chosen) { 12 | this.shape = shape; 13 | this.chosen = chosen; 14 | len = shape.length; 15 | this.shapeTP = new int[len+1]; 16 | int p = 1; 17 | shapeTP[len] = 1; 18 | for (int i = len-1; i >= 0; i--) { 19 | p*= shape[i]; 20 | shapeTP[i] = p; 21 | } 22 | } 23 | 24 | @Override public Iterator iterator() { 25 | boolean empty = true; 26 | for (int i : chosen) { 27 | if (i != 0) { empty = false; break; } 28 | } 29 | boolean finalEmpty = empty & chosen.length!=0; 30 | //noinspection Convert2Diamond java 8 31 | return new Iterator() { 32 | int index = 0; 33 | boolean hasNext = !finalEmpty; 34 | @Override public boolean hasNext() { 35 | return hasNext; 36 | } 37 | 38 | @Override public Integer next() { 39 | int ret = index; 40 | index++; 41 | int d = len-1; 42 | while (d!=-1) { 43 | if (index%shapeTP[d] == (chosen[d]*shapeTP[d+1])%shapeTP[d]) { 44 | index+= (shape[d] - chosen[d])*shapeTP[d+1]; 45 | d--; 46 | } 47 | else break; 48 | } 49 | if (d==-1) hasNext =false; 50 | return ret; 51 | } 52 | }; 53 | } 54 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/PlusBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.Builtin; 6 | 7 | 8 | public class PlusBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "+"; 11 | } 12 | 13 | 14 | 15 | public Value identity() { 16 | return Num.ZERO; 17 | } 18 | 19 | public Value call(Value w) { 20 | return allM(v -> { 21 | if (!(v instanceof Num)) throw new DomainError("Conjugating a non-number", this, w); // TODO decide whether this should exist 22 | return ((Num)v).conjugate(); 23 | }, w); 24 | } 25 | 26 | public static final D_NNeN DNF = new D_NNeN() { 27 | public double on(double a, double w) { 28 | return a + w; 29 | } 30 | public void on(double[] res, double a, double[] w) { 31 | for (int i = 0; i < w.length; i++) res[i] = a + w[i]; 32 | } 33 | public void on(double[] res, double[] a, double w) { 34 | for (int i = 0; i < a.length; i++) res[i] = a[i] + w; 35 | } 36 | public void on(double[] res, double[] a, double[] w) { 37 | for (int i = 0; i < a.length; i++) res[i] = a[i] + w[i]; 38 | } 39 | public Value call(BigValue a, BigValue w) { 40 | return new BigValue(a.i.add(w.i)); 41 | } 42 | }; 43 | public Value call(Value a, Value w) { 44 | return numD(DNF, a, w); 45 | } 46 | public Value callInv(Value w) { return call(w); } 47 | public Value callInvW(Value a, Value w) { 48 | return numD(MinusBuiltin.DNF, w, a); 49 | } 50 | 51 | @Override public Value callInvA(Value a, Value w) { 52 | return callInvW(w, a); 53 | } 54 | } -------------------------------------------------------------------------------- /src/APL/tokenizer/types/LineTok.java: -------------------------------------------------------------------------------- 1 | package APL.tokenizer.types; 2 | 3 | import APL.tokenizer.Token; 4 | 5 | import java.util.*; 6 | 7 | public class LineTok extends TokArr { 8 | private Integer colonPos; 9 | 10 | public LineTok(String raw, int spos, int epos, List tokens) { 11 | super(raw, spos, epos, tokens); 12 | } 13 | 14 | public static LineTok inherit(List tokens) { 15 | Token fst = tokens.get(0); 16 | return new LineTok(fst.raw, fst.spos, tokens.get(tokens.size()-1).epos, tokens); 17 | } 18 | 19 | public static LineTok inherit(Token tk) { 20 | ArrayList a = new ArrayList<>(); 21 | a.add(tk); 22 | return new LineTok(tk.raw, tk.spos, tk.epos, a); 23 | } 24 | 25 | public int colonPos() { 26 | if (colonPos == null) { 27 | colonPos = -1; 28 | for (int i = 0; i < tokens.size(); i++) { 29 | if (tokens.get(i) instanceof ColonTok) { 30 | colonPos = i; 31 | break; 32 | } 33 | } 34 | } 35 | return colonPos; 36 | } 37 | private Integer eguardPos; 38 | public int eguardPos() { 39 | if (eguardPos == null) { 40 | eguardPos = -1; 41 | for (int i = 0; i < tokens.size(); i++) { 42 | if (tokens.get(i) instanceof DColonTok) { 43 | eguardPos = i; 44 | break; 45 | } 46 | } 47 | } 48 | return eguardPos; 49 | } 50 | 51 | @Override public String toRepr() { 52 | StringBuilder s = new StringBuilder(); 53 | boolean tail = false; 54 | for (var v : tokens) { 55 | if (tail) s.append(" "); 56 | s.append(v.toRepr()); 57 | tail = true; 58 | } 59 | return s.toString(); 60 | } 61 | } -------------------------------------------------------------------------------- /AndroidIDE/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Download APK](https://github.com/dzaima/APL/releases) 4 | 5 | Execute `:h` in the app for a list of commands. 6 | 7 | By default, this executes code as dzaima/APL. Other options of interpretation: 8 | 9 | ```apl 10 | ⍝ TryAPL: 11 | :i TryAPL ⍝ requires an internet connection 12 | ⍝ Dyalog through RIDE: 13 | $ RIDE_INIT=SERVE:desktopIp:4502 dyalog -nokbd ⍝ on a desktop 14 | :i ride desktopIp ⍝ in the app, after starting the server; another port can be chosen if needed 15 | ⍝ for completeness sake, another separate dzaima/APL interpreter can be opened with: 16 | :i dzaima 17 | ``` 18 | 19 | 20 | --- 21 | 22 | 23 | 24 | Compile for android: 25 | 26 | 1. generate the dzaima/APL interpreter jar file - run `./convert.py` in `app/`. 27 | 2. in PS.pde, change start to `/*` 28 | 3. either run in Android Mode with a device connected, or File → Export Signed Package to generate an APK. 29 | 30 | Alternatively, Processing runs the project in Java mode just fine (keyboard input may be a bit funky though). 31 | 32 | --- 33 | 34 | ``` 35 | swipe on characters to enter ones around it 36 | = - evaluate/save 37 | ⇧ - shift (caps letters, select with «») 38 | C - clear input field 39 | M - go to matching bracket 40 | 41 | K - open virtual keyboard 42 | # - default layout 43 | A - layout with a-z 44 | N - layout with numbers at top-level 45 | F - extra function layout 46 | X - close tab (saves where applicable) 47 | 48 | ↶↷ - undo/redo 49 | ▲▼ - move up/down or trough REPL history 50 | ^C/^V - copy/paste 51 | 52 | :h - list commands (do ":h kb" to view the above text) 53 | ``` 54 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/EQBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.BitArr; 5 | import APL.types.functions.Builtin; 6 | 7 | 8 | public class EQBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "="; 11 | } 12 | 13 | 14 | 15 | private static final D_NNeB DNF = new D_NNeB() { 16 | public boolean on(double a, double w) { 17 | return a == w; 18 | } 19 | public void on(BitArr.BA res, double a, double[] w) { 20 | for (double cw : w) res.add(a == cw); 21 | } 22 | public void on(BitArr.BA res, double[] a, double w) { 23 | for (double ca : a) res.add(ca == w); 24 | } 25 | public void on(BitArr.BA res, double[] a, double[] w) { 26 | for (int i = 0; i < a.length; i++) res.add(a[i] == w[i]); 27 | } 28 | public Value call(BigValue a, BigValue w) { 29 | return a.equals(w)? Num.ONE : Num.ZERO; 30 | } 31 | }; 32 | private static final D_BB DBF = new D_BB() { 33 | @Override public Value call(boolean a, BitArr w) { 34 | if (a) return w; 35 | return TildeBuiltin.call(w); 36 | } 37 | @Override public Value call(BitArr a, boolean w) { 38 | if (w) return a; 39 | return TildeBuiltin.call(a); 40 | } 41 | @Override public Value call(BitArr a, BitArr w) { 42 | BitArr.BC bc = BitArr.create(w.shape); 43 | for (int i = 0; i < bc.arr.length; i++) bc.arr[i] = ~(a.arr[i] ^ w.arr[i]); 44 | return bc.finish(); 45 | } 46 | }; 47 | 48 | public Value call(Value a, Value w) { 49 | return ncbaD(DNF, DBF, (ca, cw) -> ca==cw? Num.ONE : Num.ZERO, (ca, cw) -> ca.equals(cw)? Num.ONE : Num.ZERO, a, w); 50 | } 51 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/NEBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.BitArr; 5 | import APL.types.functions.Builtin; 6 | 7 | 8 | public class NEBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "≠"; 11 | } 12 | 13 | 14 | 15 | private static final D_NNeB DNF = new D_NNeB() { 16 | public boolean on(double a, double w) { 17 | return a != w; 18 | } 19 | public void on(BitArr.BA res, double a, double[] w) { 20 | for (double cw : w) res.add(a != cw); 21 | } 22 | public void on(BitArr.BA res, double[] a, double w) { 23 | for (double ca : a) res.add(ca != w); 24 | } 25 | public void on(BitArr.BA res, double[] a, double[] w) { 26 | for (int i = 0; i < a.length; i++) res.add(a[i] != w[i]); 27 | } 28 | public Value call(BigValue a, BigValue w) { 29 | return a.equals(w)? Num.ZERO : Num.ONE; 30 | } 31 | }; 32 | private static final D_BB DBF = new D_BB() { 33 | @Override public Value call(boolean a, BitArr w) { 34 | if (a) return TildeBuiltin.call(w); 35 | return w; 36 | } 37 | @Override public Value call(BitArr a, boolean w) { 38 | if (w) return TildeBuiltin.call(a); 39 | return a; 40 | } 41 | @Override public Value call(BitArr a, BitArr w) { 42 | BitArr.BC bc = BitArr.create(w.shape); 43 | for (int i = 0; i < bc.arr.length; i++) bc.arr[i] = a.arr[i] ^ w.arr[i]; 44 | return bc.finish(); 45 | } 46 | }; 47 | 48 | public Value call(Value a, Value w) { 49 | return ncbaD(DNF, DBF, (ca, cw) -> ca!=cw? Num.ONE : Num.ZERO, (ca, cw) -> ca.equals(cw)? Num.ZERO : Num.ONE, a, w); 50 | } 51 | } -------------------------------------------------------------------------------- /app/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # horrible code that shouldn't exist 3 | from subprocess import call 4 | import glob 5 | import os, re 6 | 7 | os.system('rm -rf ./APL/src') 8 | os.system('rm -rf ./build/') 9 | os.system('cp -rf ../src ./APL/src') 10 | 11 | print('copied') 12 | 13 | rtp='Float[][][]' 14 | for filename in glob.iglob('APL/src/APL/**/*.java', recursive=True): 15 | with open(filename, 'r') as myfile: 16 | data=myfile.read() 17 | data = re.sub(' var ', ' '+rtp+' ', data) 18 | data = re.sub(r'\(var ', '('+rtp+' ', data) 19 | with open(filename, 'w') as myfile: 20 | myfile.write(data) 21 | print('replaced') 22 | for i in range(3): 23 | 24 | 25 | os.system('APL/build -Xdiags:verbose 2> err'); 26 | count = 0 27 | with open('err', 'r') as myfile: 28 | for line in myfile: 29 | if ((' cannot be converted to '+rtp) in line): 30 | name, ln, _1, _2, rest = line.split(':'); 31 | ln = int(ln) 32 | # error example: 33 | # APL/src/APL/Main.java:182: error: incompatible types: Token cannot be converted to Float[][][] 34 | # path:ln:error:IT: Token cannot be converted to Float[][][] 35 | tp = rest.split(' cannot be converted to ')[0]; 36 | if ('Float' not in tp): 37 | count+= 1; 38 | with open(name, 'r') as myfile: 39 | data=myfile.read() 40 | data = data.split('\n') 41 | data[ln-1] = data[ln-1].replace(rtp, tp) 42 | data = '\n'.join(data) 43 | with open(name, 'w') as myfile: 44 | myfile.write(data) 45 | # if (('error: incompatible types: cannot infer type arguments for') in line): TODO 46 | 47 | print("left:", count) 48 | os.system('./build8'); 49 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/MinusBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | public class MinusBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "-"; 9 | } 10 | 11 | 12 | 13 | static final NumMV NF = new NumMV() { 14 | public Value call(Num n) { 15 | return n.negate(); 16 | } 17 | public void call(double[] res, double[] a) { 18 | for (int i = 0; i < a.length; i++) res[i] = -a[i]; 19 | } 20 | public Value call(BigValue w) { 21 | return new BigValue(w.i.negate()); 22 | } 23 | }; 24 | 25 | public Value call(Value w) { 26 | return numChrM(NF, Char::swap, w); 27 | } 28 | 29 | public static final D_NNeN DNF = new D_NNeN() { 30 | public double on(double a, double w) { 31 | return a - w; 32 | } 33 | public void on(double[] res, double a, double[] w) { 34 | for (int i = 0; i < w.length; i++) res[i] = a - w[i]; 35 | } 36 | public void on(double[] res, double[] a, double w) { 37 | for (int i = 0; i < a.length; i++) res[i] = a[i] - w; 38 | } 39 | public void on(double[] res, double[] a, double[] w) { 40 | for (int i = 0; i < a.length; i++) res[i] = a[i] - w[i]; 41 | } 42 | public Value call(BigValue a, BigValue w) { 43 | return new BigValue(a.i.subtract(w.i)); 44 | } 45 | }; 46 | 47 | public Value call(Value a, Value w) { 48 | return numD(DNF, a, w); 49 | } 50 | public Value callInv(Value w) { return call(w); } 51 | public Value callInvW(Value a, Value w) { return call(a, w); } 52 | public Value callInvA(Value a, Value w) { 53 | return numD(PlusBuiltin.DNF, a, w); 54 | } 55 | } -------------------------------------------------------------------------------- /AndroidIDE/Drawable.pde: -------------------------------------------------------------------------------- 1 | static class Drawable { 2 | int x, y; 3 | int w, h; 4 | boolean visible; 5 | Drawable(int x, int y, int w, int h) { 6 | this.x = x; 7 | this.y = y; 8 | this.w = w; 9 | this.h = h; 10 | screen.add(this); 11 | } 12 | void tick() { } // only update things that changed. For global things called every frame, even if hidden 13 | void redraw() { } // redraw everything. Should be pure and callable at any point any time (where P5 drawing is allowed); called at least on window/screen resizing/rotating 14 | void resized() { } 15 | void mouseWheel(int dir) { } 16 | void move(int x, int y) { 17 | this.x = x; 18 | this.y = y; 19 | if (visible) redraw(); 20 | } 21 | void resize(int w, int h) { 22 | this.w = w; 23 | this.h = h; 24 | if (visible) redraw(); 25 | resized(); 26 | } 27 | void move(int x, int y, int w, int h) { 28 | this.x = x; 29 | this.y = y; 30 | this.w = w; 31 | this.h = h; 32 | if (visible) redraw(); 33 | resized(); 34 | } 35 | void show() { 36 | if (!visible) redraw(); 37 | visible = true; 38 | } 39 | void hide() { 40 | visible = false; 41 | } 42 | void align(int dir) { 43 | switch(dir) { 44 | case BOTTOM: move(x, d.height-h); 45 | } 46 | } 47 | final void delete() { 48 | assert screen.remove(this); 49 | visible = false; 50 | x = y = w = h = -1111111; 51 | } 52 | boolean mouseInMe() { 53 | return a.mouseX > x && a.mouseY > y && a.mouseX < x+w && a.mouseY < y+h; 54 | } 55 | boolean smouseIn() { 56 | return smouseX > x && smouseY > y && smouseX < x+w && smouseY < y+h; 57 | } 58 | void pasted(String s) { 59 | throw new Error(this+" didn't ask for a clipboard!"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/MergeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | import APL.types.arrs.DoubleArr; 7 | import APL.types.functions.Builtin; 8 | 9 | import java.util.Arrays; 10 | 11 | public class MergeBuiltin extends Builtin { 12 | 13 | public MergeBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | @Override public Value call(Value a, Value w) { 18 | if (w.rank != 1) throw new DomainError("%: ⍵ must be a vector", this, w); 19 | int IO = sc.IO; 20 | int[] sh = a.shape; 21 | int i1 = 0; 22 | boolean allds = true; 23 | for (Value v : w) { 24 | if (!Arrays.equals(v.shape, sh)) throw new DomainError("%: shape of item "+(i1+IO)+" in ⍵ didn't match ⍺ ("+Main.formatAPL(sh)+" vs "+Main.formatAPL(v.shape)+")", this, w); 25 | i1++; 26 | if (!v.quickDoubleArr()) allds = false; 27 | } 28 | // if (IO==0 && a instanceof BitArr) { TODO 29 | // 30 | // } 31 | if (allds) { 32 | double[] ds = new double[a.ia]; 33 | double[][] wds = new double[w.ia][]; 34 | for (int i = 0; i < w.ia; i++) wds[i] = w.get(i).asDoubleArr(); 35 | double[] idx = a.asDoubleArr(); 36 | for (int i = 0; i < idx.length; i++) { 37 | ds[i] = wds[(int)idx[i] - IO][i]; 38 | } 39 | if (a.rank == 0) return new Num(ds[0]); 40 | return new DoubleArr(ds, a.shape); 41 | } 42 | Value[] vs = new Value[a.ia]; 43 | double[] idx = a.asDoubleArr(); 44 | for (int i = 0; i < idx.length; i++) { 45 | vs[i] = w.get((int)idx[i] - IO).get(i); 46 | } 47 | return Arr.createL(vs, a.shape); 48 | } 49 | 50 | @Override public String repr() { 51 | return "%"; 52 | } 53 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/DivBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.Builtin; 6 | 7 | public class DivBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "÷"; 10 | } 11 | 12 | 13 | 14 | private static final NumMV NF = new NumMV() { 15 | public Value call(Num w) { 16 | return Num.ONE.divide(w); 17 | } 18 | public void call(double[] res, double[] a) { 19 | for (int i = 0; i < a.length; i++) res[i] = 1/a[i]; 20 | } 21 | public Value call(BigValue w) { 22 | throw new DomainError("reciprocal of biginteger", w); 23 | } 24 | }; 25 | public Value call(Value w) { 26 | return numM(NF, w); 27 | } 28 | 29 | private static final D_NNeN DNF = new D_NNeN() { 30 | public double on(double a, double w) { 31 | return a / w; 32 | } 33 | public void on(double[] res, double a, double[] w) { 34 | for (int i = 0; i < w.length; i++) res[i] = a / w[i]; 35 | } 36 | public void on(double[] res, double[] a, double w) { 37 | for (int i = 0; i < a.length; i++) res[i] = a[i] / w; 38 | } 39 | public void on(double[] res, double[] a, double[] w) { 40 | for (int i = 0; i < a.length; i++) res[i] = a[i] / w[i]; 41 | } 42 | public Value call(BigValue a, BigValue w) { 43 | return new BigValue(a.i.divide(w.i)); 44 | } 45 | }; 46 | public Value call(Value a0, Value w0) { 47 | return numD(DNF, a0, w0); 48 | } 49 | 50 | public Value callInv(Value w) { return call(w); } 51 | public Value callInvW(Value a, Value w) { return call(a, w); } 52 | 53 | @Override public Value callInvA(Value a, Value w) { 54 | return numD(MulBuiltin.DNF, a, w); 55 | } 56 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/InvertBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.errors.NYIError; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | 7 | public class InvertBuiltin extends Mop { // separate ⍵-inverse (equal to f⍣¯1) 8 | 9 | public Value call(Obj f, Value w, DerivedMop derv) { 10 | Fun ff = isFn(f); 11 | return ff.callInv(w); 12 | } 13 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 14 | Fun ff = isFn(f); 15 | return ff.callInvW(a, w); 16 | } 17 | public Value callInvW(Obj f, Value a, Value w) { 18 | Fun ff = isFn(f); 19 | return ff.call(a, w); 20 | } 21 | public Value callInvA(Obj f, Value a, Value w) { 22 | throw new NYIError("InvertBuiltin invert ⍺", this); 23 | } 24 | 25 | public static Fun invertM(Fun f) { 26 | return new Fun() { 27 | public String repr() { return f.repr()+"⍣¯1"; } 28 | public Value call(Value w) { 29 | return f.callInv(w); 30 | } 31 | }; 32 | } 33 | public static Fun invertW(Fun f) { 34 | return new Fun() { 35 | public String repr() { return f.repr()+"⍣¯1"; } 36 | public Value call(Value a, Value w) { 37 | return f.callInvW(a, w); 38 | } 39 | 40 | public Value callInvW(Value a, Value w) { 41 | return f.call(a, w); 42 | } 43 | }; 44 | } 45 | public static Fun invertA(Fun f) { 46 | return new Fun() { 47 | public String repr() { return f.repr()+"⍨⍣¯1⍨"; } 48 | public Value call(Value a, Value w) { 49 | return f.callInvA(a, w); 50 | } 51 | 52 | public Value callInvA(Value a, Value w) { 53 | return f.call(a, w); 54 | } 55 | }; 56 | } 57 | 58 | public String repr() { 59 | return "¯"; 60 | } 61 | } -------------------------------------------------------------------------------- /src/APL/types/functions/userDefined/Dfn.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.userDefined; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.tokenizer.types.DfnTok; 6 | import APL.types.*; 7 | import APL.types.functions.VarArr; 8 | 9 | public class Dfn extends Fun { 10 | public final DfnTok code; 11 | Dfn(DfnTok t, Scope sc) { 12 | super(sc); 13 | code = t; 14 | } 15 | public Value call(Value w) { 16 | Obj o = callObj(w); 17 | if (o instanceof Value) return (Value) o; 18 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 19 | } 20 | public Obj callObj(Value w) { 21 | Main.printdbg(sc, "dfn call", w); 22 | Scope nsc = new Scope(sc); 23 | nsc.set("⍺", new Variable(nsc, "⍺")); 24 | nsc.set("⍵", w); 25 | nsc.set("∇", this); 26 | var res = Main.execLines(code, nsc); 27 | if (res instanceof VarArr) return ((VarArr)res).get(); 28 | if (res instanceof Settable) return ((Settable)res).get(); 29 | return res; 30 | } 31 | public Value call(Value a, Value w) { 32 | Obj o = callObj(a, w); 33 | if (o instanceof Value) return (Value) o; 34 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 35 | } 36 | public Obj callObj(Value a, Value w) { 37 | Main.printdbg(sc, "dfn call", a, w); 38 | Scope nsc = new Scope(sc); 39 | nsc.set("⍺", a); 40 | nsc.set("⍵", w); 41 | nsc.set("∇", this); 42 | nsc.alphaDefined = true; 43 | var res = Main.execLines(code, nsc); 44 | if (res instanceof VarArr) return ((VarArr)res).get(); 45 | if (res instanceof Settable) return ((Settable)res).get(); 46 | return res; 47 | } 48 | public String repr() { 49 | return code.toRepr(); 50 | } 51 | 52 | public String name() { return "dfn"; } 53 | } -------------------------------------------------------------------------------- /APLP5/APLP5.pde: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.io.UnsupportedEncodingException; 3 | static final Null NULL = Null.NULL; 4 | Scope global; 5 | APLP5 thisobj = this; 6 | boolean inSettings = false; 7 | APLGraphics mainGraphics; 8 | P5 p5; 9 | void settings() { 10 | Main.colorful = false; 11 | mainGraphics = new APLGraphics(); 12 | inSettings = true; 13 | if (args == null) args = new String[]{"ma"}; 14 | 15 | global = new Scope(); 16 | String s; 17 | try { 18 | s = new String(loadBytes(args[0]), "UTF-8"); 19 | } catch (UnsupportedEncodingException e) { 20 | throw new DomainError("failed to load file"); 21 | } 22 | p5 = new P5(); 23 | global.set("P5", p5); 24 | p5.lm = new MouseButton(LEFT); 25 | p5.rm = new MouseButton(RIGHT); 26 | p5.mm = new MouseButton(CENTER); 27 | //Main.debug = true; 28 | exec(s); 29 | } 30 | void setup() { 31 | mainGraphics.g = g; 32 | inSettings = false; 33 | call(setup, arr(mouseX, mouseY)); 34 | } 35 | void exec(String s) { 36 | try { 37 | APL.Main.exec(s, global); 38 | } catch(APLError e) { 39 | e.print(); 40 | } catch (Throwable e) { 41 | e.printStackTrace(); 42 | throw e; 43 | } 44 | } 45 | void call(Fun f, Value a, Value w) { 46 | if (f == null) return; 47 | try { 48 | f.callObj(a, w); 49 | } catch (APLError e) { 50 | e.print(); 51 | e.printStackTrace(); 52 | throw e; 53 | } catch (Throwable e) { 54 | new NotErrorError("last known function:", null).print(); 55 | e.printStackTrace(); 56 | throw e; 57 | } 58 | } 59 | void call(Fun f, Value w) { 60 | if (f == null) return; 61 | try { 62 | f.callObj(w); 63 | } catch (APLError e) { 64 | e.print(); 65 | e.printStackTrace(); 66 | throw e; 67 | } catch (Throwable e) { 68 | e.printStackTrace(); 69 | throw e; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/APL/types/functions/trains/Fork.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.trains; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | 6 | public class Fork extends Fun { 7 | private final Obj f; 8 | private final Fun g, h; 9 | public Fork(Obj f, Fun g, Fun h) { 10 | this.f = f; 11 | this.g = g; 12 | this.h = h; 13 | } 14 | 15 | public Value call(Value w) { 16 | Value right = h.call(w); 17 | Value left = !(f instanceof Fun)? (Value) f : ((Fun) f).call(w); 18 | return g.call(left, right); 19 | } 20 | public Value callInv(Value w) { 21 | if (f instanceof Fun) throw new DomainError("(f g h)A cannot be inverted", this); 22 | Value left = (Value) f; 23 | // System.out.println(f+";"+g+";"+h); 24 | return h.callInv(g.callInvW(left, w)); 25 | } 26 | public Value call(Value a, Value w) { 27 | Value right = h.call(a, w); 28 | Value left = !(f instanceof Fun)? (Value) f : ((Fun) f).call(a, w); 29 | return g.call(left, right); 30 | } 31 | 32 | public Value callInvW(Value a, Value w) { 33 | if (f instanceof Fun) throw new DomainError("A(f g h)B cannot be inverted", this); 34 | Value left = (Value) f; 35 | return h.callInvW(a, g.callInvW(left, w)); 36 | } 37 | 38 | public Value callInvA(Value a, Value w) { 39 | if (f instanceof Fun) throw new DomainError("A(f g h)B cannot be inverted", this); 40 | return h.callInvA(g.callInvW((Value) f, a), w); 41 | } 42 | 43 | public String repr() { 44 | return "("+f+" "+g+" "+h+")"; 45 | } 46 | 47 | public Value under(Obj o, Value w) { 48 | if (!(f instanceof Value)) throw new DomainError("(f g h)A cannot be inverted", this); 49 | Value fa = (Value) f; 50 | return h.under(new Fun() { public String repr() { return g.repr(); } 51 | public Value call(Value w) { 52 | return g.underW(o, fa, w); 53 | } 54 | }, w); 55 | } 56 | } -------------------------------------------------------------------------------- /src/APL/types/functions/trains/Atop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.trains; 2 | 3 | import APL.errors.SyntaxError; 4 | import APL.types.*; 5 | 6 | public class Atop extends Fun { 7 | private final Obj g; 8 | private final Fun h; 9 | public Atop(Obj g, Fun h) { 10 | this.g = g; 11 | this.h = h; 12 | } 13 | 14 | public Value call(Value w) { 15 | if (g instanceof Fun) return ((Fun) g).call(h.call(w)); 16 | return h.call((Value) g, w); 17 | } 18 | // public Obj callInvW(Value a, Value w) { 19 | // if (!(a instanceof Value)) throw new DomainError(""); 20 | // } 21 | public Value callInv(Value w) { 22 | // if (g instanceof Fun) return ((Fun) g).callInv((Value) h.callInv(w)); 23 | if (g instanceof Fun) return h.callInv(((Fun) g).callInv(w)); 24 | return h.callInvW((Value) g, w); 25 | } 26 | public Value call(Value a, Value w) { 27 | if (!(g instanceof Fun)) throw new SyntaxError("dyadically calling an A f train"); 28 | return ((Fun) g).call(h.call(a, w)); 29 | } 30 | 31 | public Value callInvW(Value a, Value w) { 32 | if (!(g instanceof Fun)) throw new SyntaxError("inverting a dyadically called A f train"); 33 | return h.callInvW(a, ((Fun) g).callInv(w)); 34 | } 35 | 36 | public Value callInvA(Value a, Value w) { 37 | if (!(g instanceof Fun)) throw new SyntaxError("inverting a dyadically called A f train"); 38 | return h.callInvA(((Fun) g).callInv(a), w); 39 | } 40 | 41 | public Value under(Obj o, Value w) { 42 | if (g instanceof Fun) { 43 | Fun gf = (Fun) g; 44 | return h.under(new Fun() { public String repr() { return gf.repr(); } 45 | public Value call(Value w) { 46 | return gf.under(o, w); 47 | } 48 | }, w); 49 | } else { 50 | return h.underW(o, (Value) g, w); 51 | } 52 | } 53 | 54 | @Override public String repr() { 55 | return "("+g+" "+h+")"; 56 | } 57 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/RootBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.functions.Builtin; 5 | 6 | public class RootBuiltin extends Builtin { 7 | @Override public String repr() { 8 | return "√"; 9 | } 10 | 11 | 12 | 13 | private static final NumMV NF = new NumMV() { 14 | public Value call(Num w) { 15 | return w.root(Num.NUMS[2]); 16 | } 17 | public void call(double[] res, double[] a) { 18 | for (int i = 0; i < a.length; i++) res[i] = Math.sqrt(a[i]); 19 | } 20 | }; 21 | private static final NumMV NFi = new NumMV() { 22 | public Value call(Num w) { 23 | return Num.of(w.num*w.num); 24 | } 25 | public void call(double[] res, double[] a) { 26 | for (int i = 0; i < a.length; i++) res[i] = a[i]*a[i]; 27 | } 28 | }; 29 | public Value call(Value w) { 30 | return numM(NF, w); 31 | } 32 | public Value callInv(Value w) { 33 | return numM(NFi, w); 34 | } 35 | 36 | public static final D_NNeN DNF = new D_NNeN() { 37 | public double on(double a, double w) { 38 | return Math.pow(w, 1/a); 39 | } 40 | public void on(double[] res, double a, double[] w) { 41 | double pow = 1/a; 42 | for (int i = 0; i < w.length; i++) res[i] = Math.pow(w[i], pow); 43 | } 44 | public void on(double[] res, double[] a, double w) { 45 | for (int i = 0; i < a.length; i++) res[i] = Math.pow(w, 1/a[i]); 46 | } 47 | public void on(double[] res, double[] a, double[] w) { 48 | for (int i = 0; i < a.length; i++) res[i] = Math.pow(w[i], 1/a[i]); 49 | } 50 | }; 51 | public Value call(Value a0, Value w0) { 52 | return numD(DNF, a0, w0); 53 | } 54 | 55 | public Value callInvW(Value a, Value w) { 56 | return numD(StarBuiltin.DNF, w, a); 57 | } 58 | public Value callInvA(Value a, Value w) { 59 | return numD(LogBuiltin.DNF, a, w); 60 | } 61 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/OverBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | import APL.types.functions.builtins.fns.DepthBuiltin; 7 | 8 | public class OverBuiltin extends Dop { 9 | @Override public String repr() { 10 | return "⍥"; 11 | } 12 | 13 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 14 | Fun aaf = isFn(aa, '⍶'); 15 | if (ww instanceof Value) { 16 | int d = ((Value) ww).asInt(); 17 | return on(derv, aaf, d, w); 18 | } else { 19 | Fun wwf = isFn(ww, '⍹'); 20 | return aaf.call(wwf.call(w)); 21 | } 22 | } 23 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 24 | Fun f = isFn(aa, '⍶'); 25 | Fun g = isFn(ww, '⍹'); 26 | return g.callInv(f.callInvW(g.call(a), w)); 27 | } 28 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { 29 | Fun f = isFn(aa, '⍶'); 30 | Fun g = isFn(ww, '⍹'); 31 | return g.callInv(f.callInvA(a, g.call(w))); 32 | } 33 | 34 | public static Value on(Fun caller, Fun f, int d, Value w) { 35 | int ld = DepthBuiltin.lazy(w); 36 | if (ld==d || ld <= -d) { 37 | int fd = DepthBuiltin.full(w); 38 | if (d>0 && d!=fd) throw new DomainError(caller+": can't match a depth " + fd + " array", caller, w); 39 | if (d <= fd) { 40 | return f.call(w); 41 | } 42 | } 43 | if (d>0 && ld < d) throw new DomainError(caller+": can't match a depth "+DepthBuiltin.full(w)+" array", caller, w); 44 | Value[] res = new Value[w.ia]; 45 | for (int i = 0; i < res.length; i++) { 46 | res[i] = on(caller, f, d, w.get(i)); 47 | } 48 | return Arr.createL(res, w.shape); 49 | } 50 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 51 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 52 | return aaf.call(wwf.call(a), wwf.call(w)); 53 | } 54 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/TransposeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Indexer; 4 | import APL.types.*; 5 | import APL.types.arrs.DoubleArr; 6 | import APL.types.functions.Builtin; 7 | 8 | public class TransposeBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍉"; 11 | } 12 | 13 | 14 | 15 | public Value call(Value w) { 16 | if (w.scalar()) return w; 17 | if (w instanceof DoubleArr) { 18 | double[] dw = w.asDoubleArr(); 19 | double[] res = new double[w.ia]; 20 | int[] sh = new int[w.rank]; 21 | for (int i = 0; i < w.rank; i++) { 22 | sh[i] = w.shape[w.rank - i - 1]; 23 | } 24 | if (w.rank == 2) { 25 | int ww = w.shape[0]; 26 | int wh = w.shape[1]; 27 | int ip = 0; 28 | for (int x = 0; x < ww; x++) { 29 | int op = x; 30 | for (int y = 0; y < wh; y++) { 31 | res[op] = dw[ip++]; 32 | op+= ww; 33 | } 34 | } 35 | } else { 36 | int ci = 0; 37 | for (int[] c : new Indexer(w.shape, 0)) { 38 | int[] nc = new int[w.rank]; 39 | for (int i = 0; i < w.rank; i++) { 40 | nc[i] = c[w.rank - i - 1]; 41 | } 42 | res[Indexer.fromShape(sh, nc, 0)] = dw[ci++]; 43 | } 44 | } 45 | return new DoubleArr(res, sh); 46 | } 47 | Value[] arr = new Value[w.ia]; 48 | int[] ns = new int[w.rank]; 49 | for (int i = 0; i < w.rank; i++) { 50 | ns[i] = w.shape[w.rank - i - 1]; 51 | } 52 | for (int[] c : new Indexer(w.shape, 0)) { 53 | int[] nc = new int[w.rank]; 54 | for (int i = 0; i < w.rank; i++) { 55 | nc[i] = c[w.rank - i - 1]; 56 | } 57 | arr[Indexer.fromShape(ns, nc, 0)] = w.simpleAt(c); 58 | } 59 | return Arr.create(arr, ns); 60 | } 61 | public Value callInv(Value w) { 62 | return call(w); 63 | } 64 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/ScanBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.Main; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | import APL.types.arrs.DoubleArr; 7 | import APL.types.functions.*; 8 | 9 | public class ScanBuiltin extends Mop { 10 | @Override public String repr() { 11 | return "\\"; 12 | } 13 | 14 | public Value call(Obj aa, Value w, DerivedMop derv) { 15 | Fun aaf = isFn(aa); 16 | // TODO ranks 17 | if (w.rank != 1) throw new NYIError("\\: unimplemented for rank≠1 ("+Main.formatAPL(w.shape)+" ≡ ⍴⍵)"); 18 | if (w.ia == 0) return w; 19 | Value c = w.get(0); 20 | Value[] res = new Value[w.ia]; 21 | res[0] = c; 22 | for (int i = 1; i 1) throw new RankError("\\: rank of ⍵ should be less than 2 (was "+w.rank+")", this); 35 | 36 | if (w.quickDoubleArr()) { 37 | Value[] res = new Value[len-n+1]; 38 | double[] wa = w.asDoubleArr(); 39 | for (int i = 0; i < res.length; i++) { 40 | double[] curr = new double[n]; 41 | System.arraycopy(wa, i, curr, 0, n); 42 | res[i] = aaf.call(new DoubleArr(curr)); 43 | } 44 | return Arr.create(res); 45 | } 46 | 47 | Value[] res = new Value[len-n+1]; 48 | Value[] wa = w.values(); 49 | for (int i = 0; i < res.length; i++) { 50 | Value[] curr = new Value[n]; 51 | // for (int j = 0; j < n; j++) curr[j] = wa[i + j]; 52 | System.arraycopy(wa, i, curr, 0, n); 53 | res[i] = aaf.call(Arr.create(curr)); 54 | } 55 | return Arr.create(res); 56 | } 57 | } -------------------------------------------------------------------------------- /src/APL/types/functions/userDefined/Dmop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.userDefined; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.tokenizer.types.DfnTok; 6 | import APL.types.*; 7 | import APL.types.functions.*; 8 | 9 | 10 | public class Dmop extends Mop { 11 | public final DfnTok code; 12 | 13 | @Override public String repr() { 14 | return code.toRepr(); 15 | } 16 | 17 | Dmop(DfnTok t, Scope sc) { 18 | super(sc); 19 | code = t; 20 | } 21 | 22 | public Value call(Obj f, Value w, DerivedMop derv) { 23 | Obj o = callObj(f, w, derv); 24 | if (o instanceof Value) return (Value) o; 25 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 26 | } 27 | public Obj callObj(Obj aa, Value w, DerivedMop derv) { 28 | Main.printdbg(sc, "dmop call", w); 29 | Scope nsc = new Scope(sc); 30 | nsc.set("⍶", aa); 31 | nsc.set("⍺", new Variable(nsc, "⍺")); 32 | nsc.set("⍵", w); 33 | nsc.set("∇", derv); 34 | var res = Main.execLines(code, nsc); 35 | if (res instanceof VarArr) return ((VarArr)res).get(); 36 | if (res instanceof Settable) return ((Settable)res).get(); 37 | return res; 38 | } 39 | 40 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 41 | Obj o = callObj(f, a, w, derv); 42 | if (o instanceof Value) return (Value) o; 43 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 44 | } 45 | public Obj callObj(Obj aa, Value a, Value w, DerivedMop derv) { 46 | Main.printdbg(sc, "dmop call", a, w); 47 | Scope nsc = new Scope(sc); 48 | nsc.set("⍶", aa); 49 | nsc.set("⍺", a); 50 | nsc.set("⍵", w); 51 | nsc.set("∇", derv); 52 | nsc.alphaDefined = true; 53 | var res = Main.execLines(code, nsc); 54 | if (res instanceof VarArr) return ((VarArr)res).get(); 55 | if (res instanceof Settable) return ((Settable)res).get(); 56 | return res; 57 | } 58 | } -------------------------------------------------------------------------------- /src/APL/types/arrs/ChrArr.java: -------------------------------------------------------------------------------- 1 | package APL.types.arrs; 2 | 3 | import APL.Main; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | 7 | public class ChrArr extends Arr { 8 | public String s; 9 | 10 | public ChrArr(String s) { 11 | super(new int[]{s.length()}, s.length(), 1); 12 | this.s = s; 13 | } 14 | public ChrArr(String s, int[] sh) { 15 | super(sh, s.length(), sh.length); 16 | assert Main.enclosePrimitives || sh.length != 0; 17 | this.s = s; 18 | } 19 | 20 | public ChrArr(char[] arr, int[] sh) { 21 | this(new String(arr), sh); 22 | } 23 | public ChrArr(char[] arr) { 24 | this(new String(arr)); 25 | } 26 | 27 | 28 | @Override 29 | public int[] asIntArrClone() { 30 | throw new DomainError("Using character array as integer array", this); 31 | } 32 | 33 | @Override 34 | public int asInt() { 35 | throw new DomainError("Using character array as integer", this); 36 | } 37 | 38 | @Override 39 | public Value get(int i) { 40 | return Char.of(s.charAt(i)); 41 | } 42 | 43 | @Override public Value first() { 44 | if (ia > 0) return Char.of(s.charAt(0)); 45 | return Char.SPACE; 46 | } 47 | @Override 48 | public String asString() { 49 | if (rank > 1) throw new DomainError("Using rank "+rank+" character array as string", this); 50 | return s; 51 | } 52 | 53 | public Value prototype() { 54 | return Char.SPACE; 55 | } 56 | public Value safePrototype() { 57 | return Char.SPACE; 58 | } 59 | 60 | @Override 61 | public Value ofShape(int[] sh) { 62 | if (sh.length==0 && !Main.enclosePrimitives) return get(0); 63 | return new ChrArr(s, sh); 64 | } 65 | 66 | @Override 67 | public Value squeeze() { 68 | return this; 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | if (hash == 0) { 74 | for (char c : s.toCharArray()) { 75 | hash = hash*31 + c; 76 | } 77 | hash = shapeHash(hash); 78 | } 79 | return hash; 80 | } 81 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/OrBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.BitArr; 5 | import APL.types.functions.Builtin; 6 | 7 | public class OrBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "∨"; 10 | } 11 | 12 | 13 | 14 | public Value identity() { 15 | return Num.ZERO; 16 | } 17 | 18 | public Value call(Value w) { 19 | if (w instanceof BitArr) { 20 | BitArr wb = (BitArr) w; 21 | wb.setEnd(false); 22 | for (long l : wb.arr) if (l != 0L) return Num.ONE; 23 | return Num.ZERO; 24 | } 25 | return new Num(Num.gcd(w.asDoubleArr())); 26 | } 27 | 28 | private static final D_NNeN DNF = new D_NNeN() { 29 | public double on(double a, double w) { 30 | return Num.gcd2(a, w); 31 | } 32 | public void on(double[] res, double a, double[] w) { 33 | for (int i = 0; i < w.length; i++) res[i] = Num.gcd2(a, w[i]); 34 | } 35 | public void on(double[] res, double[] a, double w) { 36 | for (int i = 0; i < a.length; i++) res[i] = Num.gcd2(a[i], w); 37 | } 38 | public void on(double[] res, double[] a, double[] w) { 39 | for (int i = 0; i < a.length; i++) res[i] = Num.gcd2(a[i], w[i]); 40 | } 41 | public Value call(BigValue a, BigValue w) { 42 | return new BigValue(a.i.gcd(w.i)); 43 | } 44 | }; 45 | 46 | private static final D_BB DBF = new D_BB() { 47 | @Override public Value call(boolean a, BitArr w) { 48 | if (a) return BitArr.fill(w, true); 49 | return w; 50 | } 51 | @Override public Value call(BitArr a, boolean w) { 52 | if (w) return BitArr.fill(a, true); 53 | return a; 54 | } 55 | @Override public Value call(BitArr a, BitArr w) { 56 | BitArr.BC bc = new BitArr.BC(a.shape); 57 | for (int i = 0; i < a.arr.length; i++) bc.arr[i] = a.arr[i] | w.arr[i]; 58 | return bc.finish(); 59 | } 60 | }; 61 | public Value call(Value a0, Value w0) { 62 | return bitD(DNF, DBF, a0, w0); 63 | } 64 | } -------------------------------------------------------------------------------- /src/APL/types/functions/userDefined/Ddop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.userDefined; 2 | 3 | import APL.*; 4 | import APL.errors.DomainError; 5 | import APL.tokenizer.types.DfnTok; 6 | import APL.types.*; 7 | import APL.types.functions.*; 8 | 9 | 10 | 11 | public class Ddop extends Dop { 12 | public final DfnTok code; 13 | 14 | @Override public String repr() { 15 | return code.toRepr(); 16 | } 17 | 18 | Ddop(DfnTok t, Scope sc) { 19 | super(sc); 20 | code = t; 21 | } 22 | 23 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 24 | Obj o = callObj(aa, ww, w, derv); 25 | if (o instanceof Value) return (Value) o; 26 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 27 | } 28 | public Obj callObj(Obj aa, Obj ww, Value w, DerivedDop derv) { 29 | Main.printdbg(sc, "ddop call", w); 30 | Scope nsc = new Scope(sc); 31 | nsc.set("⍶", aa); 32 | nsc.set("⍹", ww); 33 | nsc.set("⍺", new Variable(nsc, "⍺")); 34 | nsc.set("⍵", w); 35 | nsc.set("∇", derv); 36 | var res = Main.execLines(code, nsc); 37 | if (res instanceof VarArr) return ((VarArr)res).get(); 38 | if (res instanceof Settable) return ((Settable)res).get(); 39 | return res; 40 | } 41 | 42 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 43 | Obj o = callObj(aa, ww, a, w, derv); 44 | if (o instanceof Value) return (Value) o; 45 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 46 | } 47 | public Obj callObj(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 48 | Main.printdbg(sc, "ddop call", a, w); 49 | Scope nsc = new Scope(sc); 50 | nsc.set("⍶", aa); 51 | nsc.set("⍹", ww); 52 | nsc.set("⍺", a); 53 | nsc.set("⍵", w); 54 | nsc.set("∇", derv); 55 | nsc.alphaDefined = true; 56 | var res = Main.execLines(code, nsc); 57 | if (res instanceof VarArr) return ((VarArr)res).get(); 58 | if (res instanceof Settable) return ((Settable)res).get(); 59 | return res; 60 | } 61 | } -------------------------------------------------------------------------------- /src/APL/types/Char.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.Main; 4 | import APL.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 | 23 | public static Char of(char c) { 24 | if (c < 128) return ASCII[c]; 25 | return new Char(c); 26 | } 27 | 28 | public Char upper() { 29 | return Char.of(Character.toUpperCase(chr)); 30 | } 31 | 32 | public Char lower() { 33 | return Char.of(Character.toLowerCase(chr)); 34 | } 35 | 36 | public Char swap() { 37 | if (Character.isUpperCase(chr)) return lower(); 38 | if (Character.isLowerCase(chr)) return upper(); 39 | return Char.of(chr); 40 | } 41 | 42 | public int getCase() { 43 | return Character.isUpperCase(chr)? 1 : Character.isLowerCase(chr)? -1 : 0; 44 | } 45 | 46 | public String toString() { 47 | if (Main.quotestrings) return "'"+chr+"'"; 48 | else return String.valueOf(chr); 49 | } 50 | public String oneliner(int[] ignored) { 51 | return "'"+chr+"'"; 52 | } 53 | 54 | @Override 55 | public Value ofShape(int[] sh) { 56 | if (sh.length==0 && !Main.enclosePrimitives) return this; 57 | assert ia == Arr.prod(sh); 58 | return new ChrArr(Character.toString(chr), sh); // special because there's no quickCharArr 59 | } 60 | 61 | public int compareTo(Char v) { 62 | return Character.compare(chr, v.chr); 63 | } 64 | 65 | 66 | @Override public boolean equals(Obj c) { 67 | return c instanceof Char && chr == ((Char) c).chr; 68 | } 69 | 70 | public String asString() { 71 | return String.valueOf(chr); 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | return chr; 77 | } 78 | 79 | public Value safePrototype() { 80 | return SPACE; 81 | } 82 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/AndBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.BitArr; 5 | import APL.types.functions.Builtin; 6 | 7 | public class AndBuiltin extends Builtin { 8 | @Override public String repr() { 9 | return "∧"; 10 | } 11 | 12 | 13 | 14 | public Value identity() { 15 | return Num.ONE; 16 | } 17 | 18 | public Value call(Value w) { 19 | if (w instanceof BitArr) { 20 | BitArr wb = (BitArr) w; 21 | wb.setEnd(true); 22 | for (long l : wb.arr) if (l != ~0L) return Num.ZERO; 23 | return Num.ONE; 24 | } 25 | return new Num(Num.lcm(w.asDoubleArr())); 26 | } 27 | 28 | private static final D_NNeN DNF = new D_NNeN() { 29 | public double on(double a, double w) { 30 | return Num.lcm2(a, w); 31 | } 32 | public void on(double[] res, double a, double[] w) { 33 | for (int i = 0; i < w.length; i++) res[i] = Num.lcm2(a, w[i]); 34 | } 35 | public void on(double[] res, double[] a, double w) { 36 | for (int i = 0; i < a.length; i++) res[i] = Num.lcm2(a[i], w); 37 | } 38 | public void on(double[] res, double[] a, double[] w) { 39 | for (int i = 0; i < a.length; i++) res[i] = Num.lcm2(a[i], w[i]); 40 | } 41 | public Value call(BigValue a, BigValue w) { 42 | return new BigValue(a.i.multiply(w.i).divide(a.i.gcd(w.i))); 43 | } 44 | }; 45 | 46 | private static final D_BB DBF = new D_BB() { 47 | @Override public Value call(boolean a, BitArr w) { 48 | if (a) return w; 49 | return BitArr.fill(w, false); 50 | } 51 | @Override public Value call(BitArr a, boolean w) { 52 | if (w) return a; 53 | return BitArr.fill(a, false); 54 | } 55 | @Override public Value call(BitArr a, BitArr w) { 56 | BitArr.BC bc = new BitArr.BC(a.shape); 57 | for (int i = 0; i < a.arr.length; i++) bc.arr[i] = a.arr[i] & w.arr[i]; 58 | return bc.finish(); 59 | } 60 | }; 61 | 62 | public Value call(Value a, Value w) { 63 | return bitD(DNF, DBF, a, w); 64 | } 65 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/RShoeUBBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | public class RShoeUBBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⊇"; 11 | } 12 | 13 | public RShoeUBBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | public Value call(Value a, Value w) { 18 | return on(a, w, sc.IO, this); 19 | } 20 | 21 | public static Value on(Value a, Value w, int IO, Callable blame) { 22 | if (w instanceof APLMap) { 23 | Value[] res = new Value[a.ia]; 24 | APLMap map = (APLMap) w; 25 | Value[] ks = a.values(); 26 | for (int i = 0; i < a.ia; i++) res[i] = (Value) map.getRaw(ks[i]); 27 | return Arr.createL(res, a.shape); 28 | } 29 | if (a instanceof Primitive && w.rank==1) { 30 | Value r = w.get((int) a.asDouble() - IO); 31 | if (r instanceof Primitive) return r; 32 | else return new Rank0Arr(r); 33 | } 34 | 35 | return on(Indexer.poss(a, w.shape, IO, blame), w); 36 | } 37 | 38 | public static Value on(Indexer.PosSh poss, Value w) { 39 | if (w.quickDoubleArr()) { 40 | double[] res = new double[Arr.prod(poss.sh)]; 41 | double[] wd = w.asDoubleArr();; 42 | int[] idxs = poss.vals; 43 | for (int i = 0; i < idxs.length; i++) { 44 | res[i] = wd[idxs[i]]; 45 | } 46 | return DoubleArr.safe(res, poss.sh); 47 | } 48 | Value[] res = new Value[Arr.prod(poss.sh)]; 49 | int[] idxs = poss.vals; 50 | for (int i = 0; i < idxs.length; i++) { 51 | res[i] = w.get(idxs[i]); 52 | } 53 | return Arr.createL(res, poss.sh); 54 | } 55 | 56 | public Value underW(Obj o, Value a, Value w) { 57 | Value v = o instanceof Fun? ((Fun) o).call(call(a, w)) : (Value) o; 58 | Value[] vs = w.valuesCopy(); 59 | for (int i = 0; i < a.ia; i++) { 60 | vs[Indexer.fromShape(w.shape, a.get(i).asIntVec(), sc.IO)] = v.get(i); 61 | } 62 | return Arr.createL(vs, w.shape); 63 | } 64 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/RandBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Scope; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | import APL.types.arrs.*; 7 | import APL.types.functions.Builtin; 8 | 9 | import java.math.BigInteger; 10 | import java.util.*; 11 | 12 | public class RandBuiltin extends Builtin { 13 | @Override public String repr() { 14 | return "?"; 15 | } 16 | 17 | public RandBuiltin(Scope sc) { 18 | super(sc); 19 | } 20 | 21 | private final NumMV nf = new NumMV() { 22 | @Override public Value call(Num v) { 23 | if (v.num == 0) return new Num(sc.rand(1d)); 24 | else return Num.of(sc.rand(v.asInt()) + sc.IO); 25 | } 26 | @Override public void call(double[] res, double[] a) { 27 | for (int i = 0; i < res.length; i++) { 28 | res[i] = a[i]==0? sc.rand(1d) : Math.floor(sc.rand(a[i])) + sc.IO; 29 | } 30 | } 31 | @Override public Value call(BigValue w) { 32 | if (w.i.signum()==0) throw new DomainError("?0L", w); 33 | BigInteger n; 34 | do { 35 | n = new BigInteger(w.i.bitLength(), sc.rnd); 36 | } while (n.compareTo(w.i) >= 0); 37 | return new BigValue(sc.IO==0? n : n.add(BigInteger.ONE)); 38 | } 39 | }; 40 | 41 | public Value call(Value w) { 42 | if (sc.IO==0 && w instanceof SingleItemArr) { 43 | Value f = w.first(); 44 | if (f instanceof Num && ((Num) f).num==2) { 45 | long[] ls = new long[BitArr.sizeof(w.ia)]; 46 | for (int i = 0; i < ls.length; i++) { 47 | ls[i] = sc.randLong(); 48 | } 49 | return new BitArr(ls, w.shape); 50 | } 51 | } 52 | return numM(nf, w); 53 | } 54 | 55 | public Value call(Value a, Value w) { 56 | int IO = sc.IO; 57 | ArrayList vs = new ArrayList<>(w.ia); 58 | int wi = w.asInt(); 59 | int ai = a.asInt(); 60 | for (int i = 0; i < wi; i++) { 61 | vs.add(i+IO); 62 | } 63 | Collections.shuffle(vs, sc.rnd); 64 | double[] res = new double[ai]; 65 | for (int i = 0; i < ai; i++) { 66 | res[i] = vs.get(i); 67 | } 68 | return new DoubleArr(res); 69 | } 70 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/FindBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Indexer; 4 | import APL.errors.RankError; 5 | import APL.types.Value; 6 | import APL.types.arrs.BitArr; 7 | import APL.types.functions.Builtin; 8 | 9 | public class FindBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "⍷"; 12 | } 13 | 14 | 15 | 16 | public Value call(Value a, Value w) { 17 | if (a.rank != w.rank) throw new RankError("⍷: argument ranks should be equal ("+a.rank+" ≠ "+w.rank+")", this, w); 18 | BitArr.BC bc = new BitArr.BC(w.shape); 19 | if (a.rank == 1) { 20 | if (a instanceof BitArr && w instanceof BitArr) { 21 | long[] ab = ((BitArr) a).arr; 22 | long[] wb = ((BitArr) w).arr; 23 | w: for (int ir = 0; ir < w.ia-a.ia+1; ir++) { 24 | for (int ia = 0; ia < a.ia; ia++) { 25 | int iw = ia + ir; 26 | long la = ab[ia>>6] >> (ia & 63); 27 | long lw = wb[iw>>6] >> (iw & 63); 28 | if ((la&1) != (lw&1)) continue w; 29 | } 30 | bc.set(ir); 31 | } 32 | } else if (a.quickDoubleArr() && w.quickDoubleArr()) { 33 | double[] ad = a.asDoubleArr(); 34 | double[] wd = w.asDoubleArr(); 35 | w: for (int ir = 0; ir < w.ia-a.ia+1; ir++) { 36 | for (int ia = 0; ia < a.ia; ia++) { 37 | if (ad[ia] != wd[ia + ir]) continue w; 38 | } 39 | bc.set(ir); 40 | } 41 | } else { 42 | w: for (int ir = 0; ir < w.ia-a.ia+1; ir++) { 43 | for (int ia = 0; ia < a.ia; ia++) { 44 | if (!a.get(ia).equals(w.get(ia + ir))) continue w; 45 | } 46 | bc.set(ir); 47 | } 48 | } 49 | } else { 50 | Indexer ind = new Indexer(Indexer.add(Indexer.sub(w.shape, a.shape), 1), 0); 51 | w: for (int[] inW : ind) { 52 | for (int[] inA : new Indexer(a.shape, 0)) { 53 | Value vA = a.simpleAt(inA); 54 | Value vW = w.simpleAt(Indexer.add(inA, inW)); 55 | if (!vA.equals(vW)) continue w; 56 | } 57 | bc.set(Indexer.fromShape(w.shape, inW, 0)); 58 | } 59 | } 60 | return bc.finish(); 61 | } 62 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/StarBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.Builtin; 6 | 7 | import java.math.BigInteger; 8 | 9 | public class StarBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "*"; 12 | } 13 | 14 | 15 | 16 | public static final NumMV NF = new NumMV() { 17 | public Value call(Num w) { 18 | return Num.E.pow(w); 19 | } 20 | public void call(double[] res, double[] a) { 21 | for (int i = 0; i < a.length; i++) res[i] = Math.exp(a[i]); 22 | } 23 | }; 24 | public Value call(Value w) { 25 | return numM(NF, w); 26 | } 27 | public Value callInv(Value w) { 28 | return numM(LogBuiltin.NF, w); 29 | } 30 | 31 | static final D_NNeN DNF = new D_NNeN() { 32 | public double on(double a, double w) { 33 | return Math.pow(a, w); 34 | } 35 | public void on(double[] res, double a, double[] w) { 36 | for (int i = 0; i < w.length; i++) res[i] = Math.pow(a, w[i]); 37 | } 38 | public void on(double[] res, double[] a, double w) { 39 | if (w == 2) for (int i = 0; i < a.length; i++) res[i] = a[i]*a[i]; 40 | else for (int i = 0; i < a.length; i++) res[i] = Math.pow(a[i], w); 41 | } 42 | public void on(double[] res, double[] a, double[] w) { 43 | for (int i = 0; i < a.length; i++) res[i] = Math.pow(a[i], w[i]); 44 | } 45 | public Value call(BigValue a, BigValue w) { 46 | if (a.i.signum() == 0) return BigValue.ZERO; 47 | if (a.i.equals(BigInteger.ONE)) return BigValue.ONE; 48 | if (a.i.equals(BigValue.MINUS_ONE.i)) return w.i.intValue()%2 == 0? BigValue.ONE : BigValue.MINUS_ONE; 49 | if (w.i.bitLength() > 30) throw new DomainError("*: ⍵ too big to calculate (⍺ ≡ "+a+"; ⍵ ≡ "+w+")", w); // otherwise intValue might ignore those! 50 | return new BigValue(a.i.pow(w.i.intValue())); 51 | } 52 | }; 53 | public Value call(Value a, Value w) { 54 | return numD(DNF, a, w); 55 | } 56 | public Value callInvW(Value a, Value w) { 57 | return numD(LogBuiltin.DNF, a, w); 58 | } 59 | public Value callInvA(Value a, Value w) { 60 | return numD(RootBuiltin.DNF, w, a); 61 | } 62 | } -------------------------------------------------------------------------------- /src/APL/types/arrs/EmptyArr.java: -------------------------------------------------------------------------------- 1 | package APL.types.arrs; 2 | 3 | import APL.errors.*; 4 | import APL.types.*; 5 | 6 | import java.util.Iterator; 7 | 8 | public class EmptyArr extends Arr { 9 | public static final int[] SHAPE0 = new int[]{0}; 10 | public static final EmptyArr SHAPE0Q = new EmptyArr(SHAPE0, null); 11 | public static final EmptyArr SHAPE0N = new EmptyArr(SHAPE0, Num.ZERO); 12 | public static final int[] NOINTS = new int[0]; 13 | private final Value proto; 14 | public EmptyArr(int[] sh, Value proto) { 15 | super(sh, 0, sh.length); 16 | this.proto = proto; 17 | } 18 | 19 | @Override 20 | public int[] asIntArrClone() { 21 | return NOINTS; 22 | } 23 | 24 | @Override 25 | public int asInt() { 26 | throw new DomainError("Using empty array as integer", this); 27 | } 28 | 29 | public boolean quickDoubleArr() { 30 | return true; 31 | } 32 | 33 | public double[] asDoubleArr() { 34 | return DoubleArr.EMPTY; 35 | } 36 | 37 | @Override 38 | public Value get(int i) { 39 | throw new ImplementationError("internal: using get() on empty array; view )stack"); 40 | } 41 | 42 | @Override 43 | public String asString() { 44 | if (rank >= 2) throw new DomainError("Using rank≥2 array as char vector", this); 45 | return ""; 46 | } 47 | 48 | public Value prototype() { 49 | if (proto == null) throw new DomainError("couldn't get prototype", this); 50 | return proto; 51 | } 52 | public Value safePrototype() { 53 | return proto; 54 | } 55 | 56 | @Override 57 | public Value ofShape(int[] sh) { 58 | assert ia == Arr.prod(sh); 59 | return new EmptyArr(sh, proto); 60 | } 61 | 62 | private static final Value[] NO_VALUES = new Value[0]; 63 | @Override 64 | public Value[] valuesCopy() { 65 | return NO_VALUES; // safe, copy or not - doesn't matter 66 | } 67 | 68 | @Override 69 | public Value squeeze() { 70 | return this; 71 | } 72 | 73 | 74 | 75 | private static final Iterator EIT = new Iterator() { 76 | public boolean hasNext() { return false; } 77 | public Value next() { throw new IllegalStateException("iterating empty array"); } 78 | }; 79 | public Iterator iterator() { 80 | return EIT; 81 | } 82 | } -------------------------------------------------------------------------------- /AndroidIDE/GUI.pde: -------------------------------------------------------------------------------- 1 | static class TopBar extends Drawable { 2 | Tab ctab; 3 | ArrayList tabs = new ArrayList(); 4 | TopBar(int x, int y, int w, int h) { 5 | super(x, y, w, h); 6 | } 7 | void tick() { 8 | if (smouseIn() && a.mousePressed && !pmousePressed) { 9 | d.textSize(h*.8); 10 | int cx = x; 11 | for (Tab t : tabs) { 12 | String n = t.name(); 13 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 14 | if (a.mouseX > cx && a.mouseX < cx + dx) to(t); 15 | cx+= dx; 16 | redraw(); 17 | } 18 | } 19 | } 20 | void redraw() { 21 | d.textSize(h*.8); 22 | if (!visible) return; 23 | d.rectMode(CORNER); 24 | d.fill(#222222); 25 | d.noStroke(); 26 | d.rect(x, y, w, h); 27 | 28 | int cx = x; 29 | for (Tab t : tabs) { 30 | String n = t.name(); 31 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 32 | if (t == ctab) { 33 | d.fill(#333333); 34 | d.rect(cx, y, dx, h); 35 | } 36 | cx+= dx; 37 | } 38 | 39 | d.fill(#D2D2D2); 40 | d.textAlign(CENTER, CENTER); 41 | cx = x; 42 | for (Tab t : tabs) { 43 | String n = t.name(); 44 | int dx = max(2*h, ceil(d.textWidth(n)) + h/2); 45 | d.text(n, cx + dx/2, y + h*.4); 46 | cx+= dx; 47 | } 48 | } 49 | void to(Tab t) { 50 | if (ctab != null) ctab.hide(); 51 | ctab = t; 52 | ctab.show(); 53 | redraw(); 54 | } 55 | void move(int d) { 56 | int i = tabs.indexOf(ctab) + d; 57 | i%= tabs.size(); 58 | if (i < 0) i+= tabs.size(); 59 | to(tabs.get(i)); 60 | } 61 | void toNew(Tab t) { 62 | add(t); 63 | to(t); 64 | } 65 | void add(Tab t) { 66 | tabs.add(t); 67 | redraw(); 68 | } 69 | void resized() { 70 | if (ctab != null) ctab.show(); 71 | } 72 | void close() { 73 | if (tabs.size() == 1) return; 74 | int i = tabs.indexOf(ctab); 75 | Tab t = tabs.remove(i); 76 | i--; 77 | if (i < 0) i = 0; 78 | to(tabs.get(i)); 79 | t.closed(); 80 | } 81 | void close(Tab t) { 82 | if (tabs.size() == 1) return; 83 | int i = tabs.indexOf(t); 84 | tabs.remove(i); 85 | i--; 86 | if (i < 0) i = 0; 87 | if (t==ctab) to(tabs.get(i)); 88 | else redraw(); 89 | t.closed(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/DualBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | import APL.types.functions.builtins.mops.InvertBuiltin; 7 | 8 | public class DualBuiltin extends Dop { 9 | @Override public String repr() { 10 | return "⍢"; 11 | } 12 | 13 | 14 | 15 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 16 | Fun wwf = isFn(ww, '⍹'); 17 | return wwf.under(aa, w); 18 | } 19 | public Value callInv(Obj aa, Obj ww, Value w) { 20 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 21 | return wwf.under(InvertBuiltin.invertM(aaf), w); 22 | } 23 | 24 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 25 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 26 | return wwf.under(new BindA(wwf.call(a), aaf), w); 27 | } 28 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 29 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 30 | return wwf.under(new BindA(wwf.call(a), InvertBuiltin.invertW(aaf)), w); 31 | } 32 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { // structural inverse is not possible; fall back to computational inverse 33 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 34 | Value a1 = wwf.call(a); 35 | Value w1 = wwf.call(w); 36 | try { 37 | return wwf.callInv(aaf.callInvA(a1, w1)); 38 | } 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?) 39 | String msg = e.getMessage(); 40 | if (msg.contains("doesn't support") && msg.contains("inverting")) { 41 | throw new DomainError(msg + " (possibly caused by using f⍢g⍨⍣¯1, which only allows computational inverses)", e.cause); 42 | } throw e; 43 | } 44 | } 45 | 46 | public static class BindA extends Fun { 47 | final Value a; 48 | final Fun f; 49 | public BindA(Value a, Fun f) { 50 | this.a = a; 51 | this.f = f; 52 | } 53 | 54 | public Value call(Value w) { 55 | return f.call(a, w); 56 | } 57 | public Value callInv(Value w) { 58 | return f.callInvW(a, w); 59 | } 60 | 61 | public String repr() { 62 | return f.repr(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/LShoeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Main; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | import APL.types.arrs.*; 7 | import APL.types.functions.Builtin; 8 | 9 | import java.util.ArrayList; 10 | 11 | public class LShoeBuiltin extends Builtin { 12 | @Override public String repr() { 13 | return "⊂"; 14 | } 15 | 16 | 17 | 18 | public Value call(Value w) { 19 | if (!Main.enclosePrimitives && w instanceof Primitive) return w; 20 | return new Rank0Arr(w); 21 | } 22 | public static Value on(Value w) { 23 | return !Main.enclosePrimitives && w instanceof Primitive? w : new Rank0Arr(w); 24 | } 25 | 26 | @Override public Value call(Value a, Value w) { 27 | if (w.rank != 1) throw new DomainError("⊂: ⍵ should be of rank 1 ("+Main.formatAPL(w.shape)+" ≡ ⍴⍵)", this); 28 | if (a.rank != 1) throw new DomainError("⊂: ⍺ should be of rank 1 ("+Main.formatAPL(a.shape)+" ≡ ⍴⍺)", this); 29 | if (a.ia+1 != w.ia) throw new LengthError("⊂: (1+≢⍺) ≡ ≢⍵ is required ("+Main.formatAPL(a.shape)+" ≡ ⍴⍺; "+Main.formatAPL(w.shape)+" ≡ ⍴⍵)", this); 30 | int[] aa = a.asIntVec(); 31 | ArrayList parts = new ArrayList<>(); 32 | 33 | if (w.quickDoubleArr()) { 34 | double[] vals = w.asDoubleArr(); 35 | ArrayList cpart = new ArrayList<>(); 36 | for (int i = 0; i < aa.length; i++) { 37 | int am = aa[i]; 38 | cpart.add(vals[i]); 39 | if (am > 0) { 40 | parts.add(new DoubleArr(cpart)); 41 | for (int j = 0; j < am - 1; j++) parts.add(EmptyArr.SHAPE0N); 42 | cpart.clear(); 43 | } 44 | } 45 | cpart.add(vals[vals.length - 1]); 46 | parts.add(new DoubleArr(cpart)); 47 | } else { 48 | Value[] vals = w.values(); 49 | ArrayList cpart = new ArrayList<>(); 50 | for (int i = 0; i < aa.length; i++) { 51 | int am = aa[i]; 52 | cpart.add(vals[i]); 53 | if (am > 0) { 54 | parts.add(Arr.create(cpart)); 55 | for (int j = 0; j < am - 1; j++) parts.add(new EmptyArr(EmptyArr.SHAPE0, w.safePrototype())); 56 | cpart.clear(); 57 | } 58 | } 59 | cpart.add(vals[vals.length - 1]); 60 | parts.add(Arr.create(cpart)); 61 | } 62 | return Arr.create(parts); 63 | } 64 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/NorBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | public class NorBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍱"; 11 | } 12 | 13 | public NorBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | private static final D_NNeN DNF = new D_NNeN() { 18 | public double on(double a, double w) { 19 | return Main.bool(a)|Main.bool(w) ? 0 : 1; 20 | } 21 | public void on(double[] res, double a, double[] w) { 22 | for (int i = 0; i < w.length; i++) res[i] = Main.bool(a)|Main.bool(w[i]) ? 0 : 1; 23 | } 24 | public void on(double[] res, double[] a, double w) { 25 | for (int i = 0; i < a.length; i++) res[i] = Main.bool(a[i])|Main.bool(w) ? 0 : 1; 26 | } 27 | public void on(double[] res, double[] a, double[] w) { 28 | for (int i = 0; i < a.length; i++) res[i] = Main.bool(a[i])|Main.bool(w[i]) ? 0 : 1; 29 | } 30 | }; 31 | 32 | private static final D_BB DBF = new D_BB() { 33 | @Override public Value call(boolean a, BitArr w) { 34 | if (a) return BitArr.fill(w, false); 35 | return TildeBuiltin.call(w); 36 | } 37 | @Override public Value call(BitArr a, boolean w) { 38 | if (w) return BitArr.fill(a, false); 39 | return TildeBuiltin.call(a); 40 | } 41 | @Override public Value call(BitArr a, BitArr w) { 42 | BitArr.BC bc = new BitArr.BC(a.shape); 43 | for (int i = 0; i < a.arr.length; i++) bc.arr[i] = ~(a.arr[i] | w.arr[i]); 44 | return bc.finish(); 45 | } 46 | }; 47 | 48 | public Value call(Value a, Value w) { 49 | return bitD(DNF, DBF, a, w); 50 | } 51 | public Value call(Value w) { 52 | if (w instanceof BitArr) { 53 | BitArr wb = (BitArr) w; 54 | wb.setEnd(false); 55 | for (long l : wb.arr) if (l != 0L) return Num.ZERO; 56 | return Num.ONE; 57 | } 58 | if (w instanceof DoubleArr) { 59 | double[] da = w.asDoubleArr(); 60 | for (int i = 0; i < w.ia; i++) { 61 | if (Main.bool(da[i])) return Num.ZERO; 62 | } 63 | return Num.ONE; 64 | } 65 | for (int i = 0; i < w.ia; i++) { 66 | if (Main.bool(w.get(i))) return Num.ZERO; 67 | } 68 | return Num.ONE; 69 | } 70 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/NandBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.types.*; 5 | import APL.types.arrs.BitArr; 6 | import APL.types.functions.Builtin; 7 | 8 | public class NandBuiltin extends Builtin { 9 | @Override public String repr() { 10 | return "⍲"; 11 | } 12 | 13 | public NandBuiltin(Scope sc) { 14 | super(sc); 15 | } 16 | 17 | 18 | private static final D_NNeN DNF = new D_NNeN() { 19 | public double on(double a, double w) { 20 | return Main.bool(a)&Main.bool(w) ? 0 : 1; 21 | } 22 | public void on(double[] res, double a, double[] w) { 23 | for (int i = 0; i < w.length; i++) res[i] = Main.bool(a)&Main.bool(w[i]) ? 0 : 1; 24 | } 25 | public void on(double[] res, double[] a, double w) { 26 | for (int i = 0; i < a.length; i++) res[i] = Main.bool(a[i])&Main.bool(w) ? 0 : 1; 27 | } 28 | public void on(double[] res, double[] a, double[] w) { 29 | for (int i = 0; i < a.length; i++) res[i] = Main.bool(a[i])&Main.bool(w[i]) ? 0 : 1; 30 | } 31 | }; 32 | 33 | private static final D_BB DBF = new D_BB() { 34 | @Override public Value call(boolean a, BitArr w) { 35 | if (a) return TildeBuiltin.call(w); 36 | return BitArr.fill(w, true); 37 | } 38 | @Override public Value call(BitArr a, boolean w) { 39 | if (w) return TildeBuiltin.call(a); 40 | return BitArr.fill(a, true); 41 | } 42 | @Override public Value call(BitArr a, BitArr w) { 43 | BitArr.BC bc = new BitArr.BC(a.shape); 44 | for (int i = 0; i < a.arr.length; i++) bc.arr[i] = ~(a.arr[i] & w.arr[i]); 45 | return bc.finish(); 46 | } 47 | }; 48 | 49 | public Value call(Value a, Value w) { 50 | return bitD(DNF, DBF, a, w); 51 | } 52 | public Value call(Value w) { 53 | if (w instanceof BitArr) { 54 | BitArr wb = (BitArr) w; 55 | wb.setEnd(true); 56 | for (long l : wb.arr) if (l != ~0L) return Num.ONE; 57 | return Num.ZERO; 58 | } 59 | if (w.quickDoubleArr()) { 60 | double[] da = w.asDoubleArr(); 61 | for (int i = 0; i < w.ia; i++) { 62 | if (!Main.bool(da[i])) return Num.ONE; 63 | } 64 | return Num.ZERO; 65 | } 66 | for (int i = 0; i < w.ia; i++) { 67 | if (!Main.bool(w.get(i))) return Num.ONE; 68 | } 69 | return Num.ZERO; 70 | } 71 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/ExclBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.functions.Builtin; 6 | 7 | import java.math.BigInteger; 8 | 9 | public class ExclBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "!"; 12 | } 13 | 14 | 15 | private static final double[] cache = new double[172]; 16 | static { 17 | double r = 1; 18 | cache[0] = cache[1] = r; 19 | for (int i = 2; i < 172; i++) { 20 | r*= i; 21 | cache[i] = r; 22 | } 23 | } 24 | 25 | private static final NumMV NF = new NumMV() { 26 | public Value call(Num w) { 27 | return new Num(cache[Math.min(w.asInt(), 171)]); 28 | } 29 | public void call(double[] res, double[] a) { 30 | for (int i = 0; i < a.length; i++) { 31 | res[i] = cache[Math.min((int) a[i], 171)]; 32 | } 33 | } 34 | public Value call(BigValue w) { 35 | if (w.i.bitLength() > 30) throw new DomainError("!: argument too big (⍵ ≡ "+w+")", w); // otherwise intValue might ignore those! 36 | int am = w.i.intValue(); 37 | BigInteger res = BigInteger.ONE; 38 | for (int i = 2; i <= am; i++) { 39 | res = res.multiply(BigInteger.valueOf(i)); 40 | } 41 | return new BigValue(res); 42 | } 43 | }; 44 | 45 | public Value call(Value w) { 46 | return numM(NF, w); 47 | } 48 | 49 | public Value call(Value a0, Value w0) { 50 | return allD((a, w) -> { 51 | if (a instanceof BigValue || w instanceof BigValue) { 52 | 53 | BigInteger res = BigInteger.ONE; 54 | BigInteger al = BigValue.bigint(w); 55 | BigInteger bl = BigValue.bigint(a); 56 | if (al.compareTo(bl) < 0) return Num.ZERO; 57 | 58 | if (bl.compareTo(al.subtract(bl)) > 0) bl = al.subtract(bl); 59 | 60 | if (bl.bitLength() > 30) throw new DomainError("!: arguments too big (⍺ ≡ "+a+"; ⍵ ≡ "+w+")", w); 61 | int ri = bl.intValue(); 62 | 63 | for (int i = 0; i < ri; i++) { 64 | res = res.multiply(al.subtract(BigInteger.valueOf(i))); 65 | } 66 | for (int i = 0; i < ri; i++) { 67 | res = res.divide(BigInteger.valueOf(i+1)); 68 | } 69 | return new BigValue(res); 70 | } 71 | return ((Num) w).binomial((Num) a); 72 | }, a0, w0); 73 | } 74 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/RShoeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.*; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | 7 | public class RShoeBuiltin extends Fun { 8 | @Override public String repr() { 9 | return "⊃"; 10 | } 11 | 12 | public RShoeBuiltin(Scope sc) { 13 | super(sc); 14 | } 15 | 16 | public Value call(Value w) { 17 | if (w instanceof Primitive) return w; 18 | else if (w.ia == 0) return w.prototype(); 19 | else return w.first(); 20 | } 21 | 22 | public Value call(Value a, Value w) { 23 | Obj o = callObj(a, w); 24 | if (o instanceof Value) return (Value) o; 25 | throw new DomainError("Was expected to give array, got "+o.humanType(true), this); 26 | } 27 | public Obj callObj(Value a, Value w) { 28 | if (w instanceof APLMap) { 29 | APLMap map = (APLMap) w; 30 | return map.getRaw(a); 31 | } 32 | if (a instanceof Num) { 33 | if (w.rank != 1) throw new RankError("array rank was "+w.rank+", tried to get item at rank 0", this, w); 34 | if (w.ia == 0) throw new LengthError("⊃ on array with 0 elements", this, w); 35 | int p = a.asInt() - sc.IO; 36 | if (p >= w.ia) throw new DomainError("Tried to access item at position "+a+" while shape was "+ Main.formatAPL(w.shape), this); 37 | return w.get(p); 38 | } 39 | return w.at(a.asIntVec(), sc.IO); 40 | } 41 | 42 | public Value under(Obj o, Value w) { 43 | Value[] vs = w.valuesCopy(); 44 | vs[0] = o instanceof Fun? ((Fun) o).call(call(w)) : (Value) o; 45 | return Arr.createL(vs, w.shape); 46 | } 47 | 48 | public Value underW(Obj o, Value a, Value w) { 49 | Value v = o instanceof Fun? ((Fun) o).call(call(a, w)) : (Value) o; 50 | if (a instanceof Primitive) { 51 | Value[] vs = w.valuesCopy(); 52 | vs[a.asInt() - sc.IO] = v; 53 | return Arr.createL(vs, w.shape); 54 | } else { 55 | Value[] vs = w.valuesCopy(); 56 | int[] is = a.asIntVec(); 57 | replace(vs, v, is, 0); 58 | return Arr.createL(vs, w.shape); 59 | } 60 | } 61 | private void replace(Value[] vs, Value w, int[] d, int i) { 62 | int c = d[i]-sc.IO; 63 | if (i+1 == d.length) vs[c] = w; 64 | else { 65 | Value cv = vs[c]; 66 | Value[] vsN = cv.valuesCopy(); 67 | replace(vsN, w, d, i+1); 68 | vs[c] = Arr.createL(vsN, cv.shape); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/APL/types/arrs/HArr.java: -------------------------------------------------------------------------------- 1 | package APL.types.arrs; 2 | 3 | import APL.Main; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | 7 | import java.util.*; 8 | 9 | public class HArr extends Arr { 10 | private final Value[] arr; 11 | public HArr(Value[] v, int[] sh) { 12 | super(sh, v.length, sh.length); 13 | arr = v; 14 | } 15 | 16 | public HArr(ArrayList v) { // 1D 17 | super(new int[]{v.size()}); 18 | arr = v.toArray(new Value[0]); 19 | } 20 | public HArr(Value[] v) { // 1D 21 | super(new int[]{v.length}, v.length, 1); 22 | arr = v; 23 | } 24 | 25 | public HArr(ArrayList v, int[] sh) { 26 | super(sh); 27 | arr = v.toArray(new Value[0]); 28 | } 29 | 30 | @Override 31 | public int[] asIntArrClone() { 32 | int[] res = new int[ia]; 33 | for (int i = 0; i < arr.length; i++) { 34 | res[i] = arr[i].asInt(); 35 | } 36 | return res; 37 | } 38 | 39 | @Override 40 | public int asInt() { 41 | if (rank == 0) return arr[0].asInt(); 42 | throw new DomainError("Using array as integer", this); 43 | } 44 | 45 | @Override 46 | public Value get(int i) { 47 | return arr[i]; 48 | } 49 | 50 | @Override 51 | public boolean equals(Obj o) { 52 | if (!(o instanceof Value)) return false; 53 | Value v = (Value) o; 54 | if (!Arrays.equals(shape, v.shape)) return false; 55 | assert ia == v.ia; 56 | for (int i = 0; i < ia; i++) { 57 | if (!arr[i].equals(v.get(i))) return false; 58 | } 59 | return true; 60 | } 61 | 62 | public String asString() { 63 | StringBuilder r = new StringBuilder(ia); 64 | for (Value v : arr) { 65 | if (!(v instanceof Char)) throw new DomainError("Using array containing "+v.humanType(true)+" as string", this); 66 | r.append(((Char) v).chr); 67 | } 68 | return r.toString(); 69 | } 70 | 71 | public Value prototype() { 72 | if (ia == 0) throw new DomainError("failed to get prototype", this); 73 | return arr[0].prototype(); 74 | } 75 | public Value safePrototype() { 76 | if (ia == 0) return null; 77 | return arr[0].safePrototype(); 78 | } 79 | public Value[] values() { 80 | return arr; 81 | } 82 | public Value[] valuesCopy() { 83 | return arr.clone(); 84 | } 85 | public Value ofShape(int[] sh) { 86 | if (sh.length==0 && Main.enclosePrimitives && arr[0] instanceof Primitive) return arr[0]; 87 | return new HArr(arr, sh); 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /src/APL/types/dimensions/DervDimFn.java: -------------------------------------------------------------------------------- 1 | package APL.types.dimensions; 2 | 3 | import APL.*; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | 7 | public class DervDimFn extends Fun { 8 | private final int IO; 9 | private final Fun f; 10 | private final int[] raw; 11 | private final int[] dims; 12 | 13 | @Override public String repr() { 14 | return f.repr()+"["+ Main.formatAPL(raw)+"]"; 15 | } 16 | 17 | public DervDimFn(Fun f, int[] raw, Scope sc) { 18 | super(sc); 19 | this.f = f; 20 | this.raw = raw; 21 | this.IO = sc.IO; 22 | if (raw == null) dims = new int[]{0}; 23 | else { 24 | dims = new int[raw.length]; 25 | for (int i = 0; i < raw.length; i++) { 26 | int c = raw[i]; 27 | if (c==0 && IO==1) throw new DomainError("bracket axis cannot contain 0 with ⎕IO←1", this); 28 | dims[i] = c<0? c : c-IO; 29 | } 30 | } 31 | this.token = f.token; 32 | } 33 | 34 | public int[] dims(int rank) { 35 | int[] res = new int[dims.length]; 36 | boolean[] used = new boolean[rank]; 37 | 38 | for (int i = 0; i < dims.length; i++) { 39 | int c = dims[i]; 40 | int ax = c < 0? c + rank : c; 41 | if (used[ax]) throw new DomainError("function axis specified axis "+(ax+IO)+" twice", this); 42 | else used[ax] = true; 43 | res[i] = ax; 44 | } 45 | return res; 46 | } 47 | 48 | @Override 49 | public Value call(Value a, Value w) { 50 | if (!(f instanceof DimDFn)) throw new SyntaxError("Attempt to dyadically call "+this+", which doesn't support dimension specification", this); 51 | return ((DimDFn) f).call(a, w, this); 52 | } 53 | 54 | @Override 55 | public Value call(Value w) { 56 | if (!(f instanceof DimMFn)) throw new SyntaxError("Attempt to monadically call "+this+", which doesn't support dimension specification", this); 57 | if (dims.length != 1) throw new DomainError(repr()+" expected one dimension specifier", this); 58 | return ((DimMFn) f).call(w, dims[0]); 59 | } 60 | 61 | public int singleDim(int rank) { 62 | if (dims.length != 1) throw new DomainError(f+" expected only one axis specifier", f); 63 | int c = dims[0]; 64 | if (c < 0) c+= rank; 65 | return c; 66 | } 67 | public int singleDim() { 68 | if (dims.length != 1) throw new DomainError(f+" expected only one axis specifier", f); 69 | return dims[0]; 70 | } 71 | 72 | public String format() { 73 | return Main.formatAPL(raw); 74 | } 75 | } -------------------------------------------------------------------------------- /src/APL/types/Obj.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.*; 4 | import APL.errors.NYIError; 5 | import APL.tokenizer.Token; 6 | import APL.types.dimensions.*; 7 | import APL.types.functions.*; 8 | 9 | public abstract class Obj implements Tokenable { 10 | public Token token; 11 | 12 | public boolean isObj() { 13 | return type()==Type.array || type() == Type.var; 14 | } 15 | abstract public Type type(); 16 | public boolean equals(Obj o) { 17 | return false; 18 | } 19 | 20 | public String humanType(boolean article) { 21 | 22 | if (this instanceof Arr )return article? "an array" : "array"; 23 | if (this instanceof Char )return article? "a character" : "character"; 24 | if (this instanceof Num )return article? "a number" : "number"; 25 | if (this instanceof APLMap )return article? "a map" : "map"; 26 | if (this instanceof Fun )return article? "a function" : "function"; 27 | if (this instanceof Null )return article? "javanull" : "javanull"; 28 | if (this instanceof Brackets)return article? "brackets" : "brackets"; 29 | if (this instanceof VarArr )return article? "a vararr" : "vararr"; 30 | if (this instanceof Variable)return article? "a variable" : "variable"; 31 | if (this instanceof Pick )return article? "an array item": "array item"; 32 | if (this instanceof Mop )return article? "monadic operator" : "a monadic operator"; 33 | if (this instanceof Dop )return article? "dyadic operator" : "a dyadic operator"; 34 | if (this instanceof ArrFun )return article? "an arrayified function": "arrayified function"; 35 | if (this instanceof APLMap.MapPointer)return article? "a map item": "map item"; 36 | if (this instanceof BigValue)return article? "a biginteger" : "biginteger"; 37 | return "some type that dzaima hasn't named in Obj.humanType ಠ_ಠ (class = "+getClass()+")"; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object obj) { 42 | return obj instanceof Obj && equals((Obj) obj); 43 | } 44 | 45 | public String name() { 46 | return toString(); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return humanType(false); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | throw new NYIError("hash not supported for "+this, this); 57 | } 58 | 59 | final protected int actualHashCode() { 60 | return super.hashCode(); 61 | } 62 | 63 | @Override 64 | public Token getToken() { 65 | return token; 66 | } 67 | } -------------------------------------------------------------------------------- /AndroidIDE/ROText.pde: -------------------------------------------------------------------------------- 1 | static class ROText extends Drawable { 2 | float tsz, chw; 3 | ROText(int x, int y, int w, int h) { 4 | super(x, y, w, h); 5 | s = new ArrayList(); 6 | setSize(max(d.width, d.height)/40); 7 | } 8 | int xoff = 0; // scroll 9 | int yoff = 0; 10 | int border = 10; 11 | boolean redraw; 12 | void redraw() { 13 | beginClip(d, x+border, y, w-border*2, h); 14 | d.fill(#101010); 15 | d.noStroke(); 16 | d.rectMode(CORNER); 17 | d.rect(x, y, w, h); 18 | d.textAlign(LEFT, TOP); 19 | d.fill(#D2D2D2); 20 | d.stroke(#D2D2D2); 21 | d.strokeWeight(2); 22 | d.textSize(tsz); 23 | d.line(x, y+h, x+w, y+h); 24 | int dy = -s.size(); 25 | d.clip(x+border, y+3, w-border*2, h-6); 26 | for (String s : s) { 27 | d.text(s, x+border + xoff, y + dy*tsz + yoff); 28 | dy++; 29 | } 30 | endClip(d); 31 | redraw = false; 32 | } 33 | void tick() { 34 | if (!visible) return; 35 | if (a.mousePressed && smouseIn() && (a.mouseY!=a.pmouseY || a.mouseX!=a.pmouseX)) { 36 | redraw = true; 37 | yoff+= a.mouseY-a.pmouseY; 38 | if (yoff < h-border) yoff = h-border; 39 | 40 | 41 | xoff+= a.mouseX-a.pmouseX; 42 | int max = 0; 43 | for (String s : s) max = max(max, s.length()); 44 | float maxx = (max - 2)*chw; 45 | if (xoff < -maxx) xoff = (int) -maxx; 46 | if (w > (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 | redraw = true; 57 | String[] lns = split(a, '\n'); 58 | if (newline) { 59 | for (String s : lns) append(s); 60 | } else { 61 | if (s.size()==0) s.add(""); 62 | s.set(s.size()-1, s.get(s.size()-1)+lns[0]); 63 | for (int i = 1; i < lns.length; i++) append(lns[i]); 64 | } 65 | newline = a.endsWith("\n"); 66 | if (newline)s.remove(s.size()-1); 67 | } 68 | void append(String a) { // append a line 69 | s.add(a); 70 | yoff = h-border; 71 | xoff = 0; 72 | newline = true; 73 | redraw = true; 74 | } 75 | void set(ArrayList a) { 76 | s = a; 77 | yoff = h-border; 78 | xoff = 0; 79 | newline = true; 80 | redraw = true; 81 | } 82 | void setSize(int sz) { 83 | tsz = sz; 84 | a.textSize(tsz); 85 | chw = d.textWidth('H'); 86 | redraw = true; 87 | } 88 | void end() { 89 | yoff = h-border; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/EpsilonBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.errors.DomainError; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.Builtin; 7 | 8 | import java.util.ArrayList; 9 | 10 | 11 | public class EpsilonBuiltin extends Builtin { 12 | @Override public String repr() { 13 | return "∊"; 14 | } 15 | 16 | 17 | 18 | public Value call(Value w) { 19 | var res = new ArrayList(); 20 | rec(res, w); 21 | return Arr.create(res); 22 | } 23 | 24 | private void rec(ArrayList arr, Value v) { 25 | if (v instanceof Primitive) { 26 | arr.add(v); 27 | } else { 28 | if (v instanceof BitArr) { 29 | BitArr ba = (BitArr) v; 30 | for (int i = 0; i < ba.ia; i++) arr.add(ba.get(i)); 31 | } else if (v.quickDoubleArr()) { 32 | for (double d : v.asDoubleArr()) arr.add(Num.of(d)); 33 | } else if (v instanceof ChrArr) { 34 | String s = ((ChrArr) v).s; 35 | for (int i = 0; i < s.length(); i++) { 36 | arr.add(Char.of(s.charAt(i))); 37 | } 38 | } else for (Value c : v) rec(arr, c); 39 | } 40 | } 41 | 42 | public Value call(Value a, Value w) { 43 | if (a.scalar()) { 44 | Value a1 = a.first(); 45 | for (Value v : w) { 46 | if (v.equals(a1)) { 47 | return Num.ONE; 48 | } 49 | } 50 | return Num.ZERO; 51 | } 52 | BitArr.BA ba = new BitArr.BA(a.shape); 53 | for (int i = 0; i < a.ia; i++) { 54 | Value av = a.get(i); 55 | boolean b = false; 56 | for (Value v : w) { 57 | if (v.equals(av)) { 58 | b = true; 59 | break; 60 | } 61 | } 62 | ba.add(b); 63 | } 64 | return ba.finish(); 65 | } 66 | 67 | 68 | public Value under(Obj o, Value w) { 69 | Value v = o instanceof Fun? ((Fun) o).call(call(w)) : (Value) o; 70 | Value[] vs = v.values(); 71 | Value[] res = new Value[w.ia]; 72 | int e = copyIn(res, vs, w, 0); 73 | if (e != v.ia) throw new DomainError("⍢∊ expected equal amount of output & output items", this); 74 | return Arr.create(res, w.shape); 75 | } 76 | private int copyIn(Value[] res, Value[] vs, Value orig, int s) { 77 | for (int i = 0; i < orig.ia; i++) { 78 | Value origN = orig.get(i); 79 | if (origN instanceof Primitive) { 80 | res[i] = vs[s++]; 81 | } else { 82 | Value[] resN = new Value[origN.ia]; 83 | s = copyIn(resN, vs, origN, s); 84 | res[i] = Arr.create(resN, origN.shape); 85 | } 86 | } 87 | return s; 88 | } 89 | } -------------------------------------------------------------------------------- /src/APL/types/functions/Mop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.*; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | 7 | public abstract class Mop extends Callable { 8 | 9 | protected Mop(Scope sc) { 10 | super(sc); 11 | } 12 | protected Mop() { 13 | super(null); 14 | } 15 | 16 | @Override 17 | public Type type() { 18 | return Type.mop; 19 | } 20 | 21 | public DerivedMop derive(Obj aa) { 22 | return new DerivedMop(aa, this); 23 | } 24 | public Value call(Obj f, Value w, DerivedMop derv) { 25 | throw new IncorrectArgsError(repr()+" can't be called monadically", derv, w); 26 | } 27 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 28 | throw new IncorrectArgsError(repr()+" can't be called dyadically", derv, a); 29 | } 30 | public Obj callObj(Obj f, Value w, DerivedMop derv) { // if overridden, call(f, w, derv) must be overridden too! 31 | return call(f, w, derv); 32 | } 33 | public Obj callObj(Obj f, Value a, Value w, DerivedMop derv) { // if overridden, call(f, a, w, derv) must be overridden too! 34 | return call(f, a, w, derv); 35 | } 36 | public Value callInv(Obj f, Value w) { 37 | throw new DomainError(this+" doesn't support monadic inverting", this, w); 38 | } 39 | public Value callInvW(Obj f, Value a, Value w) { 40 | throw new DomainError(this+" doesn't support dyadic inverting of ⍵", this, w); 41 | } 42 | public Value callInvA(Obj f, Value a, Value w) { 43 | throw new DomainError(this+" doesn't support dyadic inverting of ⍺", this, w); 44 | } 45 | public Value under(Obj aa, Obj o, Value w, DerivedMop derv) { 46 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, w, derv)) : (Value) o; 47 | return callInv(aa, v); 48 | } 49 | public Value underW(Obj aa, Obj o, Value a, Value w, DerivedMop derv) { 50 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, a, w, derv)) : (Value) o; 51 | return callInvW(aa, a, v); 52 | } 53 | public Value underA(Obj aa, Obj o, Value a, Value w, DerivedMop derv) { 54 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, a, w, derv)) : (Value) o; 55 | return callInvA(aa, v, w); 56 | } 57 | 58 | public String toString() { 59 | return repr(); 60 | } 61 | public abstract String repr(); 62 | 63 | protected Fun isFn(Obj o) { 64 | if (!(o instanceof Fun)) throw new SyntaxError(repr()+": ⍶ must be a function", this); 65 | return (Fun) o; 66 | } 67 | 68 | // operators are equal per-object basis 69 | @Override public int hashCode() { 70 | return actualHashCode(); 71 | } 72 | @Override public boolean equals(Obj o) { 73 | return this == o; 74 | } 75 | } -------------------------------------------------------------------------------- /src/APL/types/StrMap.java: -------------------------------------------------------------------------------- 1 | package APL.types; 2 | 3 | import APL.*; 4 | import APL.types.arrs.HArr; 5 | 6 | import java.util.*; 7 | 8 | public class StrMap extends APLMap { 9 | public final HashMap vals; 10 | // public final Scope sc; 11 | 12 | public StrMap(Scope sc) { 13 | this.vals = sc.vars; 14 | // this.sc = sc; 15 | } 16 | 17 | public StrMap(HashMap vals) { 18 | this.vals = vals; 19 | } 20 | 21 | public StrMap() { 22 | this.vals = new HashMap<>(); 23 | // this.sc = null; 24 | } 25 | 26 | // public StrMap(Scope sc, HashMap vals) { 27 | // this.sc = sc; 28 | // this.vals = vals; 29 | // } 30 | 31 | 32 | @Override 33 | public Obj getRaw(Value k) { 34 | return getRaw(k.asString()); 35 | } 36 | @Override 37 | public Obj getRaw(String k) { 38 | Obj v = vals.get(k); 39 | if (v == null) return Null.NULL; 40 | return v; 41 | } 42 | 43 | @Override 44 | public void set(Value k, Obj v) { 45 | if (v == Null.NULL) vals.remove(k.asString()); 46 | else vals.put(k.asString(), v); 47 | } 48 | 49 | public void setStr(String k, Obj v) { 50 | if (v == Null.NULL) vals.remove(k); 51 | else vals.put(k, v); 52 | } 53 | 54 | @Override 55 | public Arr allValues() { 56 | var items = new ArrayList(); 57 | for (Obj o : vals.values()) { 58 | if (o instanceof Value) items.add((Value) o); 59 | } 60 | return Arr.create(items); 61 | } 62 | 63 | @Override public Arr allKeys() { 64 | var items = new ArrayList(); 65 | for (String o : vals.keySet()) { 66 | items.add(Main.toAPL(o)); 67 | } 68 | return Arr.create(items); 69 | } 70 | 71 | @Override public Arr kvPair() { 72 | ArrayList ks = new ArrayList<>(); 73 | ArrayList vs = new ArrayList<>(); 74 | vals.forEach((k, v) -> { 75 | if (v instanceof Value) { 76 | ks.add(Main.toAPL(k)); 77 | vs.add((Value) v); 78 | } 79 | }); 80 | return new HArr(new Value[]{new HArr(ks), Arr.create(vs)}); 81 | } 82 | 83 | @Override 84 | public int size() { 85 | return vals.size(); 86 | } 87 | 88 | @Override 89 | public boolean equals(Obj o) { 90 | return o instanceof StrMap && vals.equals(((StrMap) o).vals); 91 | } 92 | 93 | @Override 94 | public String toString() { 95 | StringBuilder res = new StringBuilder("("); 96 | vals.forEach((key, value) -> { 97 | if (res.length() != 1) res.append(" ⋄ "); 98 | res.append(key).append(":").append(value); 99 | }); 100 | return res + ")"; 101 | } 102 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/ObliqueBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.errors.*; 4 | import APL.types.*; 5 | import APL.types.arrs.*; 6 | import APL.types.functions.*; 7 | import APL.types.functions.builtins.fns.UpArrowBuiltin; 8 | 9 | public class ObliqueBuiltin extends Mop { 10 | @Override public String repr() { 11 | return "⍁"; 12 | } 13 | 14 | 15 | 16 | public Value call(Obj f, Value w, DerivedMop derv) { 17 | if (w.rank != 2) throw new DomainError("⍁: ⍵ must be a rank 2 array", this, w); 18 | Fun ff = isFn(f); 19 | int[] sz = w.shape; 20 | int H = sz[0]; 21 | int W = sz[1]; 22 | int szM = Math.max(H, W); 23 | int szm = Math.min(H, W); 24 | int ram = H + W - 1; 25 | if (ram <= 0) return new EmptyArr(EmptyArr.SHAPE0, w.safePrototype()); 26 | 27 | Value[] res = new Value[ram]; 28 | 29 | if (w.quickDoubleArr()) { 30 | double[] vals = w.asDoubleArr(); 31 | double[][] rows = new double[ram][]; 32 | for (int i = 0; i < ram; i++) { 33 | rows[i] = new double[i < szm? i + 1 : i >= szM? szm + szM - i - 1 : szm]; 34 | } 35 | int p = 0; 36 | for (int y = 0; y < H; y++) { 37 | for (int x = 0; x < W; x++) { 38 | double v = vals[p++]; 39 | int ri = x + y; 40 | int s = ri > W - 2? y + W - ri - 1 : y; 41 | rows[ri][s] = v; 42 | } 43 | } 44 | res[0] = ff.call(new DoubleArr(rows[0])); 45 | int rrank = res[0].rank; // required rank 46 | for (int i = 0; i < ram; i++) { 47 | Value v = ff.call(new DoubleArr(rows[i])); 48 | if (v.rank != rrank) throw new RankError("⍁: ⍶ must return equal rank arrays", this, f); 49 | res[i] = v; 50 | } 51 | } else { 52 | Value[] vals = w.values(); 53 | Value[][] rows = new Value[ram][]; 54 | for (int i = 0; i < ram; i++) { 55 | rows[i] = new Value[i < szm? i + 1 : i >= szM? szm + szM - i - 1 : szm]; 56 | } 57 | int p = 0; 58 | for (int y = 0; y < H; y++) { 59 | for (int x = 0; x < W; x++) { 60 | Value v = vals[p++]; 61 | int ri = x + y; 62 | int s = ri > W - 2? y + W - ri - 1 : y; 63 | rows[ri][s] = v; 64 | } 65 | } 66 | res[0] = ff.call(new HArr(rows[0])); 67 | int rrank = res[0].rank; // required rank 68 | for (int i = 0; i < ram; i++) { 69 | Value v = ff.call(new HArr(rows[i])); 70 | if (v.rank != rrank) throw new DomainError("⍁: ⍶ must return equal rank arrays", this, f); 71 | res[i] = v; 72 | } 73 | } 74 | 75 | return UpArrowBuiltin.merge(res, new int[]{res.length}, this); 76 | } 77 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/dops/JotBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.dops; 2 | 3 | import APL.errors.SyntaxError; 4 | import APL.types.*; 5 | import APL.types.functions.*; 6 | 7 | public class JotBuiltin extends Dop { 8 | @Override public String repr() { 9 | return "∘"; 10 | } 11 | 12 | 13 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 14 | if (ww instanceof Fun) { 15 | if (aa instanceof Fun) { 16 | return ((Fun)aa).call(((Fun)ww).call(w)); 17 | } else { 18 | return ((Fun)ww).call((Value)aa, w); 19 | } 20 | } else { 21 | if (aa instanceof Fun) return ((Fun) aa).call(w, (Value) ww); 22 | throw new SyntaxError("arr∘arr makes no sense", this); 23 | } 24 | } 25 | public Value callInv(Obj aa, Obj ww, Value w) { 26 | if (ww instanceof Fun) { 27 | if (aa instanceof Fun) { 28 | return ((Fun)ww).callInv(((Fun)aa).callInv(w)); 29 | } else { 30 | return ((Fun)ww).callInvW((Value)aa, w); 31 | } 32 | } else { 33 | if (aa instanceof Fun) return ((Fun) aa).callInvA(w, (Value) ww); 34 | throw new SyntaxError("arr∘arr makes no sense", this); 35 | } 36 | } 37 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 38 | if (!(aa instanceof Fun)) { 39 | throw new SyntaxError("operands of dyadically applied ∘ must be functions, but ⍶ is "+aa.humanType(true), this, aa); 40 | } 41 | if (!(ww instanceof Fun)) { 42 | throw new SyntaxError("operands of dyadically applied ∘ must be functions, but ⍹ is "+ww.humanType(true), this, ww); 43 | } 44 | return ((Fun)aa).call(a, ((Fun)ww).call(w)); 45 | } 46 | 47 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 48 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 49 | return wwf.callInv(aaf.callInvW(a, w)); 50 | } 51 | 52 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { 53 | Fun aaf = isFn(aa, '⍶'); Fun wwf = isFn(ww, '⍹'); 54 | return aaf.callInvA(a, wwf.call(w)); 55 | } 56 | 57 | public Value under(Obj aa, Obj ww, Obj o, Value w, DerivedDop derv) { 58 | if (ww instanceof Fun) { 59 | Fun wwf = (Fun) ww; 60 | if (aa instanceof Fun) { 61 | Fun gf = (Fun) aa; 62 | return wwf.under(new Fun() { public String repr() { return gf.repr(); } 63 | public Value call(Value w) { 64 | return gf.under(o, w); 65 | } 66 | }, w); 67 | } else { 68 | return wwf.underW(o, (Value) aa, w); 69 | } 70 | } else { 71 | if (aa instanceof Fun) { 72 | return ((Fun) aa).underA(o, w, (Value) ww); 73 | } else { 74 | throw new SyntaxError("arr∘arr makes no sense", this); 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/APL/types/functions/Dop.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions; 2 | 3 | import APL.*; 4 | import APL.errors.*; 5 | import APL.types.*; 6 | 7 | public abstract class Dop extends Callable { 8 | 9 | protected Dop(Scope sc) { 10 | super(sc); 11 | } 12 | protected Dop() { 13 | super(null); 14 | } 15 | 16 | @Override 17 | public Type type() { 18 | return Type.dop; 19 | } 20 | 21 | public DerivedDop derive(Obj aa, Obj ww) { 22 | return new DerivedDop(aa, ww, this); 23 | } 24 | public Value call(Obj aa, Obj ww, Value w, DerivedDop derv) { 25 | throw new IncorrectArgsError(repr()+" can't be called monadically", derv, w); 26 | } 27 | public Value call(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { 28 | throw new IncorrectArgsError(repr()+" can't be called dyadically", derv, a); 29 | } 30 | public Obj callObj(Obj aa, Obj ww, Value w, DerivedDop derv) { // if overridden, call(aa, ww, w, derv) must be overridden too! 31 | return call(aa, ww, w, derv); 32 | } 33 | public Obj callObj(Obj aa, Obj ww, Value a, Value w, DerivedDop derv) { // if overridden, call(aa, ww, a, w, derv) must be overridden too! 34 | return call(aa, ww, a, w, derv); 35 | } 36 | public Value callInv(Obj aa, Obj ww, Value w) { 37 | throw new DomainError(this+" doesn't support monadic inverting", this, w); 38 | } 39 | public Value callInvW(Obj aa, Obj ww, Value a, Value w) { 40 | throw new DomainError(this+" doesn't support dyadic inverting of ⍵", this, w); 41 | } 42 | public Value callInvA(Obj aa, Obj ww, Value a, Value w) { 43 | throw new DomainError(this+" doesn't support dyadic inverting of ⍺", this, w); 44 | } 45 | public Value under(Obj aa, Obj ww, Obj o, Value w, DerivedDop derv) { 46 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, ww, w, derv)) : (Value) o; 47 | return callInv(aa, ww, v); 48 | } 49 | public Value underW(Obj aa, Obj ww, Obj o, Value a, Value w, DerivedDop derv) { 50 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, ww, a, w, derv)) : (Value) o; 51 | return callInvW(aa, ww, a, v); 52 | } 53 | public Value underA(Obj aa, Obj ww, Obj o, Value a, Value w, DerivedDop derv) { 54 | Value v = o instanceof Fun? ((Fun) o).call(call(aa, ww, a, w, derv)) : (Value) o; 55 | return callInvA(aa, ww, v, w); 56 | } 57 | 58 | public String toString() { 59 | return repr(); 60 | } 61 | public abstract String repr(); 62 | 63 | protected Fun isFn(Obj o, char c) { 64 | if (!(o instanceof Fun)) throw new SyntaxError(repr()+": "+c+" must be a function", this); 65 | return (Fun) o; 66 | } 67 | 68 | // operators are equal per-object basis 69 | @Override public int hashCode() { 70 | return actualHashCode(); 71 | } 72 | @Override public boolean equals(Obj o) { 73 | return this == o; 74 | } 75 | } -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/fns/TildeBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.fns; 2 | 3 | import APL.Main; 4 | import APL.errors.DomainError; 5 | import APL.types.*; 6 | import APL.types.arrs.*; 7 | import APL.types.functions.Builtin; 8 | 9 | public class TildeBuiltin extends Builtin { 10 | @Override public String repr() { 11 | return "~"; 12 | } 13 | public Value call(Value w) { 14 | return rec(w); 15 | } 16 | 17 | public Value callInv(Value w) { 18 | return rec(w); 19 | } 20 | 21 | private Value rec(Value w) { 22 | if (w instanceof Arr) { 23 | if (w instanceof BitArr) { 24 | BitArr wb = (BitArr) w; 25 | long[] res = new long[wb.llen()]; 26 | for (int i = 0; i < res.length; i++) res[i] = ~wb.arr[i]; 27 | return new BitArr(res, w.shape); 28 | } 29 | 30 | if (w.quickDoubleArr()) { 31 | // for (int i = 0; i < w.length; i++) if (w[i] == 0) res[i>>6]|= 1L << (i&63); 32 | BitArr.BA a = new BitArr.BA(w.shape); 33 | for (double v : w.asDoubleArr()) a.add(v == 0); 34 | return a.finish(); 35 | } 36 | 37 | Arr o = (Arr) w; 38 | if (o.ia>0 && o.get(0) instanceof Num) { 39 | BitArr.BA a = new BitArr.BA(w.ia); // it's probably worth going all-in on creating a bitarr 40 | for (int i = 0; i < o.ia; i++) { 41 | Value v = o.get(i); 42 | if (v instanceof Num) a.add(!Main.bool(v)); 43 | else { 44 | a = null; 45 | break; 46 | } 47 | } 48 | if (a != null) return a.finish(); 49 | // could make it reuse the progress made, but ¯\_(ツ)_/¯ 50 | } 51 | Value[] arr = new Value[o.ia]; 52 | for (int i = 0; i < o.ia; i++) { 53 | arr[i] = rec(o.get(i)); 54 | } 55 | return new HArr(arr, o.shape); 56 | } else if (w instanceof Num) return Main.bool(w)? Num.ZERO : Num.ONE; 57 | else throw new DomainError("Expected boolean, got "+w.humanType(false), this, w); 58 | } 59 | 60 | public static BitArr call(BitArr w) { 61 | BitArr.BC bc = BitArr.create(w.shape); 62 | for (int i = 0; i < bc.arr.length; i++) { 63 | bc.arr[i] = ~w.arr[i]; 64 | } 65 | return bc.finish(); 66 | } 67 | 68 | public Value call(Value a, Value w) { 69 | int ia = 0; 70 | boolean[] leave = new boolean[a.ia]; 71 | a: for (int i = 0; i < a.ia; i++) { 72 | Value v = a.get(i); 73 | for (var c : w) { 74 | if (v.equals(c)) continue a; 75 | } 76 | leave[i] = true; 77 | ia++; 78 | } 79 | Value[] res = new Value[ia]; 80 | int pos = 0; 81 | for (int i = 0; i < leave.length; i++) { 82 | if (leave[i]) { 83 | res[pos++] = a.get(i); 84 | } 85 | } 86 | return Arr.create(res); 87 | } 88 | } -------------------------------------------------------------------------------- /docs/chars.txt: -------------------------------------------------------------------------------- 1 | fns: 2 | dyadic monadic 3 | + add; identity (no complex numbers) 4 | - sub; negate / swap case 5 | × mul; sign / case (i.e. ×'Hi ' → 1 ¯1 0) / ×|map 6 | ÷ div; 1÷⍵ 7 | * pow; e*⍵ 8 | ⍟ log; e⍟⍵ 9 | √ root; 2√⍵ 10 | ⌈ max; ceil / uppercase 11 | ⌊ min; floor / lowercase 12 | | mod; abs / map size 13 | ∧ lcm; lcm (aka every; all 1) 14 | ∨ gcd; gcd (aka some; contains 1) 15 | ⍲ nand; not all / contains 0 16 | ⍱ nor; none / all 0 17 | ⊥ from; 2⊥⍵; aka decode, pack 18 | ⊤ to; 2⊤⍵; aka encode, unpack 19 | ○ trig; pi×⍵ 20 | ! nCk; factorial 21 | 22 | monadic dyadic 23 | ∊ in; enlist 24 | ⍷ NYI; find 25 | ⌷ map k&v; select cell 26 | ⍳ indexes; where 27 | ~ without; negate 28 | ⍸ where; NYI; where can contain >1; also ⍸⍣¯1 is useful 29 | ⍴ shape; reshape 30 | , ravel; concat 31 | ⍮ ,⊂; {⍺⍵} 32 | ≢ tally; not equal 33 | ≡ depth; equal 34 | ⊢ ⍵; ⍵ 35 | ⊣ ⍵; ⍺ 36 | ↑ merge; take; merge as in merge dimensions 37 | ↓ split; drop; split off last dimension as arrays 38 | ? rand; deal 39 | ⍪ table; vertical concat 40 | ⊖ flip; vertical rotate 41 | ⌽ reverse; horizontal rotate 42 | … NYI; range 43 | ⍕ format; NYI 44 | ⍎ eval; eval arrayified (`-⍎4) 45 | ⌿ NYI; replicate 46 | ⍀ NYI; expand 47 | ∪ unique; union 48 | ∩ NYI; intersection 49 | ⊂ enclose; split 50 | ⊃ first; get single item ('ab'≡1 1⊃2 2⍴⊂'ab') 51 | ⊇ NYI; multi-select (subject to ⎕VI) 52 | % NYI; merge - 1 2 2 3%4↑¨⎕a⎕l⎕d → 'Abc3' 53 | ⍋ grade up; NYI 54 | ⍒ grade down; NYI 55 | ⍉ transpose; NYI 56 | ⍧ unique mask; count 57 | 58 | 59 | < lt; sort asc 60 | ≤ le; NYI 61 | = eq; NYI 62 | ≥ ge; NYI 63 | > gt; sort desc 64 | ≠ ne; NYI (⍧ is unique mask) 65 | 66 | monadic ops: 67 | 68 | / reduce 69 | \ left scan 70 | ¨ for each 71 | ⍨ selfie; commute 72 | ⌾ table (aka ∘.⍺⍺) 73 | ⌸ key; also get/set map keys (e.g. 'x'(map⌸)5; map⌸'x') 74 | ᐵ each-left (A fᐵ B ≡ A f¨ ⊂B) 75 | ᑈ each-right (A fᑈ B ≡ (⊂A) f¨ B) 76 | 77 | dyadic ops 78 | 79 | ∘ compose (←→ {⍶ ⍹ ⍵} or {⍺ ⍶ ⍹ ⍵}) 80 | ⍛ left-compose (←→ {(⍶ ⍺) ⍹ ⍵}) 81 | . NYI (well, ←→ {⍶/ ⍺ ⍹ ⍵}) 82 | ⍣ repeat 83 | ⍡ cumulative repeat 84 | ⍥ over (←→ {(⍹⍺) ⍶ ⍹⍵} ) 85 | ⍤ atop (←→ {⍺⍺ ⍺ ⍵⍵ ⍵} ) 86 | ⍢ under (←→ {⍺←{⍺⍺⋄⍵}⋄(⍹⍣¯1) (⍹⍺) ⍶ ⍹⍵}; also is structural under; ⍺⍺ can be an array) 87 | ⍫ obverse - define inverse: ⍶ - regular function, ⍹ - inverse 88 | @ at; right op = indices or function giving boolean array, left op = replacement array or function 89 | ⍁ for each diagonal 90 | 91 | nilads: 92 | 93 | ⍬ 0⍴0 94 | ⎕ console (println; exec input line) 95 | ⍞ console (print ; input as string) 96 | ⍺ left arg 97 | ⍵ right arg 98 | ⍶ left operand 99 | ⍹ right operand 100 | ∇ this function 101 | 102 | dfns: 103 | {A ⋄ B} → B (also executing A) 104 | {C:A ⋄ B} → B (also executing A if C was true) 105 | {C:←A ⋄ B} → A if C, else B -------------------------------------------------------------------------------- /AndroidIDE/data/help_c.txt: -------------------------------------------------------------------------------- 1 | fns: 2 | dyadic monadic 3 | + add; identity (no complex numbers) 4 | - sub; negate / swap case 5 | × mul; sign / case (i.e. ×'Hi ' → 1 ¯1 0) / ×|map 6 | ÷ div; 1÷⍵ 7 | * pow; e*⍵ 8 | ⍟ log; e⍟⍵ 9 | √ root; 2√⍵ 10 | ⌈ max; ceil / uppercase 11 | ⌊ min; floor / lowercase 12 | | mod; abs / map size 13 | ∧ lcm; lcm (aka every; all 1) 14 | ∨ gcd; gcd (aka some; contains 1) 15 | ⍲ nand; not all / contains 0 16 | ⍱ nor; none / all 0 17 | ⊥ from; 2⊥⍵; aka decode, pack 18 | ⊤ to; 2⊤⍵; aka encode, unpack 19 | ○ trig; pi×⍵ 20 | ! nCk; factorial 21 | 22 | monadic dyadic 23 | ∊ in; enlist 24 | ⍷ NYI; find 25 | ⌷ map k&v; select cell 26 | ⍳ indexes; where 27 | ~ without; negate 28 | ⍸ where; NYI; where can contain >1; also ⍸⍣¯1 is useful 29 | ⍴ shape; reshape 30 | , ravel; concat 31 | ⍮ ,⊂; {⍺⍵} 32 | ≢ tally; not equal 33 | ≡ depth; equal 34 | ⊢ ⍵; ⍵ 35 | ⊣ ⍵; ⍺ 36 | ↑ merge; take; merge as in merge dimensions 37 | ↓ split; drop; split off last dimension as arrays 38 | ? rand; deal 39 | ⍪ table; vertical concat 40 | ⊖ flip; vertical rotate 41 | ⌽ reverse; horizontal rotate 42 | … NYI; range 43 | ⍕ format; NYI 44 | ⍎ eval; eval arrayified (`-⍎4) 45 | ⌿ NYI; replicate 46 | ⍀ NYI; expand 47 | ∪ unique; union 48 | ∩ NYI; intersection 49 | ⊂ enclose; split 50 | ⊃ first; get single item ('ab'≡1 1⊃2 2⍴⊂'ab') 51 | ⊇ NYI; multi-select (subject to ⎕VI) 52 | % NYI; merge - 1 2 2 3%4↑¨⎕a⎕l⎕d → 'Abc3' 53 | ⍋ grade up; NYI 54 | ⍒ grade down; NYI 55 | ⍉ transpose; NYI 56 | ⍧ unique mask; count 57 | 58 | 59 | < lt; sort asc 60 | ≤ le; NYI 61 | = eq; NYI 62 | ≥ ge; NYI 63 | > gt; sort desc 64 | ≠ ne; NYI (⍧ is unique mask) 65 | 66 | monadic ops: 67 | 68 | / reduce 69 | \ left scan 70 | ¨ for each 71 | ⍨ selfie; commute 72 | ⌾ table (aka ∘.⍺⍺) 73 | ⌸ key; also get/set map keys (e.g. 'x'(map⌸)5; map⌸'x') 74 | ᐵ each-left (A fᐵ B ≡ A f¨ ⊂B) 75 | ᑈ each-right (A fᑈ B ≡ (⊂A) f¨ B) 76 | 77 | dyadic ops 78 | 79 | ∘ compose (←→ {⍶ ⍹ ⍵} or {⍺ ⍶ ⍹ ⍵}) 80 | ⍛ left-compose (←→ {(⍶ ⍺) ⍹ ⍵}) 81 | . NYI (well, ←→ {⍶/ ⍺ ⍹ ⍵}) 82 | ⍣ repeat 83 | ⍡ cumulative repeat 84 | ⍥ over (←→ {(⍹⍺) ⍶ ⍹⍵} ) 85 | ⍤ atop (←→ {⍺⍺ ⍺ ⍵⍵ ⍵} ) 86 | ⍢ under (←→ {⍺←{⍺⍺⋄⍵}⋄(⍹⍣¯1) (⍹⍺) ⍶ ⍹⍵}; also is structural under; ⍺⍺ can be an array) 87 | ⍫ obverse - define inverse: ⍶ - regular function, ⍹ - inverse 88 | @ at; right op = indices or function giving boolean array, left op = replacement array or function 89 | ⍁ for each diagonal 90 | 91 | nilads: 92 | 93 | ⍬ 0⍴0 94 | ⎕ console (println; exec input line) 95 | ⍞ console (print ; input as string) 96 | ⍺ left arg 97 | ⍵ right arg 98 | ⍶ left operand 99 | ⍹ right operand 100 | ∇ this function 101 | 102 | dfns: 103 | {A ⋄ B} → B (also executing A) 104 | {C:A ⋄ B} → B (also executing A if C was true) 105 | {C:←A ⋄ B} → A if C, else B -------------------------------------------------------------------------------- /src/APL/types/functions/builtins/mops/TableBuiltin.java: -------------------------------------------------------------------------------- 1 | package APL.types.functions.builtins.mops; 2 | 3 | import APL.types.*; 4 | import APL.types.arrs.*; 5 | import APL.types.functions.*; 6 | 7 | public final class TableBuiltin extends Mop { 8 | @Override public String repr() { 9 | return "∘."; 10 | } 11 | 12 | 13 | public Value call(Obj f, Value a, Value w, DerivedMop derv) { 14 | int[] shape = new int[a.rank+w.rank]; 15 | System.arraycopy(a.shape, 0, shape, 0, a.rank); 16 | System.arraycopy(w.shape, 0, shape, a.rank, w.rank); 17 | 18 | if (a.ia==0 || w.ia==0) return new EmptyArr(shape, a.safePrototype()); 19 | 20 | Fun ff = (Fun) f; 21 | 22 | 23 | int i = 0; 24 | Value first = ff.call(a.first(), w.first()); 25 | 26 | if (first instanceof Num) { 27 | double[] dres = new double[a.ia * w.ia]; 28 | boolean allNums = true; 29 | boolean firstSkipped = false; 30 | Value failure = null; 31 | 32 | numatt: for (Value na : a) { 33 | for (Value nw : w) { 34 | Value r; 35 | if (firstSkipped) r = ff.call(na, nw); 36 | else { 37 | firstSkipped = true; 38 | r = first; 39 | } 40 | if (r instanceof Num) dres[i++] = ((Num) r).num; 41 | else { 42 | allNums = false; 43 | failure = r; 44 | break numatt; 45 | } 46 | } 47 | } 48 | if (allNums) { 49 | if (shape.length == 0) return new Num(dres[0]); 50 | return new DoubleArr(dres, shape); 51 | } else { // i points to the place the failure should be 52 | Value[] res = new Value[a.ia*w.ia]; 53 | for (int n = 0; n < i; n++) { // slowly copy the data back.. 54 | res[n] = new Num(dres[n]); 55 | } 56 | res[i++] = failure; // insert that horrible thing that broke everything 57 | if (i%w.ia != 0) { // finish the damn row.. 58 | Value va = a.get(i / w.ia); 59 | for (int wi = i % w.ia; wi < w.ia; wi++) { 60 | res[i++] = ff.call(va, w.get(wi)); 61 | } 62 | } 63 | for (int ai = (i+w.ia-1)/w.ia; ai < a.ia; ai++) { // and do the rest, slowly and horribly 64 | Value va = a.get(ai); 65 | for (Value vw : w) { 66 | res[i++] = ff.call(va, vw); 67 | } 68 | } 69 | if (shape.length == 0 && res[0] instanceof Primitive) return res[0]; 70 | return Arr.create(res, shape); 71 | } 72 | } 73 | boolean firstSkipped = false; 74 | Value[] arr = new Value[a.ia*w.ia]; 75 | for (Value na : a) { 76 | for (Value nw : w) { 77 | if (firstSkipped) arr[i++] = ff.call(na, nw); 78 | else { 79 | firstSkipped = true; 80 | arr[i++] = first; 81 | } 82 | } 83 | } 84 | if (shape.length == 0 && arr[0] instanceof Primitive) return arr[0]; 85 | return Arr.create(arr, shape); 86 | } 87 | } -------------------------------------------------------------------------------- /AndroidIDE/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); 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 | }); -------------------------------------------------------------------------------- /src/APL/errors/APLError.java: -------------------------------------------------------------------------------- 1 | package APL.errors; 2 | 3 | import APL.*; 4 | import APL.tokenizer.Token; 5 | import APL.types.*; 6 | 7 | import java.util.*; 8 | 9 | public abstract class APLError extends RuntimeException { 10 | public Tokenable cause; 11 | 12 | protected APLError(String msg) { 13 | super(msg); 14 | } 15 | protected APLError(String msg, Tokenable blame) { 16 | super(msg); 17 | if (blame instanceof Callable) Main.faulty = blame; 18 | else cause = blame; 19 | } 20 | protected APLError(String msg, Callable blame, Tokenable cause) { 21 | super(msg); 22 | Main.faulty = blame; 23 | this.cause = cause; 24 | } 25 | 26 | 27 | public void print(Sys s) { 28 | String type = getClass().getSimpleName(); 29 | String msg = getMessage(); 30 | if (msg == null) msg = ""; 31 | if (msg.length() == 0) s.colorprint(type, 246); 32 | else s.colorprint(type + ": " + msg, 246); 33 | ArrayList l = new ArrayList<>(); 34 | Tokenable faulty = Main.faulty; 35 | if (faulty!=null) Mg.add(l, faulty, '^'); 36 | if (cause !=null) Mg.add(l, cause , '¯'); 37 | if (l.size() == 2 && l.get(0).eqSrc(l.get(1))) println(s, l); 38 | else for (Mg g : l) { 39 | ArrayList c = new ArrayList<>(); 40 | c.add(g); 41 | println(s, c); 42 | } 43 | } 44 | 45 | public void println(Sys s, List gs) { 46 | if (gs.size() == 0) return; 47 | 48 | String raw = gs.get(0).raw; 49 | int lns = gs.get(0).lns; 50 | 51 | int lne = raw.indexOf("\n", lns); 52 | if (lne == -1) lne = raw.length(); 53 | 54 | String ln = gs.get(0).raw.substring(lns, lne); 55 | s.println(ln); 56 | char[] str = new char[ln.length()]; 57 | for (int i = 0; i < str.length; i++) { 58 | char c = ' '; 59 | for (Mg g : gs) if (i>=g.spos && i l, Tokenable to, char c) { 82 | Token t = to.getToken(); 83 | if (t == null) return; 84 | 85 | String raw = t.raw; 86 | 87 | int lns = raw.lastIndexOf("\n", t.spos) + 1; // not found handles itself 88 | 89 | 90 | int spos = t.spos - lns; 91 | int epos = (t.epos==Token.EPOS_DEF? spos+1 : t.epos) - lns; 92 | 93 | l.add(new Mg(t, c, raw, lns, spos, epos)); 94 | } 95 | 96 | boolean eqSrc(Mg g) { 97 | // noinspection StringEquality \\ we want that 98 | return raw==g.raw && lns==g.lns; 99 | } 100 | } 101 | } --------------------------------------------------------------------------------