Skip to content

Commit 93739c4

Browse files
shaunxcodemarijnh
authored andcommitted
Add APL mode
1 parent 75f2961 commit 93739c4

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

mode/apl/apl.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
CodeMirror.defineMode("apl", function(config, parserConfig) {
2+
var builtInOps = {
3+
".": "innerProduct",
4+
"\\": "scan",
5+
"/": "reduce",
6+
"⌿": "reduce1Axis",
7+
"⍀": "scan1Axis",
8+
"¨": "each",
9+
"⍣": "power"
10+
};
11+
var builtInFuncs = {
12+
"+": ["conjugate", "add"],
13+
"−": ["negate", "subtract"],
14+
"×": ["signOf", "multiply"],
15+
"÷": ["reciprocal", "divide"],
16+
"⌈": ["ceiling", "greaterOf"],
17+
"⌊": ["floor", "lesserOf"],
18+
"∣": ["absolute", "residue"],
19+
"⍳": ["indexGenerate", "indexOf"],
20+
"?": ["roll", "deal"],
21+
"⋆": ["exponentiate", "toThePowerOf"],
22+
"⍟": ["naturalLog", "logToTheBase"],
23+
"○": ["piTimes", "circularFuncs"],
24+
"!": ["factorial", "binomial"],
25+
"⌹": ["matrixInverse", "matrixDivide"],
26+
"<": [null, "lessThan"],
27+
"≤": [null, "lessThanOrEqual"],
28+
"=": [null, "equals"],
29+
">": [null, "greaterThan"],
30+
"≥": [null, "greaterThanOrEqual"],
31+
"≠": [null, "notEqual"],
32+
"≡": ["depth", "match"],
33+
"≢": [null, "notMatch"],
34+
"∈": ["enlist", "membership"],
35+
"⍷": [null, "find"],
36+
"∪": ["unique", "union"],
37+
"∩": [null, "intersection"],
38+
"∼": ["not", "without"],
39+
"∨": [null, "or"],
40+
"∧": [null, "and"],
41+
"⍱": [null, "nor"],
42+
"⍲": [null, "nand"],
43+
"⍴": ["shapeOf", "reshape"],
44+
",": ["ravel", "catenate"],
45+
"⍪": [null, "firstAxisCatenate"],
46+
"⌽": ["reverse", "rotate"],
47+
"⊖": ["axis1Reverse", "axis1Rotate"],
48+
"⍉": ["transpose", null],
49+
"↑": ["first", "take"],
50+
"↓": [null, "drop"],
51+
"⊂": ["enclose", "partitionWithAxis"],
52+
"⊃": ["diclose", "pick"],
53+
"⌷": [null, "index"],
54+
"⍋": ["gradeUp", null],
55+
"⍒": ["gradeDown", null],
56+
"⊤": ["encode", null],
57+
"⊥": ["decode", null],
58+
"⍕": ["format", "formatByExample"],
59+
"⍎": ["execute", null],
60+
"⊣": ["stop", "left"],
61+
"⊢": ["pass", "right"]
62+
};
63+
64+
var isOperator = /[\.\/¨]/;
65+
var isNiladic = //;
66+
var isFunction = /[\+×÷\?!<=>,]/;
67+
var isArrow = //;
68+
var isComment = /[#].*$/;
69+
70+
var stringEater = function(type) {
71+
var prev;
72+
prev = false;
73+
return function(c) {
74+
prev = c;
75+
if (c === type) {
76+
return prev === "\\";
77+
}
78+
return true;
79+
};
80+
};
81+
return {
82+
startState: function() {
83+
return {
84+
prev: false,
85+
func: false,
86+
op: false,
87+
string: false,
88+
escape: false
89+
};
90+
},
91+
token: function(stream, state) {
92+
var ch, funcName, word;
93+
if (stream.eatSpace()) {
94+
return null;
95+
}
96+
ch = stream.next();
97+
if (ch === '"' || ch === "'") {
98+
stream.eatWhile(stringEater(ch));
99+
stream.next();
100+
state.prev = true;
101+
return "string";
102+
}
103+
if (/[\[{\(]/.test(ch)) {
104+
state.prev = false;
105+
return null;
106+
}
107+
if (/[\]}\)]/.test(ch)) {
108+
state.prev = true;
109+
return null;
110+
}
111+
if (isNiladic.test(ch)) {
112+
state.prev = false;
113+
return "niladic";
114+
}
115+
if (/[¯\d]/.test(ch)) {
116+
if (state.func) {
117+
state.func = false;
118+
state.prev = false;
119+
} else {
120+
state.prev = true;
121+
}
122+
stream.eatWhile(/[\w\.]/);
123+
return "number";
124+
}
125+
if (isOperator.test(ch)) {
126+
return "operator apl-" + builtInOps[ch];
127+
}
128+
if (isArrow.test(ch)) {
129+
return "apl-arrow";
130+
}
131+
if (isFunction.test(ch)) {
132+
funcName = "apl-";
133+
if (builtInFuncs[ch] != null) {
134+
if (state.prev) {
135+
funcName += builtInFuncs[ch][1];
136+
} else {
137+
funcName += builtInFuncs[ch][0];
138+
}
139+
}
140+
state.func = true;
141+
state.prev = false;
142+
return "function " + funcName;
143+
}
144+
if (isComment.test(ch)) {
145+
stream.skipToEnd();
146+
return "comment";
147+
}
148+
if (ch === "∘" && stream.peek() === ".") {
149+
stream.next();
150+
return "function jot-dot";
151+
}
152+
stream.eatWhile(/[\w\$_]/);
153+
word = stream.current();
154+
state.prev = true;
155+
return "keyword";
156+
}
157+
};
158+
});
159+
160+
CodeMirror.defineMIME("text/apl", "apl");

mode/apl/index.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>CodeMirror: APL mode</title>
6+
<link rel="stylesheet" href="../../doc/docs.css">
7+
<link rel="stylesheet" href="../../lib/codemirror.css">
8+
<script src="../../lib/codemirror.js"></script>
9+
<script src="../../addon/edit/matchbrackets.js"></script>
10+
<script src="./apl.js"></script>
11+
<style>
12+
.CodeMirror { border: 2px inset #dee; }
13+
</style>
14+
</head>
15+
<body>
16+
<h1>CodeMirror: APL mode</h1>
17+
18+
<form><textarea id="code" name="code">
19+
⍝ Conway's game of life
20+
21+
⍝ This example was inspired by the impressive demo at
22+
⍝ http://www.youtube.com/watch?v=a9xAKttWgP4
23+
24+
⍝ Create a matrix:
25+
⍝ 0 1 1
26+
⍝ 1 1 0
27+
⍝ 0 1 0
28+
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7 ⍝ Original creature from demo
29+
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8 ⍝ Glider
30+
31+
⍝ Place the creature on a larger board, near the centre
32+
board ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature
33+
34+
⍝ A function to move from one generation to the next
35+
life ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}
36+
37+
⍝ Compute n-th generation and format it as a
38+
⍝ character matrix
39+
gen ← {' #'[(life ⍣ ⍵) board]}
40+
41+
⍝ Show first three generations
42+
(gen 1) (gen 2) (gen 3)
43+
</textarea></form>
44+
45+
<script>
46+
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
47+
lineNumbers: true,
48+
matchBrackets: true,
49+
mode: "text/apl"
50+
});
51+
</script>
52+
53+
<p>Simple mode that tries to handle APL as well as it can.</p>
54+
<p>It attempts to label functions/operators based upon
55+
monadic/dyadic usage (but this is far from fully fleshed out).
56+
This means there are meaningful classnames so hover states can
57+
have popups etc.</p>
58+
59+
<p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>
60+
</body>
61+
</html>

0 commit comments

Comments
 (0)