xanascript 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -0
- package/VERSION +1 -0
- package/llms.txt +322 -0
- package/package.json +33 -0
- package/src/ast.js +65 -0
- package/src/bench.js +68 -0
- package/src/bytecode/compiler.js +189 -0
- package/src/bytecode/opcodes.js +36 -0
- package/src/bytecode/vm.js +216 -0
- package/src/cli.js +535 -0
- package/src/codegen.js +101 -0
- package/src/codegen_opt.js +352 -0
- package/src/codegen_wasm.js +306 -0
- package/src/docsgen.js +262 -0
- package/src/errors.js +162 -0
- package/src/interpreter.js +471 -0
- package/src/lexer.js +195 -0
- package/src/lsp.js +304 -0
- package/src/macros.js +132 -0
- package/src/optimizer.js +175 -0
- package/src/orm.js +120 -0
- package/src/parser.js +819 -0
- package/src/pkgmgr.js +273 -0
- package/src/runtime.js +171 -0
- package/src/sourcemap.js +120 -0
- package/src/testrunner.js +118 -0
- package/src/wasm_binary.js +573 -0
- package/std/math.xs +60 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { OP } from "./opcodes.js";
|
|
2
|
+
|
|
3
|
+
export function compile(ast) {
|
|
4
|
+
const code = [];
|
|
5
|
+
|
|
6
|
+
emitNode(ast);
|
|
7
|
+
|
|
8
|
+
code.push([OP.HALT]);
|
|
9
|
+
|
|
10
|
+
return code;
|
|
11
|
+
|
|
12
|
+
function emit(op, arg = null) {
|
|
13
|
+
code.push([op, arg]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function emitNode(node) {
|
|
17
|
+
switch (node.type) {
|
|
18
|
+
|
|
19
|
+
case "Program":
|
|
20
|
+
node.body.forEach(emitNode);
|
|
21
|
+
break;
|
|
22
|
+
|
|
23
|
+
case "Block":
|
|
24
|
+
node.body.forEach(emitNode);
|
|
25
|
+
break;
|
|
26
|
+
|
|
27
|
+
case "Num":
|
|
28
|
+
emit(OP.PUSH, node.value);
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case "Str":
|
|
32
|
+
emit(OP.PUSH, node.value);
|
|
33
|
+
break;
|
|
34
|
+
|
|
35
|
+
case "Bool":
|
|
36
|
+
emit(OP.PUSH, node.value);
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case "Nil":
|
|
40
|
+
emit(OP.PUSH, null);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case "Ident":
|
|
44
|
+
emit(OP.LOAD, node.name);
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
case "VarDecl":
|
|
48
|
+
emitNode(node.init);
|
|
49
|
+
emit(OP.STORE, node.id);
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case "Assign":
|
|
53
|
+
emitNode(node.right);
|
|
54
|
+
emit(OP.STORE, node.left.name);
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case "Binary":
|
|
58
|
+
emitNode(node.left);
|
|
59
|
+
emitNode(node.right);
|
|
60
|
+
|
|
61
|
+
switch (node.op) {
|
|
62
|
+
case "+": emit(OP.ADD); break;
|
|
63
|
+
case "-": emit(OP.SUB); break;
|
|
64
|
+
case "*": emit(OP.MUL); break;
|
|
65
|
+
case "/": emit(OP.DIV); break;
|
|
66
|
+
case "%": emit(OP.MOD); break;
|
|
67
|
+
case "==": emit(OP.EQ); break;
|
|
68
|
+
case "!=": emit(OP.NEQ); break;
|
|
69
|
+
case "<": emit(OP.LT); break;
|
|
70
|
+
case ">": emit(OP.GT); break;
|
|
71
|
+
case "<=": emit(OP.LTE); break;
|
|
72
|
+
case ">=": emit(OP.GTE); break;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
case "Unary":
|
|
78
|
+
emitNode(node.arg);
|
|
79
|
+
if (node.op === "!") emit(OP.NOT);
|
|
80
|
+
if (node.op === "-") emit(OP.PUSH, 0); emit(OP.SWAP); emit(OP.SUB);
|
|
81
|
+
break;
|
|
82
|
+
|
|
83
|
+
case "IfStmt": {
|
|
84
|
+
emitNode(node.test);
|
|
85
|
+
const jmpfIdx = code.length;
|
|
86
|
+
emit(OP.JMPF, 0);
|
|
87
|
+
emitNode(node.cons);
|
|
88
|
+
if (node.alt) {
|
|
89
|
+
const jmpIdx = code.length;
|
|
90
|
+
emit(OP.JMP, 0);
|
|
91
|
+
code[jmpfIdx][1] = code.length;
|
|
92
|
+
emitNode(node.alt);
|
|
93
|
+
code[jmpIdx][1] = code.length;
|
|
94
|
+
} else {
|
|
95
|
+
code[jmpfIdx][1] = code.length;
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
case "ForStmt": {
|
|
101
|
+
if (node.init) emitNode(node.init);
|
|
102
|
+
const loopStart = code.length;
|
|
103
|
+
emitNode(node.test);
|
|
104
|
+
const jmpfIdx = code.length;
|
|
105
|
+
emit(OP.JMPF, 0);
|
|
106
|
+
emitNode(node.body);
|
|
107
|
+
if (node.update) emitNode(node.update);
|
|
108
|
+
emit(OP.JMP, loopStart);
|
|
109
|
+
code[jmpfIdx][1] = code.length;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
case "WhileStmt": {
|
|
114
|
+
const loopStart = code.length;
|
|
115
|
+
emitNode(node.test);
|
|
116
|
+
const jmpfIdx = code.length;
|
|
117
|
+
emit(OP.JMPF, 0);
|
|
118
|
+
emitNode(node.body);
|
|
119
|
+
emit(OP.JMP, loopStart);
|
|
120
|
+
code[jmpfIdx][1] = code.length;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
case "Call": {
|
|
125
|
+
if (
|
|
126
|
+
node.callee.type === "Ident" &&
|
|
127
|
+
node.callee.name === "SOLTA_O_GRITO"
|
|
128
|
+
) {
|
|
129
|
+
for (const arg of node.args) {
|
|
130
|
+
emitNode(arg);
|
|
131
|
+
}
|
|
132
|
+
emit(OP.PRINT, node.args.length);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (
|
|
137
|
+
node.callee.type === "Ident" &&
|
|
138
|
+
node.callee.name === "FALA_BAIXO"
|
|
139
|
+
) {
|
|
140
|
+
for (const arg of node.args) {
|
|
141
|
+
emitNode(arg);
|
|
142
|
+
}
|
|
143
|
+
emit(OP.WARN, node.args.length);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const arg of node.args) {
|
|
148
|
+
emitNode(arg);
|
|
149
|
+
}
|
|
150
|
+
emitNode(node.callee);
|
|
151
|
+
emit(OP.CALL, node.args.length);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
case "Member": {
|
|
156
|
+
emitNode(node.obj);
|
|
157
|
+
emit(OP.PUSH, node.prop);
|
|
158
|
+
emit(OP.MEMBER);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
case "IndexExpr": {
|
|
163
|
+
emitNode(node.obj);
|
|
164
|
+
emitNode(node.index);
|
|
165
|
+
emit(OP.INDEX);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
case "ArrayExpr": {
|
|
170
|
+
for (const item of node.items) {
|
|
171
|
+
emitNode(item);
|
|
172
|
+
}
|
|
173
|
+
emit(OP.PUSH, node.items.length);
|
|
174
|
+
emit(OP.ARRAY);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
case "ObjectExpr": {
|
|
179
|
+
for (const p of node.props) {
|
|
180
|
+
emit(OP.PUSH, p.key);
|
|
181
|
+
emitNode(p.value);
|
|
182
|
+
}
|
|
183
|
+
emit(OP.PUSH, node.props.length * 2);
|
|
184
|
+
emit(OP.OBJECT);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const OP = {
|
|
2
|
+
PUSH: 0,
|
|
3
|
+
|
|
4
|
+
ADD: 1,
|
|
5
|
+
SUB: 2,
|
|
6
|
+
MUL: 3,
|
|
7
|
+
DIV: 4,
|
|
8
|
+
MOD: 5,
|
|
9
|
+
|
|
10
|
+
STORE: 6,
|
|
11
|
+
LOAD: 7,
|
|
12
|
+
|
|
13
|
+
EQ: 8,
|
|
14
|
+
NEQ: 9,
|
|
15
|
+
LT: 10,
|
|
16
|
+
GT: 11,
|
|
17
|
+
LTE: 12,
|
|
18
|
+
GTE: 13,
|
|
19
|
+
NOT: 14,
|
|
20
|
+
|
|
21
|
+
PRINT: 15,
|
|
22
|
+
|
|
23
|
+
JMP: 16,
|
|
24
|
+
JMPF: 17,
|
|
25
|
+
JMPT: 18,
|
|
26
|
+
|
|
27
|
+
CALL: 19,
|
|
28
|
+
MEMBER: 20,
|
|
29
|
+
INDEX: 21,
|
|
30
|
+
ARRAY: 22,
|
|
31
|
+
OBJECT: 23,
|
|
32
|
+
SWAP: 24,
|
|
33
|
+
WARN: 25,
|
|
34
|
+
|
|
35
|
+
HALT: 26
|
|
36
|
+
};
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { OP } from "./opcodes.js";
|
|
2
|
+
|
|
3
|
+
export function run(code) {
|
|
4
|
+
const stack = [];
|
|
5
|
+
const globals = {};
|
|
6
|
+
let ip = 0;
|
|
7
|
+
let last = null;
|
|
8
|
+
|
|
9
|
+
while (ip < code.length) {
|
|
10
|
+
const instr = code[ip];
|
|
11
|
+
const op = instr[0];
|
|
12
|
+
const arg = instr[1];
|
|
13
|
+
|
|
14
|
+
switch (op) {
|
|
15
|
+
|
|
16
|
+
case OP.PUSH:
|
|
17
|
+
stack.push(arg);
|
|
18
|
+
break;
|
|
19
|
+
|
|
20
|
+
case OP.LOAD:
|
|
21
|
+
stack.push(globals[arg]);
|
|
22
|
+
break;
|
|
23
|
+
|
|
24
|
+
case OP.STORE: {
|
|
25
|
+
const val = stack.pop();
|
|
26
|
+
globals[arg] = val;
|
|
27
|
+
last = val;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
case OP.ADD: {
|
|
32
|
+
const b = stack.pop();
|
|
33
|
+
const a = stack.pop();
|
|
34
|
+
stack.push(a + b);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
case OP.SUB: {
|
|
39
|
+
const b = stack.pop();
|
|
40
|
+
const a = stack.pop();
|
|
41
|
+
stack.push(a - b);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
case OP.MUL: {
|
|
46
|
+
const b = stack.pop();
|
|
47
|
+
const a = stack.pop();
|
|
48
|
+
stack.push(a * b);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case OP.DIV: {
|
|
53
|
+
const b = stack.pop();
|
|
54
|
+
const a = stack.pop();
|
|
55
|
+
stack.push(a / b);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
case OP.MOD: {
|
|
60
|
+
const b = stack.pop();
|
|
61
|
+
const a = stack.pop();
|
|
62
|
+
stack.push(a % b);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
case OP.EQ: {
|
|
67
|
+
const b = stack.pop();
|
|
68
|
+
const a = stack.pop();
|
|
69
|
+
stack.push(a == b);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
case OP.NEQ: {
|
|
74
|
+
const b = stack.pop();
|
|
75
|
+
const a = stack.pop();
|
|
76
|
+
stack.push(a != b);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
case OP.LT: {
|
|
81
|
+
const b = stack.pop();
|
|
82
|
+
const a = stack.pop();
|
|
83
|
+
stack.push(a < b);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case OP.GT: {
|
|
88
|
+
const b = stack.pop();
|
|
89
|
+
const a = stack.pop();
|
|
90
|
+
stack.push(a > b);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
case OP.LTE: {
|
|
95
|
+
const b = stack.pop();
|
|
96
|
+
const a = stack.pop();
|
|
97
|
+
stack.push(a <= b);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case OP.GTE: {
|
|
102
|
+
const b = stack.pop();
|
|
103
|
+
const a = stack.pop();
|
|
104
|
+
stack.push(a >= b);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
case OP.NOT: {
|
|
109
|
+
const a = stack.pop();
|
|
110
|
+
stack.push(!a);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case OP.JMP:
|
|
115
|
+
ip = arg;
|
|
116
|
+
continue;
|
|
117
|
+
|
|
118
|
+
case OP.JMPF: {
|
|
119
|
+
const val = stack.pop();
|
|
120
|
+
if (!val) {
|
|
121
|
+
ip = arg;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
case OP.JMPT: {
|
|
128
|
+
const val = stack.pop();
|
|
129
|
+
if (val) {
|
|
130
|
+
ip = arg;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
case OP.SWAP: {
|
|
137
|
+
const a = stack.pop();
|
|
138
|
+
const b = stack.pop();
|
|
139
|
+
stack.push(a);
|
|
140
|
+
stack.push(b);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
case OP.CALL: {
|
|
145
|
+
const fn = stack.pop();
|
|
146
|
+
const args = [];
|
|
147
|
+
for (let i = 0; i < arg; i++) {
|
|
148
|
+
args.unshift(stack.pop());
|
|
149
|
+
}
|
|
150
|
+
last = fn(...args);
|
|
151
|
+
stack.push(last);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
case OP.MEMBER: {
|
|
156
|
+
const prop = stack.pop();
|
|
157
|
+
const obj = stack.pop();
|
|
158
|
+
stack.push(obj[prop]);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
case OP.INDEX: {
|
|
163
|
+
const idx = stack.pop();
|
|
164
|
+
const obj = stack.pop();
|
|
165
|
+
stack.push(obj[idx]);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
case OP.ARRAY: {
|
|
170
|
+
const arr = [];
|
|
171
|
+
for (let i = 0; i < arg; i++) {
|
|
172
|
+
arr.unshift(stack.pop());
|
|
173
|
+
}
|
|
174
|
+
stack.push(arr);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
case OP.OBJECT: {
|
|
179
|
+
const total = arg;
|
|
180
|
+
const obj = {};
|
|
181
|
+
const pairs = [];
|
|
182
|
+
for (let i = 0; i < total; i++) {
|
|
183
|
+
pairs.unshift(stack.pop());
|
|
184
|
+
}
|
|
185
|
+
for (let i = 0; i < pairs.length; i += 2) {
|
|
186
|
+
obj[pairs[i]] = pairs[i + 1];
|
|
187
|
+
}
|
|
188
|
+
stack.push(obj);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
case OP.PRINT: {
|
|
193
|
+
const vals = [];
|
|
194
|
+
for (let i = 0; i < arg; i++) {
|
|
195
|
+
vals.unshift(stack.pop());
|
|
196
|
+
}
|
|
197
|
+
console.log(...vals);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
case OP.WARN: {
|
|
202
|
+
const vals = [];
|
|
203
|
+
for (let i = 0; i < arg; i++) {
|
|
204
|
+
vals.unshift(stack.pop());
|
|
205
|
+
}
|
|
206
|
+
console.warn(...vals);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case OP.HALT:
|
|
211
|
+
return last;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
ip++;
|
|
215
|
+
}
|
|
216
|
+
}
|