mevento 2.0.6 → 3.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/dist/cjs/index.js +8 -0
- package/{lib/mevento.d.ts → dist/esm/index.d.mts} +43 -42
- package/dist/esm/index.mjs +8 -0
- package/package.json +23 -29
- package/README.md +0 -59
- package/esm2020/lib/mevento.mjs +0 -2165
- package/esm2020/mevento.mjs +0 -5
- package/esm2020/public-api.mjs +0 -5
- package/fesm2015/mevento.mjs +0 -2244
- package/fesm2015/mevento.mjs.map +0 -1
- package/fesm2020/mevento.mjs +0 -2175
- package/fesm2020/mevento.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/public-api.d.ts +0 -1
package/fesm2015/mevento.mjs
DELETED
|
@@ -1,2244 +0,0 @@
|
|
|
1
|
-
import { __awaiter } from 'tslib';
|
|
2
|
-
|
|
3
|
-
function error(token, expected) {
|
|
4
|
-
const text = `Invalid token ${token.type}[${token.value}] at ${token.line}, ${token.col} ${expected ? `: expecting ${expected} token` : ''}\n`;
|
|
5
|
-
throw Error(text);
|
|
6
|
-
}
|
|
7
|
-
function isNum(value) {
|
|
8
|
-
return typeof value === 'number';
|
|
9
|
-
}
|
|
10
|
-
function isBoolean(value) {
|
|
11
|
-
return typeof value === 'boolean';
|
|
12
|
-
}
|
|
13
|
-
function isString(value) {
|
|
14
|
-
return typeof value === 'string';
|
|
15
|
-
}
|
|
16
|
-
function _boolValue(test) {
|
|
17
|
-
return (test === null ||
|
|
18
|
-
(isNum(test) && test === 0) ||
|
|
19
|
-
(isString(test) && test.length === 0) ||
|
|
20
|
-
(isBoolean(test) && !test)) ? false : true;
|
|
21
|
-
}
|
|
22
|
-
;
|
|
23
|
-
function hashCode(str) {
|
|
24
|
-
let hash = 0;
|
|
25
|
-
let i = 0;
|
|
26
|
-
let chr;
|
|
27
|
-
if (str.length === 0)
|
|
28
|
-
return hash;
|
|
29
|
-
for (i = 0; i < str.length; i++) {
|
|
30
|
-
chr = str.charCodeAt(i);
|
|
31
|
-
hash = ((hash << 5) - hash) + chr;
|
|
32
|
-
hash |= 0; // Convert to 32bit integer
|
|
33
|
-
}
|
|
34
|
-
return hash;
|
|
35
|
-
}
|
|
36
|
-
;
|
|
37
|
-
class TokenType {
|
|
38
|
-
}
|
|
39
|
-
TokenType.id = 0;
|
|
40
|
-
TokenType.comma = 1;
|
|
41
|
-
TokenType.semi = 2;
|
|
42
|
-
TokenType.numberConst = 3;
|
|
43
|
-
TokenType.stringConst = 4;
|
|
44
|
-
TokenType.equal = 5;
|
|
45
|
-
TokenType.lparen = 6;
|
|
46
|
-
TokenType.rparen = 7;
|
|
47
|
-
TokenType.eol = 8;
|
|
48
|
-
TokenType.eof = 9;
|
|
49
|
-
TokenType.lbrace = 10;
|
|
50
|
-
TokenType.rbrace = 11;
|
|
51
|
-
TokenType.lbracket = 12;
|
|
52
|
-
TokenType.rbracket = 13;
|
|
53
|
-
TokenType.great = 14;
|
|
54
|
-
TokenType.greatEq = 15;
|
|
55
|
-
TokenType.less = 16;
|
|
56
|
-
TokenType.lessEq = 17;
|
|
57
|
-
TokenType.eqeq = 18;
|
|
58
|
-
TokenType.IF = 19;
|
|
59
|
-
TokenType.ELSE = 20;
|
|
60
|
-
TokenType.TRUE = 21;
|
|
61
|
-
TokenType.FALSE = 22;
|
|
62
|
-
TokenType.NULL = 23;
|
|
63
|
-
TokenType.not = 24;
|
|
64
|
-
TokenType.notEq = 25;
|
|
65
|
-
TokenType.and = 26;
|
|
66
|
-
TokenType.or = 27;
|
|
67
|
-
TokenType.plus = 28;
|
|
68
|
-
TokenType.minus = 29;
|
|
69
|
-
TokenType.div = 30;
|
|
70
|
-
TokenType.mult = 31;
|
|
71
|
-
TokenType.mod = 32;
|
|
72
|
-
TokenType.invalid = 33;
|
|
73
|
-
TokenType.colon = 34;
|
|
74
|
-
TokenType.WHILE_TILL = 35;
|
|
75
|
-
TokenType.FOR_LOOP = 36;
|
|
76
|
-
TokenType.up = 37;
|
|
77
|
-
TokenType.down = 38;
|
|
78
|
-
TokenType.with = 39;
|
|
79
|
-
TokenType.in = 40;
|
|
80
|
-
TokenType.TILL = 41;
|
|
81
|
-
TokenType.BREAK = 42;
|
|
82
|
-
TokenType.CONTINUE = 43;
|
|
83
|
-
TokenType.nullity = 44;
|
|
84
|
-
TokenType.RETURN = 45;
|
|
85
|
-
class Token {
|
|
86
|
-
constructor(type, value, line = 1, col = 1) {
|
|
87
|
-
this.type = type;
|
|
88
|
-
this.value = value;
|
|
89
|
-
this.line = line;
|
|
90
|
-
this.col = col;
|
|
91
|
-
}
|
|
92
|
-
static from(type, value) {
|
|
93
|
-
return new Token(type, value);
|
|
94
|
-
}
|
|
95
|
-
toString() {
|
|
96
|
-
return `[${this.type.toString()}, ${this.value}]`;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
class Chars {
|
|
100
|
-
}
|
|
101
|
-
Chars.equal = '='.charCodeAt(0);
|
|
102
|
-
Chars.comma = ','.charCodeAt(0);
|
|
103
|
-
Chars.semiColon = ';'.charCodeAt(0);
|
|
104
|
-
Chars.lparen = '('.charCodeAt(0);
|
|
105
|
-
Chars.rparen = ')'.charCodeAt(0);
|
|
106
|
-
Chars.backslash = '\\'.charCodeAt(0);
|
|
107
|
-
Chars.quote = '"'.charCodeAt(0);
|
|
108
|
-
Chars.squote = "'".charCodeAt(0);
|
|
109
|
-
Chars.plus = "+".charCodeAt(0);
|
|
110
|
-
Chars.minus = "-".charCodeAt(0);
|
|
111
|
-
Chars.star = "*".charCodeAt(0);
|
|
112
|
-
Chars.slash = "/".charCodeAt(0);
|
|
113
|
-
Chars.percent = "%".charCodeAt(0);
|
|
114
|
-
Chars.lbrace = "{".charCodeAt(0);
|
|
115
|
-
Chars.rbrace = "}".charCodeAt(0);
|
|
116
|
-
Chars.lbracket = "[".charCodeAt(0);
|
|
117
|
-
Chars.rbracket = "]".charCodeAt(0);
|
|
118
|
-
Chars.not = "!".charCodeAt(0);
|
|
119
|
-
Chars.great = ">".charCodeAt(0);
|
|
120
|
-
Chars.less = "<".charCodeAt(0);
|
|
121
|
-
Chars.and = "&".charCodeAt(0);
|
|
122
|
-
Chars.pipe = "|".charCodeAt(0);
|
|
123
|
-
Chars.colon = ":".charCodeAt(0);
|
|
124
|
-
Chars.questionMark = "?".charCodeAt(0);
|
|
125
|
-
Chars.shebang = "#".charCodeAt(0);
|
|
126
|
-
class LexerDictionary {
|
|
127
|
-
constructor(lang, keywords) {
|
|
128
|
-
this.keywords = {};
|
|
129
|
-
this.keywords = Object.assign({}, keywords);
|
|
130
|
-
this.lang = lang;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Lexing => Parsing ===> AST ===> Walking
|
|
135
|
-
*/
|
|
136
|
-
/**
|
|
137
|
-
* Lexer
|
|
138
|
-
*/
|
|
139
|
-
class Lexer {
|
|
140
|
-
constructor(source) {
|
|
141
|
-
this._position = 0;
|
|
142
|
-
this._line = 1;
|
|
143
|
-
this._col = 1;
|
|
144
|
-
this._currentChar = -1;
|
|
145
|
-
this._source = source;
|
|
146
|
-
this._currentChar = this._source[this._position].charCodeAt(0);
|
|
147
|
-
this._resolveLanguage();
|
|
148
|
-
}
|
|
149
|
-
get source() {
|
|
150
|
-
return this._source;
|
|
151
|
-
}
|
|
152
|
-
_resolveLanguage() {
|
|
153
|
-
var _a;
|
|
154
|
-
let token = this.nextToken();
|
|
155
|
-
if (token.type === TokenType.less) {
|
|
156
|
-
// language setting
|
|
157
|
-
const idToken = this.nextToken();
|
|
158
|
-
if (idToken.type !== TokenType.id) {
|
|
159
|
-
error(token);
|
|
160
|
-
}
|
|
161
|
-
const lang = idToken.value.toString();
|
|
162
|
-
this._language = (_a = Lexer.languages.find((element) => element.lang === lang)) !== null && _a !== void 0 ? _a : Lexer._defaultLanguage;
|
|
163
|
-
token = this.nextToken();
|
|
164
|
-
if (token.type !== TokenType.great) {
|
|
165
|
-
error(token);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
this._language = Lexer._defaultLanguage;
|
|
170
|
-
// reset reading
|
|
171
|
-
this._position = 0;
|
|
172
|
-
this._currentChar = this._source[this._position].charCodeAt(0);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
_advance() {
|
|
176
|
-
this._position++;
|
|
177
|
-
if (this._position >= this._source.length) {
|
|
178
|
-
this._currentChar = -1;
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
this._currentChar = this._source[this._position].charCodeAt(0);
|
|
182
|
-
this._col++;
|
|
183
|
-
}
|
|
184
|
-
_pick() {
|
|
185
|
-
if (this._position + 1 >= this._source.length) {
|
|
186
|
-
return -1;
|
|
187
|
-
}
|
|
188
|
-
return this._source[this._position + 1].charCodeAt(0);
|
|
189
|
-
}
|
|
190
|
-
_isId(code) {
|
|
191
|
-
if (code < 48) {
|
|
192
|
-
return code === 36;
|
|
193
|
-
}
|
|
194
|
-
if (code < 58) {
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
if (code < 65) {
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
if (code < 91) {
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
if (code < 97) {
|
|
204
|
-
return code === 95;
|
|
205
|
-
}
|
|
206
|
-
if (code < 123) {
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
_isIdStart(code) {
|
|
212
|
-
if (code < 65) {
|
|
213
|
-
return code === 36;
|
|
214
|
-
}
|
|
215
|
-
if (code < 91) {
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
if (code < 97) {
|
|
219
|
-
return code === 95;
|
|
220
|
-
}
|
|
221
|
-
if (code < 123) {
|
|
222
|
-
return true;
|
|
223
|
-
}
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
_id() {
|
|
227
|
-
var _a, _b;
|
|
228
|
-
let ret = "";
|
|
229
|
-
const lastC = this._col;
|
|
230
|
-
const lastP = this._position;
|
|
231
|
-
const line = this._line;
|
|
232
|
-
while (this._isId(this._currentChar)) {
|
|
233
|
-
ret += String.fromCharCode(this._currentChar);
|
|
234
|
-
this._advance();
|
|
235
|
-
}
|
|
236
|
-
const translatedId = this._language
|
|
237
|
-
? (_a = (this._language.keywords[ret])) !== null && _a !== void 0 ? _a : ret
|
|
238
|
-
: ret;
|
|
239
|
-
return (_b = Lexer.RESERVED[translatedId]) !== null && _b !== void 0 ? _b : new Token(TokenType.id, ret, line, lastC);
|
|
240
|
-
}
|
|
241
|
-
_isLineEnd(c) {
|
|
242
|
-
return c === 10 ||
|
|
243
|
-
c === 13 ||
|
|
244
|
-
['\n', '\r', '\u2028', '\u2029'].includes(String.fromCharCode(c));
|
|
245
|
-
}
|
|
246
|
-
_isWhiteSpace(c) {
|
|
247
|
-
return [' ', '\t'].includes(String.fromCharCode(c));
|
|
248
|
-
}
|
|
249
|
-
_isDigit(c) {
|
|
250
|
-
// tslint:disable-next-line:no-bitwise
|
|
251
|
-
return c > 0 && (c ^ 0x30) <= 9;
|
|
252
|
-
}
|
|
253
|
-
_skipWhiteSpace() {
|
|
254
|
-
while (this._isWhiteSpace(this._currentChar) === true) {
|
|
255
|
-
this._advance();
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
_number() {
|
|
259
|
-
let ret = "";
|
|
260
|
-
const lastC = this._col;
|
|
261
|
-
const lastP = this._position;
|
|
262
|
-
const line = this._line;
|
|
263
|
-
const first = String.fromCharCode(this._currentChar);
|
|
264
|
-
this._advance();
|
|
265
|
-
const bc = String.fromCharCode(this._currentChar);
|
|
266
|
-
let base = 10;
|
|
267
|
-
if (first === '0' && ['b', 'B', 'x', 'X', 'o', 'O'].includes(bc)) {
|
|
268
|
-
// look ahead to see that the number is tagged
|
|
269
|
-
this._advance();
|
|
270
|
-
switch (bc.toLowerCase()) {
|
|
271
|
-
case 'b':
|
|
272
|
-
base = 2;
|
|
273
|
-
break;
|
|
274
|
-
case "o":
|
|
275
|
-
base = 8;
|
|
276
|
-
break;
|
|
277
|
-
case "x":
|
|
278
|
-
base = 16;
|
|
279
|
-
break;
|
|
280
|
-
default:
|
|
281
|
-
base = 10;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
ret += first;
|
|
286
|
-
base = 10;
|
|
287
|
-
}
|
|
288
|
-
while (this._isDigit(this._currentChar) ||
|
|
289
|
-
(base === 16 &&
|
|
290
|
-
['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f']
|
|
291
|
-
.includes(String.fromCharCode(this._currentChar)))) {
|
|
292
|
-
ret += String.fromCharCode(this._currentChar);
|
|
293
|
-
this._advance();
|
|
294
|
-
}
|
|
295
|
-
if (String.fromCharCode(this._currentChar) === '.' && this._isDigit(this._pick()) === true) {
|
|
296
|
-
if (base !== 10) {
|
|
297
|
-
error(new Token(TokenType.id, bc, line, lastP));
|
|
298
|
-
}
|
|
299
|
-
// floating number
|
|
300
|
-
ret += String.fromCharCode(this._currentChar);
|
|
301
|
-
this._advance();
|
|
302
|
-
while (this._isDigit(this._currentChar)) {
|
|
303
|
-
ret += String.fromCharCode(this._currentChar);
|
|
304
|
-
this._advance();
|
|
305
|
-
}
|
|
306
|
-
return new Token(TokenType.numberConst, parseFloat(ret), line, lastC);
|
|
307
|
-
}
|
|
308
|
-
return new Token(TokenType.numberConst, parseInt(ret, base), line, lastC);
|
|
309
|
-
}
|
|
310
|
-
_literalString(startChar) {
|
|
311
|
-
let ret = "";
|
|
312
|
-
let lastChar = -1;
|
|
313
|
-
const lastP = this._position;
|
|
314
|
-
const lastC = this._col;
|
|
315
|
-
const lastL = this._line;
|
|
316
|
-
while (this._currentChar !== -1) {
|
|
317
|
-
const next = String.fromCharCode(this._pick());
|
|
318
|
-
if (this._currentChar === Chars.backslash) {
|
|
319
|
-
// scape char
|
|
320
|
-
if ([
|
|
321
|
-
startChar,
|
|
322
|
-
'\\',
|
|
323
|
-
'0',
|
|
324
|
-
'a',
|
|
325
|
-
'b',
|
|
326
|
-
'e',
|
|
327
|
-
'f',
|
|
328
|
-
'n',
|
|
329
|
-
'r',
|
|
330
|
-
't',
|
|
331
|
-
'u',
|
|
332
|
-
'U',
|
|
333
|
-
'v',
|
|
334
|
-
'x'
|
|
335
|
-
].includes(next)) {
|
|
336
|
-
lastChar = this._currentChar;
|
|
337
|
-
this._advance();
|
|
338
|
-
continue;
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
if (this._currentChar === startChar && lastChar !== Chars.backslash) {
|
|
342
|
-
// end
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
345
|
-
ret += String.fromCharCode(this._currentChar);
|
|
346
|
-
lastChar = this._currentChar;
|
|
347
|
-
this._advance();
|
|
348
|
-
}
|
|
349
|
-
return new Token(TokenType.stringConst, ret, lastL, lastC);
|
|
350
|
-
}
|
|
351
|
-
_skipLineComment() {
|
|
352
|
-
while (!this._isLineEnd(this._currentChar) === true && this._currentChar != -1) {
|
|
353
|
-
this._advance();
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
_skipComment() {
|
|
357
|
-
while (this._currentChar !== -1) {
|
|
358
|
-
if (this._currentChar === Chars.star && this._pick() === Chars.shebang) {
|
|
359
|
-
// end of block comment
|
|
360
|
-
this._advance();
|
|
361
|
-
this._advance();
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
364
|
-
this._advance();
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
// f=SUBMIT_FORM(xxx);
|
|
368
|
-
// r = CALL_API(API_ID, f);
|
|
369
|
-
// DISPLAY("MSG #r")
|
|
370
|
-
nextToken() {
|
|
371
|
-
const lastL = this._line;
|
|
372
|
-
const lastC = this._col;
|
|
373
|
-
const lastP = this._position;
|
|
374
|
-
while (this._currentChar !== -1) {
|
|
375
|
-
if (this._isLineEnd(this._currentChar)) {
|
|
376
|
-
this._line++;
|
|
377
|
-
this._col = 1;
|
|
378
|
-
this._advance();
|
|
379
|
-
return new Token(TokenType.eol, "\n", lastL, lastC);
|
|
380
|
-
}
|
|
381
|
-
if (this._isWhiteSpace(this._currentChar)) {
|
|
382
|
-
this._skipWhiteSpace();
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
if (this._currentChar == Chars.shebang) {
|
|
386
|
-
this._advance();
|
|
387
|
-
if (this._currentChar === Chars.star) {
|
|
388
|
-
// mutli block comment
|
|
389
|
-
this._advance();
|
|
390
|
-
this._skipComment();
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
this._skipLineComment();
|
|
394
|
-
}
|
|
395
|
-
continue;
|
|
396
|
-
}
|
|
397
|
-
if (this._isDigit(this._currentChar)) {
|
|
398
|
-
return this._number();
|
|
399
|
-
}
|
|
400
|
-
if (this._isIdStart(this._currentChar)) {
|
|
401
|
-
return this._id();
|
|
402
|
-
}
|
|
403
|
-
if (this._currentChar === Chars.equal) {
|
|
404
|
-
this._advance();
|
|
405
|
-
if (this._currentChar === Chars.equal) {
|
|
406
|
-
this._advance();
|
|
407
|
-
return new Token(TokenType.eqeq, "==", lastL, lastC);
|
|
408
|
-
}
|
|
409
|
-
return new Token(TokenType.equal, "=", lastL, lastC);
|
|
410
|
-
}
|
|
411
|
-
if (this._currentChar === Chars.great) {
|
|
412
|
-
this._advance();
|
|
413
|
-
if (this._currentChar === Chars.equal) {
|
|
414
|
-
this._advance();
|
|
415
|
-
return new Token(TokenType.greatEq, ">=", lastL, lastC);
|
|
416
|
-
}
|
|
417
|
-
return new Token(TokenType.great, ">", lastL, lastC);
|
|
418
|
-
}
|
|
419
|
-
if (this._currentChar === Chars.less) {
|
|
420
|
-
this._advance();
|
|
421
|
-
if (this._currentChar === Chars.equal) {
|
|
422
|
-
this._advance();
|
|
423
|
-
return new Token(TokenType.lessEq, "<=", lastL, lastC);
|
|
424
|
-
}
|
|
425
|
-
return new Token(TokenType.less, "<", lastL, lastC);
|
|
426
|
-
}
|
|
427
|
-
if (this._currentChar === Chars.semiColon) {
|
|
428
|
-
this._advance();
|
|
429
|
-
return new Token(TokenType.semi, ";", lastL, lastC);
|
|
430
|
-
}
|
|
431
|
-
if (this._currentChar === Chars.lparen) {
|
|
432
|
-
this._advance();
|
|
433
|
-
return new Token(TokenType.lparen, "(", lastL, lastC);
|
|
434
|
-
}
|
|
435
|
-
if (this._currentChar === Chars.rparen) {
|
|
436
|
-
this._advance();
|
|
437
|
-
return new Token(TokenType.rparen, ")", lastL, lastC);
|
|
438
|
-
}
|
|
439
|
-
if (this._currentChar === Chars.comma) {
|
|
440
|
-
this._advance();
|
|
441
|
-
return new Token(TokenType.comma, ",", lastL, lastC);
|
|
442
|
-
}
|
|
443
|
-
if (this._currentChar === Chars.lbrace) {
|
|
444
|
-
this._advance();
|
|
445
|
-
return new Token(TokenType.lbrace, "{", lastL, lastC);
|
|
446
|
-
}
|
|
447
|
-
if (this._currentChar === Chars.rbrace) {
|
|
448
|
-
this._advance();
|
|
449
|
-
return new Token(TokenType.rbrace, "}", lastL, lastC);
|
|
450
|
-
}
|
|
451
|
-
if (this._currentChar === Chars.lbracket) {
|
|
452
|
-
this._advance();
|
|
453
|
-
return new Token(TokenType.lbracket, "[", lastL, lastC);
|
|
454
|
-
}
|
|
455
|
-
if (this._currentChar === Chars.rbracket) {
|
|
456
|
-
this._advance();
|
|
457
|
-
return new Token(TokenType.rbracket, "]", lastL, lastC);
|
|
458
|
-
}
|
|
459
|
-
if (this._currentChar === Chars.plus) {
|
|
460
|
-
this._advance();
|
|
461
|
-
return new Token(TokenType.plus, "+", lastL, lastC);
|
|
462
|
-
}
|
|
463
|
-
if (this._currentChar === Chars.minus) {
|
|
464
|
-
this._advance();
|
|
465
|
-
return new Token(TokenType.minus, "-", lastL, lastC);
|
|
466
|
-
}
|
|
467
|
-
if (this._currentChar === Chars.slash) {
|
|
468
|
-
this._advance();
|
|
469
|
-
return new Token(TokenType.div, "/", lastL, lastC);
|
|
470
|
-
}
|
|
471
|
-
if (this._currentChar === Chars.star) {
|
|
472
|
-
this._advance();
|
|
473
|
-
return new Token(TokenType.mult, "*", lastL, lastC);
|
|
474
|
-
}
|
|
475
|
-
if (this._currentChar === Chars.percent) {
|
|
476
|
-
this._advance();
|
|
477
|
-
return new Token(TokenType.mod, "%", lastL, lastC);
|
|
478
|
-
}
|
|
479
|
-
if (this._currentChar === Chars.colon) {
|
|
480
|
-
this._advance();
|
|
481
|
-
return new Token(TokenType.colon, ":", lastL, lastC);
|
|
482
|
-
}
|
|
483
|
-
if (this._currentChar === Chars.not) {
|
|
484
|
-
this._advance();
|
|
485
|
-
if (this._currentChar === Chars.equal) {
|
|
486
|
-
this._advance();
|
|
487
|
-
return new Token(TokenType.notEq, "!=", lastL, lastC);
|
|
488
|
-
}
|
|
489
|
-
return new Token(TokenType.not, "!", lastL, lastC);
|
|
490
|
-
}
|
|
491
|
-
if (this._currentChar === Chars.and && this._pick() === Chars.and) {
|
|
492
|
-
this._advance();
|
|
493
|
-
this._advance();
|
|
494
|
-
return new Token(TokenType.and, "&&", lastL, lastC);
|
|
495
|
-
}
|
|
496
|
-
if (this._currentChar === Chars.pipe && this._pick() === Chars.pipe) {
|
|
497
|
-
this._advance();
|
|
498
|
-
this._advance();
|
|
499
|
-
return new Token(TokenType.or, '||', lastL, lastC);
|
|
500
|
-
}
|
|
501
|
-
if (this._currentChar === Chars.questionMark && this._pick() === Chars.questionMark) {
|
|
502
|
-
this._advance();
|
|
503
|
-
this._advance();
|
|
504
|
-
return new Token(TokenType.nullity, '??', lastL, lastC);
|
|
505
|
-
}
|
|
506
|
-
if (this._currentChar === Chars.quote || this._currentChar === Chars.squote) {
|
|
507
|
-
const startChar = this._currentChar;
|
|
508
|
-
this._advance();
|
|
509
|
-
const t = this._literalString(startChar);
|
|
510
|
-
this._advance();
|
|
511
|
-
return t;
|
|
512
|
-
}
|
|
513
|
-
return new Token(TokenType.invalid, String.fromCharCode(this._currentChar), lastL, lastC);
|
|
514
|
-
}
|
|
515
|
-
return new Token(TokenType.eof, "", lastL, lastC);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
Lexer._defaultLanguage = new LexerDictionary("en", {
|
|
519
|
-
"if": "if",
|
|
520
|
-
"else": "else",
|
|
521
|
-
"true": "true",
|
|
522
|
-
"false": "false",
|
|
523
|
-
"null": "null",
|
|
524
|
-
"while": "while",
|
|
525
|
-
"for": "for",
|
|
526
|
-
"with": "with",
|
|
527
|
-
"up": "up",
|
|
528
|
-
"down": "down",
|
|
529
|
-
"till": "till",
|
|
530
|
-
"in": "in",
|
|
531
|
-
"break": "break",
|
|
532
|
-
"continue": "continue",
|
|
533
|
-
"return": "return",
|
|
534
|
-
});
|
|
535
|
-
Lexer.languages = [
|
|
536
|
-
Lexer._defaultLanguage,
|
|
537
|
-
new LexerDictionary("fr", {
|
|
538
|
-
"si": "if",
|
|
539
|
-
"sinon": "else",
|
|
540
|
-
"vrai": "true",
|
|
541
|
-
"faux": "false",
|
|
542
|
-
"nul": "null",
|
|
543
|
-
"tanque": "while",
|
|
544
|
-
"pour": "for",
|
|
545
|
-
"avec": "with",
|
|
546
|
-
"mont": "up",
|
|
547
|
-
"desc": "down",
|
|
548
|
-
"jusqua": "till",
|
|
549
|
-
"dans": "in",
|
|
550
|
-
"couper": "break",
|
|
551
|
-
"continuer": "continue",
|
|
552
|
-
"returner": "return",
|
|
553
|
-
}),
|
|
554
|
-
new LexerDictionary("bm", {
|
|
555
|
-
"nii": "if",
|
|
556
|
-
"note": "else",
|
|
557
|
-
"tien": "true",
|
|
558
|
-
"galon": "false",
|
|
559
|
-
"gansan": "null",
|
|
560
|
-
"foo": "while",
|
|
561
|
-
"seginka": "for",
|
|
562
|
-
"niin": "with",
|
|
563
|
-
"kay": "up",
|
|
564
|
-
"kaj": "down",
|
|
565
|
-
"kata": "till",
|
|
566
|
-
"kono": "in",
|
|
567
|
-
"tike": "break",
|
|
568
|
-
"ipan": "continue",
|
|
569
|
-
"segin": "return",
|
|
570
|
-
}),
|
|
571
|
-
];
|
|
572
|
-
Lexer.RESERVED = {
|
|
573
|
-
"if": Token.from(TokenType.IF, "if"),
|
|
574
|
-
"else": Token.from(TokenType.ELSE, "else"),
|
|
575
|
-
"true": Token.from(TokenType.TRUE, true),
|
|
576
|
-
"false": Token.from(TokenType.FALSE, false),
|
|
577
|
-
"null": Token.from(TokenType.NULL, null),
|
|
578
|
-
"for": Token.from(TokenType.FOR_LOOP, "for"),
|
|
579
|
-
"while": Token.from(TokenType.WHILE_TILL, "while"),
|
|
580
|
-
"with": Token.from(TokenType.with, "with"),
|
|
581
|
-
"up": Token.from(TokenType.up, "up"),
|
|
582
|
-
"down": Token.from(TokenType.down, "down"),
|
|
583
|
-
"till": Token.from(TokenType.TILL, "till"),
|
|
584
|
-
"in": Token.from(TokenType.in, "in"),
|
|
585
|
-
"break": Token.from(TokenType.BREAK, "break"),
|
|
586
|
-
"continue": Token.from(TokenType.CONTINUE, "continue"),
|
|
587
|
-
"return": Token.from(TokenType.RETURN, "return"),
|
|
588
|
-
};
|
|
589
|
-
/**
|
|
590
|
-
* Parser
|
|
591
|
-
*/
|
|
592
|
-
class AST {
|
|
593
|
-
constructor(line, col) {
|
|
594
|
-
this.line = line;
|
|
595
|
-
this.col = col;
|
|
596
|
-
}
|
|
597
|
-
dump() {
|
|
598
|
-
return this.toString();
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
class RootAST extends AST {
|
|
602
|
-
constructor(body, name, source) {
|
|
603
|
-
super(1, 1);
|
|
604
|
-
this.body = body;
|
|
605
|
-
this.name = name;
|
|
606
|
-
this.source = source;
|
|
607
|
-
}
|
|
608
|
-
dump() {
|
|
609
|
-
let builder = `Module ${this.name} Start {`;
|
|
610
|
-
for (const it of this.body) {
|
|
611
|
-
builder += `${it.dump()}\n`;
|
|
612
|
-
}
|
|
613
|
-
builder += "}";
|
|
614
|
-
return builder;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
class BlockStatementAST extends AST {
|
|
618
|
-
constructor(body, token) {
|
|
619
|
-
super(token.line, token.col);
|
|
620
|
-
this.body = body;
|
|
621
|
-
}
|
|
622
|
-
toString() {
|
|
623
|
-
return `{\n${this.body.map((e) => e.toString()).join("\n")}}`;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
class IdentifierAST extends AST {
|
|
627
|
-
constructor(token) {
|
|
628
|
-
super(token.line, token.col);
|
|
629
|
-
this.value = token.value.toString();
|
|
630
|
-
}
|
|
631
|
-
toString() {
|
|
632
|
-
return this.value;
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
class LiteralAST extends AST {
|
|
636
|
-
constructor(token, raw) {
|
|
637
|
-
super(token.line, token.col);
|
|
638
|
-
this.value = token.value;
|
|
639
|
-
this.raw = raw;
|
|
640
|
-
}
|
|
641
|
-
toString() {
|
|
642
|
-
return this.value.toString();
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
class AssignmentExpressionAST extends AST {
|
|
646
|
-
constructor(identifier, init) {
|
|
647
|
-
super(identifier.line, identifier.col);
|
|
648
|
-
this.identifier = identifier;
|
|
649
|
-
this.init = init;
|
|
650
|
-
}
|
|
651
|
-
toString() {
|
|
652
|
-
return `${this.identifier} = ${this.init}`;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
class ExpressionStatementAST extends AST {
|
|
656
|
-
constructor(expression) {
|
|
657
|
-
super(expression.line, expression.col);
|
|
658
|
-
this.expression = expression;
|
|
659
|
-
}
|
|
660
|
-
toString() {
|
|
661
|
-
return this.expression.toString();
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
class CallExpressionAST extends AST {
|
|
665
|
-
constructor(callee, ags) {
|
|
666
|
-
super(callee.line, callee.col);
|
|
667
|
-
this.callee = callee;
|
|
668
|
-
this.arguments = ags;
|
|
669
|
-
}
|
|
670
|
-
toString() {
|
|
671
|
-
return `${this.callee.toString()}(...${this.arguments.length})`;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
class BinaryExpressionAST extends AST {
|
|
675
|
-
constructor(left, operation, right) {
|
|
676
|
-
super(left.line, left.col);
|
|
677
|
-
this.left = left;
|
|
678
|
-
this.operation = operation;
|
|
679
|
-
this.right = right;
|
|
680
|
-
}
|
|
681
|
-
toString() {
|
|
682
|
-
return `${this.left} ${this.operation} ${this.right}`;
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
class UnaryExpressionAST extends AST {
|
|
686
|
-
constructor(operation, argument) {
|
|
687
|
-
super(operation.line, operation.col);
|
|
688
|
-
this.operation = operation, this.argument = argument;
|
|
689
|
-
}
|
|
690
|
-
toString() {
|
|
691
|
-
return `${this.operation} ${this.argument}`;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
class IfStatementAST extends AST {
|
|
695
|
-
constructor(test, consequent, alternate) {
|
|
696
|
-
super(test.line, test.col);
|
|
697
|
-
this.test = test;
|
|
698
|
-
this.consequent = consequent;
|
|
699
|
-
this.alternate = alternate;
|
|
700
|
-
}
|
|
701
|
-
toString() {
|
|
702
|
-
return `if ${this.test} ${this.consequent} ${this.alternate ? `else ${this.alternate} ` : ''}`;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
class LogicalExpressionAST extends AST {
|
|
706
|
-
constructor(left, operator, right) {
|
|
707
|
-
super(left.line, left.col);
|
|
708
|
-
this.left = left;
|
|
709
|
-
this.operator = operator;
|
|
710
|
-
this.right = right;
|
|
711
|
-
}
|
|
712
|
-
toString() {
|
|
713
|
-
return `${this.left} ${this.operator.value} ${this.right}`;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
class IndexAccessorAST extends AST {
|
|
717
|
-
constructor(owner, key, computed = false) {
|
|
718
|
-
super(owner.line, owner.col);
|
|
719
|
-
this.computed = false;
|
|
720
|
-
this.owner = owner;
|
|
721
|
-
this.key = key;
|
|
722
|
-
this.computed = computed;
|
|
723
|
-
}
|
|
724
|
-
toString() {
|
|
725
|
-
return `${this.owner}[${this.key}]`;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
class ObjectExpression extends AST {
|
|
729
|
-
constructor(props, startToken, endToken) {
|
|
730
|
-
super(startToken === null || startToken === void 0 ? void 0 : startToken.line, startToken === null || startToken === void 0 ? void 0 : startToken.col);
|
|
731
|
-
this.properties = props;
|
|
732
|
-
}
|
|
733
|
-
toString() {
|
|
734
|
-
return "{...}";
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
class ArrayExpression extends AST {
|
|
738
|
-
constructor(props, start, end) {
|
|
739
|
-
super(start === null || start === void 0 ? void 0 : start.line, start === null || start === void 0 ? void 0 : start.col);
|
|
740
|
-
this.elements = props;
|
|
741
|
-
}
|
|
742
|
-
toString() {
|
|
743
|
-
return "[...]";
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
class ObjectProperty extends AST {
|
|
747
|
-
constructor(key, value) {
|
|
748
|
-
super(key.line, key.col);
|
|
749
|
-
this.value = value;
|
|
750
|
-
this.key = key;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
class WhileLoopStatement extends AST {
|
|
754
|
-
constructor(test, body, startToken, endToken, retain = false) {
|
|
755
|
-
super(startToken === null || startToken === void 0 ? void 0 : startToken.line, startToken === null || startToken === void 0 ? void 0 : startToken.col);
|
|
756
|
-
this.retain = false;
|
|
757
|
-
this.test = test;
|
|
758
|
-
this.body = body;
|
|
759
|
-
this.retain = retain;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
class ForLoopStatement extends AST {
|
|
763
|
-
constructor(init, test, update, direction, body, startToken, endToken, retain = false) {
|
|
764
|
-
super(startToken === null || startToken === void 0 ? void 0 : startToken.line, startToken === null || startToken === void 0 ? void 0 : startToken.col);
|
|
765
|
-
this.init = init;
|
|
766
|
-
this.test = test;
|
|
767
|
-
this.update = update;
|
|
768
|
-
this.direction = direction;
|
|
769
|
-
this.body = body;
|
|
770
|
-
this.retain = retain;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
class ForOfStatement extends AST {
|
|
774
|
-
constructor(identifier, collection, body, startToken, endToken, retain = false) {
|
|
775
|
-
super(startToken === null || startToken === void 0 ? void 0 : startToken.line, startToken === null || startToken === void 0 ? void 0 : startToken.col);
|
|
776
|
-
this.identifier = identifier;
|
|
777
|
-
this.collection = collection;
|
|
778
|
-
this.body = body;
|
|
779
|
-
this.retain = retain;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
class TupleExpression extends AST {
|
|
783
|
-
constructor(first, second) {
|
|
784
|
-
super(first.line, first.col);
|
|
785
|
-
this.first = first;
|
|
786
|
-
this.second = second;
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
class BreakAST extends AST {
|
|
790
|
-
constructor(line, col) {
|
|
791
|
-
super(line, col);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
class ReturnAST extends AST {
|
|
795
|
-
constructor(value, line, col) {
|
|
796
|
-
super(line, col);
|
|
797
|
-
this.value = value;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
class ContinueAST extends AST {
|
|
801
|
-
constructor(line, col) {
|
|
802
|
-
super(line, col);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
class Parser {
|
|
806
|
-
constructor(lexer) {
|
|
807
|
-
this.currentToken = lexer.nextToken();
|
|
808
|
-
this.lexer = lexer;
|
|
809
|
-
}
|
|
810
|
-
_eat(type) {
|
|
811
|
-
var _a;
|
|
812
|
-
if (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === type) {
|
|
813
|
-
this.currentToken = this.lexer.nextToken();
|
|
814
|
-
}
|
|
815
|
-
else {
|
|
816
|
-
error(this.currentToken, type);
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
_eatEOL() {
|
|
820
|
-
var _a;
|
|
821
|
-
while (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === TokenType.eol) {
|
|
822
|
-
this._eat(TokenType.eol);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
_eatSemiOrEOL() {
|
|
826
|
-
var _a, _b;
|
|
827
|
-
while (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === TokenType.eol ||
|
|
828
|
-
((_b = this.currentToken) === null || _b === void 0 ? void 0 : _b.type) === TokenType.semi) {
|
|
829
|
-
this._eat(this.currentToken.type);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
_eatSemi() {
|
|
833
|
-
var _a;
|
|
834
|
-
while (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === TokenType.semi) {
|
|
835
|
-
this._eat(TokenType.semi);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
_variable() {
|
|
839
|
-
const node = new IdentifierAST(this.currentToken);
|
|
840
|
-
this._eat(TokenType.id);
|
|
841
|
-
return node;
|
|
842
|
-
}
|
|
843
|
-
_return() {
|
|
844
|
-
const token = this.currentToken;
|
|
845
|
-
let value = undefined;
|
|
846
|
-
if (!this._expect(TokenType.eol) && !this._expect(TokenType.semi)) {
|
|
847
|
-
value = this._expression();
|
|
848
|
-
}
|
|
849
|
-
return new ReturnAST(value, token === null || token === void 0 ? void 0 : token.line, token === null || token === void 0 ? void 0 : token.col);
|
|
850
|
-
}
|
|
851
|
-
_factor() {
|
|
852
|
-
const token = this.currentToken;
|
|
853
|
-
switch (token.type) {
|
|
854
|
-
case TokenType.plus:
|
|
855
|
-
case TokenType.minus:
|
|
856
|
-
case TokenType.not:
|
|
857
|
-
this._eat(this.currentToken.type);
|
|
858
|
-
return new UnaryExpressionAST(token, this._term());
|
|
859
|
-
case TokenType.numberConst:
|
|
860
|
-
this._eat(TokenType.numberConst);
|
|
861
|
-
return new LiteralAST(token, token.value.toString());
|
|
862
|
-
case TokenType.stringConst:
|
|
863
|
-
this._eat(TokenType.stringConst);
|
|
864
|
-
return new LiteralAST(token, token.value.toString());
|
|
865
|
-
case TokenType.lparen:
|
|
866
|
-
this._eat(TokenType.lparen);
|
|
867
|
-
const node = this._expression();
|
|
868
|
-
this._eat(TokenType.rparen);
|
|
869
|
-
return node;
|
|
870
|
-
case TokenType.TRUE:
|
|
871
|
-
case TokenType.FALSE:
|
|
872
|
-
this._eat(this.currentToken.type);
|
|
873
|
-
return new LiteralAST(token, token.value.toString());
|
|
874
|
-
case TokenType.NULL:
|
|
875
|
-
this._eat(TokenType.NULL);
|
|
876
|
-
return new LiteralAST(token, "null");
|
|
877
|
-
case TokenType.lbracket:
|
|
878
|
-
// literal array expression
|
|
879
|
-
return this._arrayExpression();
|
|
880
|
-
case TokenType.lbrace:
|
|
881
|
-
return this._objectExpression();
|
|
882
|
-
case TokenType.IF:
|
|
883
|
-
return this._ifStatement();
|
|
884
|
-
default:
|
|
885
|
-
return this._variable();
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
_term() {
|
|
889
|
-
let node = this._factor();
|
|
890
|
-
node = this._tryParsingFunctionCall(node);
|
|
891
|
-
node = this._tryParsingMemberExpression(node);
|
|
892
|
-
return node;
|
|
893
|
-
}
|
|
894
|
-
_expression() {
|
|
895
|
-
let node = this._term();
|
|
896
|
-
node = this._tryBinaryExpression(0, node);
|
|
897
|
-
while ([TokenType.and, TokenType.or, TokenType.nullity].includes(this.currentToken.type)) {
|
|
898
|
-
const token = this.currentToken;
|
|
899
|
-
this._eat(token.type);
|
|
900
|
-
node = new LogicalExpressionAST(node, token, this._expression());
|
|
901
|
-
}
|
|
902
|
-
if (this._expect(TokenType.equal)) {
|
|
903
|
-
if (node instanceof IdentifierAST || node instanceof IndexAccessorAST) {
|
|
904
|
-
const token = this.currentToken;
|
|
905
|
-
this._eat(TokenType.equal);
|
|
906
|
-
node = new AssignmentExpressionAST(node, this._expression());
|
|
907
|
-
}
|
|
908
|
-
else {
|
|
909
|
-
throw new Error("Unexpected token");
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
return node;
|
|
913
|
-
}
|
|
914
|
-
_objectProperty() {
|
|
915
|
-
var _a;
|
|
916
|
-
let key;
|
|
917
|
-
switch ((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) {
|
|
918
|
-
case TokenType.stringConst:
|
|
919
|
-
{
|
|
920
|
-
key = new LiteralAST(this.currentToken, this.currentToken.value);
|
|
921
|
-
this._eat(TokenType.stringConst);
|
|
922
|
-
break;
|
|
923
|
-
}
|
|
924
|
-
case TokenType.lbracket:
|
|
925
|
-
{
|
|
926
|
-
this._eat(TokenType.lbracket);
|
|
927
|
-
var expr = this._expression();
|
|
928
|
-
this._eat(TokenType.rbracket);
|
|
929
|
-
key = expr;
|
|
930
|
-
break;
|
|
931
|
-
}
|
|
932
|
-
case TokenType.id:
|
|
933
|
-
{
|
|
934
|
-
const id = this._variable();
|
|
935
|
-
key = new LiteralAST(new Token(TokenType.id, id.value, id.line, id.col), id.value);
|
|
936
|
-
break;
|
|
937
|
-
}
|
|
938
|
-
default:
|
|
939
|
-
throw `Unexpected token ${this.currentToken}`;
|
|
940
|
-
}
|
|
941
|
-
this._eat(TokenType.colon);
|
|
942
|
-
var value = this._expression();
|
|
943
|
-
return new ObjectProperty(key, value);
|
|
944
|
-
}
|
|
945
|
-
_property() {
|
|
946
|
-
return this._objectProperty();
|
|
947
|
-
}
|
|
948
|
-
_objectProperties() {
|
|
949
|
-
var _a, _b;
|
|
950
|
-
const properties = [];
|
|
951
|
-
if (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) != TokenType.rbrace) {
|
|
952
|
-
this._eatEOL();
|
|
953
|
-
properties.push(this._property());
|
|
954
|
-
this._eatEOL();
|
|
955
|
-
}
|
|
956
|
-
while (((_b = this.currentToken) === null || _b === void 0 ? void 0 : _b.type) === TokenType.comma) {
|
|
957
|
-
this._eat(TokenType.comma);
|
|
958
|
-
this._eatEOL();
|
|
959
|
-
if (this._expect(TokenType.rbrace)) {
|
|
960
|
-
break;
|
|
961
|
-
}
|
|
962
|
-
properties.push(this._property());
|
|
963
|
-
this._eatEOL();
|
|
964
|
-
}
|
|
965
|
-
return properties;
|
|
966
|
-
}
|
|
967
|
-
_objectExpression(braceToken) {
|
|
968
|
-
var token = braceToken !== null && braceToken !== void 0 ? braceToken : this.currentToken;
|
|
969
|
-
if (!braceToken)
|
|
970
|
-
this._eat(TokenType.lbrace);
|
|
971
|
-
var properties = this._objectProperties();
|
|
972
|
-
this._eat(TokenType.rbrace);
|
|
973
|
-
return new ObjectExpression(properties, token, this.currentToken);
|
|
974
|
-
}
|
|
975
|
-
_arrayExpression() {
|
|
976
|
-
this._eat(TokenType.lbracket);
|
|
977
|
-
const elements = this._expect(TokenType.rbracket) ? [] : this._expressionsList();
|
|
978
|
-
this._eat(TokenType.rbracket);
|
|
979
|
-
var startNode = elements.length !== 0 ? elements[0] : undefined;
|
|
980
|
-
var lastNode = elements.length !== 0 ? elements[elements.length - 1] : undefined;
|
|
981
|
-
return new ArrayExpression(elements, startNode, lastNode);
|
|
982
|
-
}
|
|
983
|
-
_tryParsingMemberExpression(n) {
|
|
984
|
-
let node = n;
|
|
985
|
-
while (this.currentToken.type === TokenType.lbracket) {
|
|
986
|
-
this._eat(TokenType.lbracket);
|
|
987
|
-
const key = this._expression();
|
|
988
|
-
node = new IndexAccessorAST(node, key);
|
|
989
|
-
this._eat(TokenType.rbracket);
|
|
990
|
-
}
|
|
991
|
-
return node;
|
|
992
|
-
}
|
|
993
|
-
_tryBinaryExpression(prec, left) {
|
|
994
|
-
let node = left;
|
|
995
|
-
while (true) {
|
|
996
|
-
const currentPrec = Parser._binopPrecdences[this.currentToken.type] || -1;
|
|
997
|
-
if (currentPrec < prec)
|
|
998
|
-
return node;
|
|
999
|
-
const operator = this.currentToken;
|
|
1000
|
-
this._eat(operator.type);
|
|
1001
|
-
let right = this._term();
|
|
1002
|
-
const nextPrec = Parser._binopPrecdences[this.currentToken.type] || -1;
|
|
1003
|
-
if (currentPrec < nextPrec) {
|
|
1004
|
-
const tmp = this._tryBinaryExpression(currentPrec + 1, right);
|
|
1005
|
-
if (tmp === node)
|
|
1006
|
-
return tmp;
|
|
1007
|
-
right = tmp;
|
|
1008
|
-
}
|
|
1009
|
-
node = new BinaryExpressionAST(node, operator, right);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
_expressionsList() {
|
|
1013
|
-
var _a;
|
|
1014
|
-
this._eatEOL();
|
|
1015
|
-
// if (expect(Lexer.TokenType.RPAREN)) return emptyList()
|
|
1016
|
-
let expr = this._expression();
|
|
1017
|
-
this._eatEOL();
|
|
1018
|
-
const result = [expr];
|
|
1019
|
-
while (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === TokenType.comma) {
|
|
1020
|
-
this._eat(TokenType.comma);
|
|
1021
|
-
this._eatEOL();
|
|
1022
|
-
if (this._expect(TokenType.rbracket)) {
|
|
1023
|
-
break;
|
|
1024
|
-
}
|
|
1025
|
-
expr = this._expression();
|
|
1026
|
-
result.push(expr);
|
|
1027
|
-
this._eatEOL();
|
|
1028
|
-
}
|
|
1029
|
-
return result;
|
|
1030
|
-
}
|
|
1031
|
-
_callExpression(node) {
|
|
1032
|
-
this._eat(TokenType.lparen);
|
|
1033
|
-
let args = [];
|
|
1034
|
-
if (!this._expect(TokenType.rparen)) {
|
|
1035
|
-
args = this._expressionsList();
|
|
1036
|
-
}
|
|
1037
|
-
this._eat(TokenType.rparen);
|
|
1038
|
-
if (!(node instanceof IdentifierAST)) {
|
|
1039
|
-
error(this.currentToken);
|
|
1040
|
-
}
|
|
1041
|
-
return new CallExpressionAST(node, args);
|
|
1042
|
-
}
|
|
1043
|
-
_tryParsingFunctionCall(n) {
|
|
1044
|
-
let node = n;
|
|
1045
|
-
while (this.currentToken.type === TokenType.lparen) {
|
|
1046
|
-
// probable function call
|
|
1047
|
-
node = this._callExpression(node);
|
|
1048
|
-
}
|
|
1049
|
-
return node;
|
|
1050
|
-
}
|
|
1051
|
-
_statementExpression() {
|
|
1052
|
-
const node = this._expression();
|
|
1053
|
-
if (![TokenType.semi, TokenType.eol, TokenType.eof]
|
|
1054
|
-
.includes(this.currentToken.type)) {
|
|
1055
|
-
error(this.currentToken);
|
|
1056
|
-
}
|
|
1057
|
-
return node;
|
|
1058
|
-
}
|
|
1059
|
-
_blockStatement(ignoreFirstBrace = false) {
|
|
1060
|
-
var _a;
|
|
1061
|
-
if (!ignoreFirstBrace)
|
|
1062
|
-
this._eat(TokenType.lbrace);
|
|
1063
|
-
this._eatEOL();
|
|
1064
|
-
if (this._expect(TokenType.rbrace)) {
|
|
1065
|
-
this._eat(TokenType.rbrace);
|
|
1066
|
-
return new BlockStatementAST([], this.currentToken);
|
|
1067
|
-
}
|
|
1068
|
-
// const body = _statements();
|
|
1069
|
-
const body = [this._statement()];
|
|
1070
|
-
while (true) {
|
|
1071
|
-
this._eatSemiOrEOL();
|
|
1072
|
-
if (this.currentToken.type === TokenType.rbrace || this.currentToken.type === TokenType.eof) {
|
|
1073
|
-
// _eat(this.currentToken!.type);
|
|
1074
|
-
break;
|
|
1075
|
-
}
|
|
1076
|
-
body.push(this._statement());
|
|
1077
|
-
if (this._expect(TokenType.rbrace))
|
|
1078
|
-
break;
|
|
1079
|
-
if (this.currentToken.type !== TokenType.eol &&
|
|
1080
|
-
this.currentToken.type !== TokenType.semi &&
|
|
1081
|
-
this.currentToken.type !== TokenType.eof) {
|
|
1082
|
-
error(this.currentToken);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
this._eat(TokenType.rbrace);
|
|
1086
|
-
if (((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === TokenType.rbrace) {
|
|
1087
|
-
// endBlock
|
|
1088
|
-
this._eat(TokenType.rbrace);
|
|
1089
|
-
}
|
|
1090
|
-
return new BlockStatementAST(body, this.currentToken);
|
|
1091
|
-
}
|
|
1092
|
-
_ifStatement() {
|
|
1093
|
-
this._eat(TokenType.IF);
|
|
1094
|
-
const withPar = this.currentToken.type === TokenType.lparen;
|
|
1095
|
-
if (withPar) {
|
|
1096
|
-
this._eat(TokenType.lparen);
|
|
1097
|
-
}
|
|
1098
|
-
const test = this._expression();
|
|
1099
|
-
if (withPar) {
|
|
1100
|
-
this._eat(TokenType.rparen);
|
|
1101
|
-
}
|
|
1102
|
-
let consequent;
|
|
1103
|
-
if (this.currentToken.type === TokenType.lbrace) {
|
|
1104
|
-
consequent = this._blockStatement();
|
|
1105
|
-
}
|
|
1106
|
-
else {
|
|
1107
|
-
consequent = this._expression();
|
|
1108
|
-
}
|
|
1109
|
-
// this._eatSemiOrEOL();
|
|
1110
|
-
let alternate;
|
|
1111
|
-
if (this.currentToken.type === TokenType.ELSE) {
|
|
1112
|
-
this._eat(TokenType.ELSE);
|
|
1113
|
-
switch (this.currentToken.type) {
|
|
1114
|
-
case TokenType.IF:
|
|
1115
|
-
alternate = this._ifStatement();
|
|
1116
|
-
break;
|
|
1117
|
-
case TokenType.lbrace:
|
|
1118
|
-
alternate = this._blockStatement();
|
|
1119
|
-
break;
|
|
1120
|
-
default:
|
|
1121
|
-
alternate = this._expression();
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
return new IfStatementAST(test, consequent, alternate);
|
|
1125
|
-
}
|
|
1126
|
-
_whileLoop() {
|
|
1127
|
-
const token = this.currentToken;
|
|
1128
|
-
this._eat(TokenType.WHILE_TILL);
|
|
1129
|
-
const test = this._expression();
|
|
1130
|
-
const body = this.currentToken.type === TokenType.lbrace ? this._blockStatement() : this._expression();
|
|
1131
|
-
return new WhileLoopStatement(test, body, token, this.currentToken);
|
|
1132
|
-
}
|
|
1133
|
-
_forOfIdentifier() {
|
|
1134
|
-
switch (this.currentToken.type) {
|
|
1135
|
-
case TokenType.lparen: {
|
|
1136
|
-
// probable tuple
|
|
1137
|
-
this._eat(TokenType.lparen);
|
|
1138
|
-
const first = this._variable();
|
|
1139
|
-
this._eat(TokenType.comma);
|
|
1140
|
-
const second = this._variable();
|
|
1141
|
-
this._eat(TokenType.rparen);
|
|
1142
|
-
return new TupleExpression(first, second);
|
|
1143
|
-
}
|
|
1144
|
-
// TokenType.LBRACE -> objectPattern()
|
|
1145
|
-
// TokenType.LBRACKET -> arrayPattern()
|
|
1146
|
-
default:
|
|
1147
|
-
return this._variable();
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
/**
|
|
1151
|
-
* # ForLoopStatement with step
|
|
1152
|
-
* (seginka|for) a=0 (foo|to) 10 (kay|kaj) niin 2 { # for a = 0; a<10; a+=2
|
|
1153
|
-
*
|
|
1154
|
-
* }
|
|
1155
|
-
* (seginka|for) mali kono a
|
|
1156
|
-
*/
|
|
1157
|
-
_forLoop() {
|
|
1158
|
-
const startToken = this.currentToken;
|
|
1159
|
-
this._eat(TokenType.FOR_LOOP);
|
|
1160
|
-
let forOf = [TokenType.lparen].includes(this.currentToken.type);
|
|
1161
|
-
let node;
|
|
1162
|
-
if (forOf) {
|
|
1163
|
-
node = this._forOfIdentifier();
|
|
1164
|
-
}
|
|
1165
|
-
else {
|
|
1166
|
-
const expr = this._expression();
|
|
1167
|
-
if (!(expr instanceof AssignmentExpressionAST)) {
|
|
1168
|
-
forOf = true;
|
|
1169
|
-
}
|
|
1170
|
-
node = expr;
|
|
1171
|
-
}
|
|
1172
|
-
if (!forOf && node instanceof AssignmentExpressionAST) {
|
|
1173
|
-
// normal for
|
|
1174
|
-
this._eat(TokenType.TILL);
|
|
1175
|
-
const test = this._expression();
|
|
1176
|
-
let direction;
|
|
1177
|
-
if (this.currentToken.type === TokenType.up || this.currentToken.type === TokenType.down) {
|
|
1178
|
-
const t = this.currentToken;
|
|
1179
|
-
this._eat(t.type);
|
|
1180
|
-
direction = t;
|
|
1181
|
-
}
|
|
1182
|
-
else {
|
|
1183
|
-
direction = new Token(TokenType.up, "up");
|
|
1184
|
-
}
|
|
1185
|
-
let update;
|
|
1186
|
-
if (this._expect(TokenType.with)) {
|
|
1187
|
-
this._eat(TokenType.with);
|
|
1188
|
-
const expr = this._expression();
|
|
1189
|
-
update = expr;
|
|
1190
|
-
}
|
|
1191
|
-
else {
|
|
1192
|
-
update = new LiteralAST(new Token(TokenType.numberConst, 1, this.currentToken.line, this.currentToken.col), "1");
|
|
1193
|
-
}
|
|
1194
|
-
const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
|
|
1195
|
-
node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken);
|
|
1196
|
-
}
|
|
1197
|
-
else if (forOf) {
|
|
1198
|
-
this._eat(TokenType.in);
|
|
1199
|
-
const collection = this._expression();
|
|
1200
|
-
const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
|
|
1201
|
-
node = new ForOfStatement(node, collection, body, startToken, this.currentToken);
|
|
1202
|
-
}
|
|
1203
|
-
else {
|
|
1204
|
-
error(this.currentToken);
|
|
1205
|
-
}
|
|
1206
|
-
return node;
|
|
1207
|
-
}
|
|
1208
|
-
_statement() {
|
|
1209
|
-
var _a, _b, _c, _d;
|
|
1210
|
-
switch (this.currentToken.type) {
|
|
1211
|
-
case TokenType.BREAK:
|
|
1212
|
-
this._eat(TokenType.BREAK);
|
|
1213
|
-
return new BreakAST((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.line, (_b = this.currentToken) === null || _b === void 0 ? void 0 : _b.col);
|
|
1214
|
-
case TokenType.CONTINUE:
|
|
1215
|
-
this._eat(TokenType.CONTINUE);
|
|
1216
|
-
return new ContinueAST((_c = this.currentToken) === null || _c === void 0 ? void 0 : _c.line, (_d = this.currentToken) === null || _d === void 0 ? void 0 : _d.col);
|
|
1217
|
-
case TokenType.RETURN:
|
|
1218
|
-
this._eat(TokenType.RETURN);
|
|
1219
|
-
return this._return();
|
|
1220
|
-
case TokenType.semi:
|
|
1221
|
-
this._eatSemi();
|
|
1222
|
-
return this._statement();
|
|
1223
|
-
case TokenType.eol:
|
|
1224
|
-
this._eatEOL();
|
|
1225
|
-
return this._statement();
|
|
1226
|
-
// case TokenType.IF:
|
|
1227
|
-
// return this._ifStatement();
|
|
1228
|
-
case TokenType.WHILE_TILL:
|
|
1229
|
-
return this._whileLoop();
|
|
1230
|
-
case TokenType.FOR_LOOP:
|
|
1231
|
-
return this._forLoop();
|
|
1232
|
-
default:
|
|
1233
|
-
return this._statementExpression();
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
_expect(type) {
|
|
1237
|
-
var _a;
|
|
1238
|
-
return ((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.type) === type;
|
|
1239
|
-
}
|
|
1240
|
-
_definition() {
|
|
1241
|
-
this._eatSemiOrEOL();
|
|
1242
|
-
if (this._expect(TokenType.eof)) {
|
|
1243
|
-
return [];
|
|
1244
|
-
}
|
|
1245
|
-
const results = [this._statement()];
|
|
1246
|
-
while (true) {
|
|
1247
|
-
this._eatSemiOrEOL();
|
|
1248
|
-
if (this.currentToken.type === TokenType.eof) {
|
|
1249
|
-
this._eat(TokenType.eof);
|
|
1250
|
-
break;
|
|
1251
|
-
}
|
|
1252
|
-
if (this.currentToken.type === TokenType.lbrace) {
|
|
1253
|
-
results.push(this._blockStatement());
|
|
1254
|
-
}
|
|
1255
|
-
else {
|
|
1256
|
-
results.push(this._statement());
|
|
1257
|
-
}
|
|
1258
|
-
// if (this.currentToken!.type !== TokenType.eol &&
|
|
1259
|
-
// this.currentToken!.type !== TokenType.semi &&
|
|
1260
|
-
// this.currentToken!.type !== TokenType.eof) {
|
|
1261
|
-
// error(this.currentToken!);
|
|
1262
|
-
// }
|
|
1263
|
-
}
|
|
1264
|
-
return results;
|
|
1265
|
-
}
|
|
1266
|
-
_root() {
|
|
1267
|
-
const source = this.lexer.source;
|
|
1268
|
-
const name = "<module>";
|
|
1269
|
-
const list = this._definition();
|
|
1270
|
-
return new RootAST(list, name, source);
|
|
1271
|
-
}
|
|
1272
|
-
parse() {
|
|
1273
|
-
return this._root();
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
Parser._binopPrecdences = {
|
|
1277
|
-
[TokenType.eqeq]: 10,
|
|
1278
|
-
[TokenType.notEq]: 10,
|
|
1279
|
-
[TokenType.great]: 10,
|
|
1280
|
-
[TokenType.greatEq]: 10,
|
|
1281
|
-
[TokenType.less]: 10,
|
|
1282
|
-
[TokenType.lessEq]: 10,
|
|
1283
|
-
[TokenType.plus]: 20,
|
|
1284
|
-
[TokenType.minus]: 20,
|
|
1285
|
-
[TokenType.mult]: 40,
|
|
1286
|
-
[TokenType.div]: 40,
|
|
1287
|
-
[TokenType.mod]: 40,
|
|
1288
|
-
};
|
|
1289
|
-
class LoopControl {
|
|
1290
|
-
}
|
|
1291
|
-
class BreakBranch extends LoopControl {
|
|
1292
|
-
}
|
|
1293
|
-
class ContinueBranch extends LoopControl {
|
|
1294
|
-
}
|
|
1295
|
-
class ReturnBranch {
|
|
1296
|
-
constructor(value) {
|
|
1297
|
-
this.value = value;
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
;
|
|
1301
|
-
// AST Wallker
|
|
1302
|
-
class ANodeVisitor {
|
|
1303
|
-
constructor() {
|
|
1304
|
-
this._nodesVisitors = {};
|
|
1305
|
-
}
|
|
1306
|
-
registerVisitor(type, visitor) {
|
|
1307
|
-
const methodName = `visit${type.name}`;
|
|
1308
|
-
this._nodesVisitors[methodName] = visitor;
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
class NodeVisitor extends ANodeVisitor {
|
|
1312
|
-
constructor() {
|
|
1313
|
-
super();
|
|
1314
|
-
this.registerVisitor(RootAST, this.visitRootAST);
|
|
1315
|
-
this.registerVisitor(BlockStatementAST, this.visitBlockStatementAST);
|
|
1316
|
-
this.registerVisitor(IdentifierAST, this.visitIdentifierAST);
|
|
1317
|
-
this.registerVisitor(LiteralAST, this.visitLiteralAST);
|
|
1318
|
-
this.registerVisitor(AssignmentExpressionAST, this.visitAssignmentExpressionAST);
|
|
1319
|
-
this.registerVisitor(ExpressionStatementAST, this.visitExpressionStatementAST);
|
|
1320
|
-
this.registerVisitor(CallExpressionAST, this.visitCallExpressionAST);
|
|
1321
|
-
this.registerVisitor(BinaryExpressionAST, this.visitBinaryExpressionAST);
|
|
1322
|
-
this.registerVisitor(UnaryExpressionAST, this.visitUnaryExpressionAST);
|
|
1323
|
-
this.registerVisitor(IfStatementAST, this.visitIfStatementAST);
|
|
1324
|
-
this.registerVisitor(LogicalExpressionAST, this.visitLogicalExpressionAST);
|
|
1325
|
-
this.registerVisitor(IndexAccessorAST, this.visitIndexAccessorAST);
|
|
1326
|
-
this.registerVisitor(ObjectProperty, this.visitObjectProperty);
|
|
1327
|
-
this.registerVisitor(ObjectExpression, this.visitObjectExpression);
|
|
1328
|
-
this.registerVisitor(ArrayExpression, this.visitArrayExpression);
|
|
1329
|
-
this.registerVisitor(WhileLoopStatement, this.visitWhileLoopStatement);
|
|
1330
|
-
this.registerVisitor(ForLoopStatement, this.visitForLoopStatement);
|
|
1331
|
-
this.registerVisitor(ForOfStatement, this.visitForOfStatement);
|
|
1332
|
-
this.registerVisitor(BreakAST, this.visitBreakAST);
|
|
1333
|
-
this.registerVisitor(ContinueAST, this.visitContinueAST);
|
|
1334
|
-
this.registerVisitor(ReturnAST, this.visitReturnAST);
|
|
1335
|
-
}
|
|
1336
|
-
visit(node) {
|
|
1337
|
-
var _a;
|
|
1338
|
-
try {
|
|
1339
|
-
const methodName = `visit${node.constructor.name}`;
|
|
1340
|
-
// const fn = Object.getPrototypeOf(this)[methodName];
|
|
1341
|
-
const fn = this._nodesVisitors[methodName];
|
|
1342
|
-
return (_a = fn === null || fn === void 0 ? void 0 : fn.call(this, node)) !== null && _a !== void 0 ? _a : null;
|
|
1343
|
-
}
|
|
1344
|
-
catch (error) {
|
|
1345
|
-
return null;
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
assignProperty(owner, property, value) {
|
|
1349
|
-
if (Array.isArray(owner)) {
|
|
1350
|
-
owner[property] = value;
|
|
1351
|
-
}
|
|
1352
|
-
else if (typeof owner === 'object') {
|
|
1353
|
-
owner[property] = value;
|
|
1354
|
-
}
|
|
1355
|
-
else { }
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
class MEventScope {
|
|
1359
|
-
constructor(name, memory, parent) {
|
|
1360
|
-
this.memory = {};
|
|
1361
|
-
this.name = name;
|
|
1362
|
-
this.memory = memory;
|
|
1363
|
-
this.parent = parent;
|
|
1364
|
-
}
|
|
1365
|
-
resolve(key) {
|
|
1366
|
-
var _a, _b;
|
|
1367
|
-
return Object.keys(this.memory).includes(key) ? this.memory[key] : ((_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.resolve(key)) !== null && _b !== void 0 ? _b : null);
|
|
1368
|
-
}
|
|
1369
|
-
change(key, value, declare = true) {
|
|
1370
|
-
if (Object.keys(this.memory).includes(key)) {
|
|
1371
|
-
// change here
|
|
1372
|
-
this.memory[key] = value;
|
|
1373
|
-
return true;
|
|
1374
|
-
}
|
|
1375
|
-
if (this.parent && this.parent.change(key, value, false)) {
|
|
1376
|
-
return true;
|
|
1377
|
-
}
|
|
1378
|
-
if (!declare) {
|
|
1379
|
-
return false;
|
|
1380
|
-
}
|
|
1381
|
-
this.memory[key] = value;
|
|
1382
|
-
return true;
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
class MEvento extends NodeVisitor {
|
|
1386
|
-
constructor() {
|
|
1387
|
-
super();
|
|
1388
|
-
this.rootScope = new MEventScope("Program", {});
|
|
1389
|
-
this.currentScope = this.rootScope;
|
|
1390
|
-
this.debug = false;
|
|
1391
|
-
this._functionsRegistry = {};
|
|
1392
|
-
this._functionsRegistry = Object.assign({}, MEvento._globalFunctionsRegistry);
|
|
1393
|
-
}
|
|
1394
|
-
resolve(name) {
|
|
1395
|
-
var _a, _b;
|
|
1396
|
-
return (_b = (_a = this.currentScope) === null || _a === void 0 ? void 0 : _a.resolve(name)) !== null && _b !== void 0 ? _b : null;
|
|
1397
|
-
}
|
|
1398
|
-
changeVariable(name, value) {
|
|
1399
|
-
var _a;
|
|
1400
|
-
if ((_a = this.currentScope) === null || _a === void 0 ? void 0 : _a.change(name, value)) {
|
|
1401
|
-
return value;
|
|
1402
|
-
}
|
|
1403
|
-
else
|
|
1404
|
-
return null;
|
|
1405
|
-
}
|
|
1406
|
-
pushScope(name) {
|
|
1407
|
-
const scope = new MEventScope(name, {}, this.currentScope);
|
|
1408
|
-
this.currentScope = scope;
|
|
1409
|
-
}
|
|
1410
|
-
popScope() {
|
|
1411
|
-
var _a;
|
|
1412
|
-
this.currentScope = (_a = this.currentScope) === null || _a === void 0 ? void 0 : _a.parent;
|
|
1413
|
-
}
|
|
1414
|
-
log(message) {
|
|
1415
|
-
if (this.debug) {
|
|
1416
|
-
console.log(message);
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
visitRootAST(node) {
|
|
1420
|
-
var _a;
|
|
1421
|
-
const list = node.body;
|
|
1422
|
-
let last;
|
|
1423
|
-
for (const n of list) {
|
|
1424
|
-
last = this.visit(n);
|
|
1425
|
-
if (last instanceof ReturnBranch) {
|
|
1426
|
-
return (_a = last.value) !== null && _a !== void 0 ? _a : null;
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
return last !== null && last !== void 0 ? last : null;
|
|
1430
|
-
}
|
|
1431
|
-
visitBlockStatementAST(node) {
|
|
1432
|
-
const list = node.body;
|
|
1433
|
-
let last;
|
|
1434
|
-
this.pushScope("Block");
|
|
1435
|
-
for (const n of list) {
|
|
1436
|
-
last = this.visit(n);
|
|
1437
|
-
if (last instanceof LoopControl) {
|
|
1438
|
-
break;
|
|
1439
|
-
}
|
|
1440
|
-
if (last instanceof ReturnBranch) {
|
|
1441
|
-
break;
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
this.popScope();
|
|
1445
|
-
return last !== null && last !== void 0 ? last : null;
|
|
1446
|
-
}
|
|
1447
|
-
visitIdentifierAST(node) {
|
|
1448
|
-
var _a;
|
|
1449
|
-
const id = node.value;
|
|
1450
|
-
return (_a = this === null || this === void 0 ? void 0 : this.resolve(id)) !== null && _a !== void 0 ? _a : null;
|
|
1451
|
-
}
|
|
1452
|
-
visitLiteralAST(node) {
|
|
1453
|
-
const value = node.value;
|
|
1454
|
-
return value;
|
|
1455
|
-
}
|
|
1456
|
-
visitAssignmentExpressionAST(node) {
|
|
1457
|
-
const id = node.identifier;
|
|
1458
|
-
const init = node.init;
|
|
1459
|
-
let value = null;
|
|
1460
|
-
if (id instanceof IndexAccessorAST) {
|
|
1461
|
-
var target = this.visit(id.owner);
|
|
1462
|
-
value = this.visit(node.init);
|
|
1463
|
-
var property = this.visit(id.key);
|
|
1464
|
-
this.assignProperty(target, property, value);
|
|
1465
|
-
}
|
|
1466
|
-
else if (id instanceof IdentifierAST) {
|
|
1467
|
-
value = this.visit(init);
|
|
1468
|
-
this.changeVariable(id.value, value);
|
|
1469
|
-
}
|
|
1470
|
-
return value;
|
|
1471
|
-
}
|
|
1472
|
-
visitExpressionStatementAST(node) {
|
|
1473
|
-
const expr = node.expression;
|
|
1474
|
-
return this.visit(expr);
|
|
1475
|
-
}
|
|
1476
|
-
visitCallExpressionAST(node) {
|
|
1477
|
-
const callee = node.callee;
|
|
1478
|
-
const args = node.arguments;
|
|
1479
|
-
const calleeName = callee.value;
|
|
1480
|
-
const fn = this.resolveFunction(calleeName);
|
|
1481
|
-
const argValues = args.map((e) => this.visit(e));
|
|
1482
|
-
// print("argValues::", argValues)
|
|
1483
|
-
return fn === null || fn === void 0 ? void 0 : fn(argValues, this);
|
|
1484
|
-
}
|
|
1485
|
-
visitBinaryExpressionAST(node) {
|
|
1486
|
-
const left = node.left;
|
|
1487
|
-
const right = node.right;
|
|
1488
|
-
const op = node.operation;
|
|
1489
|
-
const lValue = this.visit(left);
|
|
1490
|
-
const rValue = this.visit(right);
|
|
1491
|
-
switch (op.type) {
|
|
1492
|
-
case TokenType.plus:
|
|
1493
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1494
|
-
return lValue + rValue;
|
|
1495
|
-
}
|
|
1496
|
-
return `${lValue}${rValue}`;
|
|
1497
|
-
case TokenType.minus:
|
|
1498
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1499
|
-
return lValue - rValue;
|
|
1500
|
-
}
|
|
1501
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1502
|
-
case TokenType.mult:
|
|
1503
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1504
|
-
return lValue * rValue;
|
|
1505
|
-
}
|
|
1506
|
-
if (isString(lValue) && isNum(rValue)) {
|
|
1507
|
-
return lValue.repeat(rValue);
|
|
1508
|
-
}
|
|
1509
|
-
if (isNum(lValue) && isString(rValue)) {
|
|
1510
|
-
return rValue.repeat(lValue);
|
|
1511
|
-
}
|
|
1512
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1513
|
-
case TokenType.div:
|
|
1514
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1515
|
-
if (rValue === 0) {
|
|
1516
|
-
throw new Error("Invalid division by 0");
|
|
1517
|
-
}
|
|
1518
|
-
return lValue / rValue;
|
|
1519
|
-
}
|
|
1520
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1521
|
-
case TokenType.mod:
|
|
1522
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1523
|
-
return lValue % rValue;
|
|
1524
|
-
}
|
|
1525
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1526
|
-
case TokenType.great:
|
|
1527
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1528
|
-
return lValue > rValue;
|
|
1529
|
-
}
|
|
1530
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1531
|
-
case TokenType.greatEq:
|
|
1532
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1533
|
-
return lValue >= rValue;
|
|
1534
|
-
}
|
|
1535
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1536
|
-
case TokenType.less:
|
|
1537
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1538
|
-
return lValue < rValue;
|
|
1539
|
-
}
|
|
1540
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1541
|
-
case TokenType.lessEq:
|
|
1542
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1543
|
-
return lValue <= rValue;
|
|
1544
|
-
}
|
|
1545
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1546
|
-
case TokenType.eqeq:
|
|
1547
|
-
return lValue === rValue;
|
|
1548
|
-
case TokenType.notEq:
|
|
1549
|
-
return lValue !== rValue;
|
|
1550
|
-
default:
|
|
1551
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
visitUnaryExpressionAST(node) {
|
|
1555
|
-
const arg = node.argument;
|
|
1556
|
-
const op = node.operation;
|
|
1557
|
-
const argValue = this.visit(arg);
|
|
1558
|
-
if (op.type === TokenType.not) {
|
|
1559
|
-
return _boolValue(argValue) === false;
|
|
1560
|
-
}
|
|
1561
|
-
if (!isNum(argValue)) {
|
|
1562
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1563
|
-
}
|
|
1564
|
-
if (op.type === TokenType.plus) {
|
|
1565
|
-
return argValue;
|
|
1566
|
-
}
|
|
1567
|
-
else if (op.type === TokenType.minus) {
|
|
1568
|
-
return -argValue;
|
|
1569
|
-
}
|
|
1570
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1571
|
-
}
|
|
1572
|
-
visitIfStatementAST(node) {
|
|
1573
|
-
const testNode = node.test;
|
|
1574
|
-
const test = this.visit(testNode);
|
|
1575
|
-
const testBoolValue = _boolValue(test);
|
|
1576
|
-
if (testBoolValue) {
|
|
1577
|
-
return this.visit(node.consequent);
|
|
1578
|
-
}
|
|
1579
|
-
if (node.alternate) {
|
|
1580
|
-
return this.visit(node.alternate);
|
|
1581
|
-
}
|
|
1582
|
-
return null;
|
|
1583
|
-
}
|
|
1584
|
-
visitLogicalExpressionAST(node) {
|
|
1585
|
-
const leftNode = node.left;
|
|
1586
|
-
let test = this.visit(leftNode);
|
|
1587
|
-
if (node.operator.type === TokenType.nullity) {
|
|
1588
|
-
if (test != null) {
|
|
1589
|
-
return test;
|
|
1590
|
-
}
|
|
1591
|
-
return this.visit(node.right);
|
|
1592
|
-
}
|
|
1593
|
-
const testBoolValue = _boolValue(test);
|
|
1594
|
-
if (node.operator.type === TokenType.and) {
|
|
1595
|
-
if (!testBoolValue) {
|
|
1596
|
-
return false;
|
|
1597
|
-
}
|
|
1598
|
-
return _boolValue(this.visit(node.right));
|
|
1599
|
-
}
|
|
1600
|
-
if (node.operator.type === TokenType.or) {
|
|
1601
|
-
if (testBoolValue) {
|
|
1602
|
-
return true;
|
|
1603
|
-
}
|
|
1604
|
-
return _boolValue(this.visit(node.right));
|
|
1605
|
-
}
|
|
1606
|
-
return null;
|
|
1607
|
-
}
|
|
1608
|
-
visitIndexAccessorAST(node) {
|
|
1609
|
-
var _a, _b;
|
|
1610
|
-
const ownerNode = node.owner;
|
|
1611
|
-
const owner = this.visit(ownerNode);
|
|
1612
|
-
if (owner === null || owner === undefined) {
|
|
1613
|
-
return null;
|
|
1614
|
-
}
|
|
1615
|
-
if (typeof owner === 'object') {
|
|
1616
|
-
const key = this.visit(node.key);
|
|
1617
|
-
return (_a = owner[key]) !== null && _a !== void 0 ? _a : null;
|
|
1618
|
-
}
|
|
1619
|
-
else if (Array.isArray(owner)) {
|
|
1620
|
-
const key = this.visit(node.key);
|
|
1621
|
-
return isNum(key) && owner.length < key && key >= 0 ? (_b = owner[key]) !== null && _b !== void 0 ? _b : null : null;
|
|
1622
|
-
}
|
|
1623
|
-
return null;
|
|
1624
|
-
}
|
|
1625
|
-
visitObjectProperty(node) { }
|
|
1626
|
-
visitObjectExpression(ast) {
|
|
1627
|
-
const instance = {};
|
|
1628
|
-
const node = ast;
|
|
1629
|
-
for (const it of node.properties) {
|
|
1630
|
-
if (it instanceof ObjectProperty) {
|
|
1631
|
-
let key = this.visit(it.key);
|
|
1632
|
-
key = isString(key) ? key : key.toString();
|
|
1633
|
-
instance[key] = this.visit(it.value);
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
return instance;
|
|
1637
|
-
}
|
|
1638
|
-
visitArrayExpression(ast) {
|
|
1639
|
-
const node = ast;
|
|
1640
|
-
const args = this.resolveArguments(node.elements);
|
|
1641
|
-
return args;
|
|
1642
|
-
}
|
|
1643
|
-
visitBreakAST(node) {
|
|
1644
|
-
return new BreakBranch();
|
|
1645
|
-
}
|
|
1646
|
-
visitWhileLoopStatement(node) {
|
|
1647
|
-
this.log(`WhileLoopStatement ${node.test} ${node.body}`);
|
|
1648
|
-
const retainer = node.retain ? [] : undefined;
|
|
1649
|
-
while (_boolValue(this.visit(node.test))) {
|
|
1650
|
-
const ret = this.visit(node.body);
|
|
1651
|
-
if (ret instanceof BreakBranch) {
|
|
1652
|
-
break;
|
|
1653
|
-
}
|
|
1654
|
-
if (ret instanceof ContinueBranch) {
|
|
1655
|
-
continue;
|
|
1656
|
-
}
|
|
1657
|
-
if (ret instanceof ReturnBranch) {
|
|
1658
|
-
this.popScope();
|
|
1659
|
-
return ret;
|
|
1660
|
-
}
|
|
1661
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
1662
|
-
}
|
|
1663
|
-
return retainer !== null && retainer !== void 0 ? retainer : null;
|
|
1664
|
-
}
|
|
1665
|
-
visitForLoopStatement(node) {
|
|
1666
|
-
const retainer = node.retain ? [] : undefined;
|
|
1667
|
-
const loopIdentifier = node.init.identifier;
|
|
1668
|
-
if (!(loopIdentifier instanceof IdentifierAST))
|
|
1669
|
-
throw new Error("Unexpected identifer found");
|
|
1670
|
-
this.pushScope("ForLoopStatement");
|
|
1671
|
-
const initialValue = this.visit(node.init.init);
|
|
1672
|
-
this.changeVariable(loopIdentifier.value, initialValue);
|
|
1673
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(initialValue);
|
|
1674
|
-
const test = () => {
|
|
1675
|
-
const ret = this.visit(node.test);
|
|
1676
|
-
if (isNum(ret)) {
|
|
1677
|
-
const tmp = this.resolve(loopIdentifier.value);
|
|
1678
|
-
return node.direction.type === TokenType.up ? ret >= tmp : ret <= tmp;
|
|
1679
|
-
}
|
|
1680
|
-
return _boolValue(ret);
|
|
1681
|
-
};
|
|
1682
|
-
const update = () => {
|
|
1683
|
-
const updateValue = this.visit(node.update);
|
|
1684
|
-
if (isNum(updateValue)) {
|
|
1685
|
-
// auto handle
|
|
1686
|
-
const tmp = this.resolve(loopIdentifier.value);
|
|
1687
|
-
if (!isNum(tmp))
|
|
1688
|
-
throw Error("Cant update value");
|
|
1689
|
-
this.changeVariable(loopIdentifier.value, node.direction.type === TokenType.up ? tmp + updateValue : tmp - updateValue);
|
|
1690
|
-
}
|
|
1691
|
-
else {
|
|
1692
|
-
throw Error("Update value cant be non number");
|
|
1693
|
-
}
|
|
1694
|
-
};
|
|
1695
|
-
while (test()) {
|
|
1696
|
-
const ret = this.visit(node.body);
|
|
1697
|
-
if (ret instanceof BreakBranch) {
|
|
1698
|
-
break;
|
|
1699
|
-
}
|
|
1700
|
-
if (ret instanceof ContinueBranch) {
|
|
1701
|
-
update();
|
|
1702
|
-
continue;
|
|
1703
|
-
}
|
|
1704
|
-
if (ret instanceof ReturnBranch) {
|
|
1705
|
-
this.popScope();
|
|
1706
|
-
return ret;
|
|
1707
|
-
}
|
|
1708
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
1709
|
-
// update
|
|
1710
|
-
update();
|
|
1711
|
-
}
|
|
1712
|
-
this.popScope();
|
|
1713
|
-
return retainer !== null && retainer !== void 0 ? retainer : null;
|
|
1714
|
-
}
|
|
1715
|
-
visitForOfStatement(node) {
|
|
1716
|
-
const collection = this.visit(node.collection);
|
|
1717
|
-
if (!Array.isArray(collection)) {
|
|
1718
|
-
throw Error("Can iterate non array object");
|
|
1719
|
-
}
|
|
1720
|
-
const retainer = node.retain ? [] : undefined;
|
|
1721
|
-
this.pushScope("ForOfStatement");
|
|
1722
|
-
for (const it of collection) {
|
|
1723
|
-
this._declareForIdentifier(node.identifier, it);
|
|
1724
|
-
const ret = this.visit(node.body);
|
|
1725
|
-
if (ret instanceof BreakBranch) {
|
|
1726
|
-
break;
|
|
1727
|
-
}
|
|
1728
|
-
if (ret instanceof ContinueBranch) {
|
|
1729
|
-
continue;
|
|
1730
|
-
}
|
|
1731
|
-
if (ret instanceof ReturnBranch) {
|
|
1732
|
-
this.popScope();
|
|
1733
|
-
return ret;
|
|
1734
|
-
}
|
|
1735
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
1736
|
-
}
|
|
1737
|
-
this.popScope();
|
|
1738
|
-
return retainer !== null && retainer !== void 0 ? retainer : null;
|
|
1739
|
-
}
|
|
1740
|
-
visitContinueAST(node) {
|
|
1741
|
-
return new ContinueBranch();
|
|
1742
|
-
}
|
|
1743
|
-
visitReturnAST(node) {
|
|
1744
|
-
return new ReturnBranch(node.value != null ? this.visit(node.value) : null);
|
|
1745
|
-
}
|
|
1746
|
-
_declareForIdentifier(node, value) {
|
|
1747
|
-
if (node instanceof TupleExpression) {
|
|
1748
|
-
if (!Array.isArray(value)) {
|
|
1749
|
-
throw Error("Unable to make a tuple from non Array element");
|
|
1750
|
-
}
|
|
1751
|
-
this.changeVariable(node.first.value, value[0]);
|
|
1752
|
-
this.changeVariable(node.second.value, value[1]);
|
|
1753
|
-
}
|
|
1754
|
-
this.changeVariable(node.value, value);
|
|
1755
|
-
}
|
|
1756
|
-
resolveArguments(args) {
|
|
1757
|
-
return args.map((it) => {
|
|
1758
|
-
return this.visit(it);
|
|
1759
|
-
});
|
|
1760
|
-
}
|
|
1761
|
-
setFunctionResolver(resolver) {
|
|
1762
|
-
this._functionResolver = resolver;
|
|
1763
|
-
}
|
|
1764
|
-
resolveFunction(name) {
|
|
1765
|
-
var _a, _b;
|
|
1766
|
-
return (_a = this._functionsRegistry[name]) !== null && _a !== void 0 ? _a : (_b = this._functionResolver) === null || _b === void 0 ? void 0 : _b.call(this, name);
|
|
1767
|
-
}
|
|
1768
|
-
registerFunction(id, fn) {
|
|
1769
|
-
this._functionsRegistry[id] = fn;
|
|
1770
|
-
}
|
|
1771
|
-
unregisterFunction(id) {
|
|
1772
|
-
delete this._functionsRegistry[id];
|
|
1773
|
-
}
|
|
1774
|
-
execute(source, cache = true, input) {
|
|
1775
|
-
const module = MEvento.compile(source, cache);
|
|
1776
|
-
if (input) {
|
|
1777
|
-
Object.keys(input).forEach(k => this.changeVariable(k, input[k]));
|
|
1778
|
-
}
|
|
1779
|
-
return this.visit(module);
|
|
1780
|
-
}
|
|
1781
|
-
static compile(source, cache = false) {
|
|
1782
|
-
const hash = hashCode(source);
|
|
1783
|
-
if (cache && this._cache.has(hash)) {
|
|
1784
|
-
return this._cache.get(hash);
|
|
1785
|
-
}
|
|
1786
|
-
const lexer = new Lexer(source);
|
|
1787
|
-
const parser = new Parser(lexer);
|
|
1788
|
-
const module = parser.parse();
|
|
1789
|
-
if (cache)
|
|
1790
|
-
this._cache.set(hash, module);
|
|
1791
|
-
return module;
|
|
1792
|
-
}
|
|
1793
|
-
static register(id, fn) {
|
|
1794
|
-
MEvento._globalFunctionsRegistry[id] = fn;
|
|
1795
|
-
}
|
|
1796
|
-
static unregister(id) {
|
|
1797
|
-
delete MEvento._globalFunctionsRegistry[id];
|
|
1798
|
-
}
|
|
1799
|
-
static run(source, cache = false, input) {
|
|
1800
|
-
const mevento = new MEvento();
|
|
1801
|
-
const module = MEvento.compile(source, cache);
|
|
1802
|
-
if (input) {
|
|
1803
|
-
Object.keys(input).forEach(k => mevento.changeVariable(k, input[k]));
|
|
1804
|
-
}
|
|
1805
|
-
return mevento.visit(module);
|
|
1806
|
-
}
|
|
1807
|
-
static newInstance() {
|
|
1808
|
-
// const lexer = Lexer(source);
|
|
1809
|
-
// const parser = Parser(lexer);
|
|
1810
|
-
// const module = parser.parse();
|
|
1811
|
-
return new MEvento();
|
|
1812
|
-
}
|
|
1813
|
-
clone() {
|
|
1814
|
-
var ret = new MEvento();
|
|
1815
|
-
ret._functionsRegistry = Object.assign({}, this._functionsRegistry);
|
|
1816
|
-
ret.rootScope.memory = Object.assign({}, this.rootScope.memory);
|
|
1817
|
-
return ret;
|
|
1818
|
-
}
|
|
1819
|
-
newAsyncInstance() {
|
|
1820
|
-
const asyncIns = MEventoAsync.newInstance();
|
|
1821
|
-
asyncIns.rootScope.memory = this.rootScope.memory;
|
|
1822
|
-
/// ????
|
|
1823
|
-
asyncIns._functionsRegistry = this._functionsRegistry;
|
|
1824
|
-
return asyncIns;
|
|
1825
|
-
}
|
|
1826
|
-
;
|
|
1827
|
-
}
|
|
1828
|
-
MEvento._globalFunctionsRegistry = {};
|
|
1829
|
-
MEvento._cache = new Map();
|
|
1830
|
-
class MEventoAsync extends MEvento {
|
|
1831
|
-
constructor() {
|
|
1832
|
-
super();
|
|
1833
|
-
}
|
|
1834
|
-
visitRootAST(node) {
|
|
1835
|
-
var _a;
|
|
1836
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1837
|
-
const list = node.body;
|
|
1838
|
-
let last;
|
|
1839
|
-
for (const n of list) {
|
|
1840
|
-
last = yield this.visit(n);
|
|
1841
|
-
if (last instanceof ReturnBranch) {
|
|
1842
|
-
return (_a = last.value) !== null && _a !== void 0 ? _a : null;
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
return last !== null && last !== void 0 ? last : null;
|
|
1846
|
-
});
|
|
1847
|
-
}
|
|
1848
|
-
visitBlockStatementAST(node) {
|
|
1849
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1850
|
-
const list = node.body;
|
|
1851
|
-
let last;
|
|
1852
|
-
this.pushScope("Block");
|
|
1853
|
-
for (const n of list) {
|
|
1854
|
-
last = yield this.visit(n);
|
|
1855
|
-
if (last instanceof LoopControl) {
|
|
1856
|
-
break;
|
|
1857
|
-
}
|
|
1858
|
-
if (last instanceof ReturnBranch) {
|
|
1859
|
-
break;
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
this.popScope();
|
|
1863
|
-
return last;
|
|
1864
|
-
});
|
|
1865
|
-
}
|
|
1866
|
-
visitIdentifierAST(node) {
|
|
1867
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1868
|
-
const id = node.value;
|
|
1869
|
-
return this.resolve(id);
|
|
1870
|
-
});
|
|
1871
|
-
}
|
|
1872
|
-
visitLiteralAST(node) {
|
|
1873
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1874
|
-
const value = node.value;
|
|
1875
|
-
return value;
|
|
1876
|
-
});
|
|
1877
|
-
}
|
|
1878
|
-
visitAssignmentExpressionAST(node) {
|
|
1879
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1880
|
-
const id = node.identifier;
|
|
1881
|
-
const init = node.init;
|
|
1882
|
-
let value = null;
|
|
1883
|
-
if (id instanceof IndexAccessorAST) {
|
|
1884
|
-
var target = yield this.visit(id.owner);
|
|
1885
|
-
value = yield this.visit(node.init);
|
|
1886
|
-
var property = yield this.visit(id.key);
|
|
1887
|
-
this.assignProperty(target, property, value);
|
|
1888
|
-
}
|
|
1889
|
-
else if (id instanceof IdentifierAST) {
|
|
1890
|
-
value = yield this.visit(init);
|
|
1891
|
-
this.changeVariable(id.value, value);
|
|
1892
|
-
}
|
|
1893
|
-
return value;
|
|
1894
|
-
});
|
|
1895
|
-
}
|
|
1896
|
-
visitExpressionStatementAST(node) {
|
|
1897
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1898
|
-
const expr = node.expression;
|
|
1899
|
-
return yield this.visit(expr);
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
visitCallExpressionAST(node) {
|
|
1903
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1904
|
-
const callee = node.callee;
|
|
1905
|
-
const args = node.arguments;
|
|
1906
|
-
const calleeName = callee.value;
|
|
1907
|
-
const fn = this._functionsRegistry[calleeName];
|
|
1908
|
-
const argValues = yield Promise.all(args.map((e) => this.visit(e)));
|
|
1909
|
-
// print("argValues::", argValues)
|
|
1910
|
-
return yield (fn === null || fn === void 0 ? void 0 : fn(argValues, this));
|
|
1911
|
-
});
|
|
1912
|
-
}
|
|
1913
|
-
visitBinaryExpressionAST(node) {
|
|
1914
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1915
|
-
const left = node.left;
|
|
1916
|
-
const right = node.right;
|
|
1917
|
-
const op = node.operation;
|
|
1918
|
-
const lValue = yield this.visit(left);
|
|
1919
|
-
const rValue = yield this.visit(right);
|
|
1920
|
-
switch (op.type) {
|
|
1921
|
-
case TokenType.plus:
|
|
1922
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1923
|
-
return lValue + rValue;
|
|
1924
|
-
}
|
|
1925
|
-
return `${lValue}${rValue}`;
|
|
1926
|
-
case TokenType.minus:
|
|
1927
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1928
|
-
return lValue - rValue;
|
|
1929
|
-
}
|
|
1930
|
-
if (isString(lValue) && isNum(rValue)) {
|
|
1931
|
-
return lValue.repeat(rValue);
|
|
1932
|
-
}
|
|
1933
|
-
if (isNum(lValue) && isString(rValue)) {
|
|
1934
|
-
return rValue.repeat(lValue);
|
|
1935
|
-
}
|
|
1936
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1937
|
-
case TokenType.mult:
|
|
1938
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1939
|
-
return lValue * rValue;
|
|
1940
|
-
}
|
|
1941
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1942
|
-
case TokenType.div:
|
|
1943
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1944
|
-
if (rValue === 0) {
|
|
1945
|
-
throw new Error("Invalid division by 0");
|
|
1946
|
-
}
|
|
1947
|
-
return lValue / rValue;
|
|
1948
|
-
}
|
|
1949
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1950
|
-
case TokenType.mod:
|
|
1951
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1952
|
-
return lValue % rValue;
|
|
1953
|
-
}
|
|
1954
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1955
|
-
case TokenType.great:
|
|
1956
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1957
|
-
return lValue > rValue;
|
|
1958
|
-
}
|
|
1959
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1960
|
-
case TokenType.greatEq:
|
|
1961
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1962
|
-
return lValue >= rValue;
|
|
1963
|
-
}
|
|
1964
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1965
|
-
case TokenType.less:
|
|
1966
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1967
|
-
return lValue < rValue;
|
|
1968
|
-
}
|
|
1969
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1970
|
-
case TokenType.lessEq:
|
|
1971
|
-
if (isNum(lValue) && isNum(rValue)) {
|
|
1972
|
-
return lValue <= rValue;
|
|
1973
|
-
}
|
|
1974
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1975
|
-
case TokenType.eqeq:
|
|
1976
|
-
return lValue === rValue;
|
|
1977
|
-
case TokenType.notEq:
|
|
1978
|
-
return lValue !== rValue;
|
|
1979
|
-
default:
|
|
1980
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1981
|
-
}
|
|
1982
|
-
});
|
|
1983
|
-
}
|
|
1984
|
-
visitUnaryExpressionAST(node) {
|
|
1985
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1986
|
-
const arg = node.argument;
|
|
1987
|
-
const op = node.operation;
|
|
1988
|
-
const argValue = yield this.visit(arg);
|
|
1989
|
-
if (op.type === TokenType.not) {
|
|
1990
|
-
return _boolValue(argValue) === false;
|
|
1991
|
-
}
|
|
1992
|
-
if (!isNum(argValue)) {
|
|
1993
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1994
|
-
}
|
|
1995
|
-
if (op.type === TokenType.plus) {
|
|
1996
|
-
return argValue;
|
|
1997
|
-
}
|
|
1998
|
-
else if (op.type === TokenType.minus) {
|
|
1999
|
-
return -argValue;
|
|
2000
|
-
}
|
|
2001
|
-
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
2002
|
-
});
|
|
2003
|
-
}
|
|
2004
|
-
visitIfStatementAST(node) {
|
|
2005
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2006
|
-
const testNode = node.test;
|
|
2007
|
-
const test = yield this.visit(testNode);
|
|
2008
|
-
const testBoolValue = _boolValue(test);
|
|
2009
|
-
if (testBoolValue) {
|
|
2010
|
-
return yield this.visit(node.consequent);
|
|
2011
|
-
}
|
|
2012
|
-
if (node.alternate) {
|
|
2013
|
-
return yield this.visit(node.alternate);
|
|
2014
|
-
}
|
|
2015
|
-
return null;
|
|
2016
|
-
});
|
|
2017
|
-
}
|
|
2018
|
-
visitLogicalExpressionAST(node) {
|
|
2019
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2020
|
-
const leftNode = node.left;
|
|
2021
|
-
let test = yield this.visit(leftNode);
|
|
2022
|
-
if (node.operator.type === TokenType.nullity) {
|
|
2023
|
-
if (test != null) {
|
|
2024
|
-
return test;
|
|
2025
|
-
}
|
|
2026
|
-
return yield this.visit(node.right);
|
|
2027
|
-
}
|
|
2028
|
-
const testBoolValue = _boolValue(test);
|
|
2029
|
-
if (node.operator.type === TokenType.and) {
|
|
2030
|
-
if (!testBoolValue) {
|
|
2031
|
-
return false;
|
|
2032
|
-
}
|
|
2033
|
-
return _boolValue(yield this.visit(node.right));
|
|
2034
|
-
}
|
|
2035
|
-
if (node.operator.type === TokenType.or) {
|
|
2036
|
-
if (testBoolValue) {
|
|
2037
|
-
return true;
|
|
2038
|
-
}
|
|
2039
|
-
return _boolValue(yield this.visit(node.right));
|
|
2040
|
-
}
|
|
2041
|
-
return false;
|
|
2042
|
-
});
|
|
2043
|
-
}
|
|
2044
|
-
visitIndexAccessorAST(node) {
|
|
2045
|
-
var _a, _b;
|
|
2046
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2047
|
-
const ownerNode = node.owner;
|
|
2048
|
-
const owner = yield this.visit(ownerNode);
|
|
2049
|
-
if (owner === null || owner === undefined) {
|
|
2050
|
-
return null;
|
|
2051
|
-
}
|
|
2052
|
-
if (typeof owner === 'object') {
|
|
2053
|
-
const key = yield this.visit(node.key);
|
|
2054
|
-
return (_a = owner[key]) !== null && _a !== void 0 ? _a : null;
|
|
2055
|
-
}
|
|
2056
|
-
else if (Array.isArray(owner)) {
|
|
2057
|
-
const key = yield this.visit(node.key);
|
|
2058
|
-
return isNum(key) && owner.length < key && key >= 0 ? (_b = owner[key]) !== null && _b !== void 0 ? _b : null : null;
|
|
2059
|
-
}
|
|
2060
|
-
return null;
|
|
2061
|
-
});
|
|
2062
|
-
}
|
|
2063
|
-
visitObjectProperty(node) {
|
|
2064
|
-
return __awaiter(this, void 0, void 0, function* () { });
|
|
2065
|
-
}
|
|
2066
|
-
visitObjectExpression(ast) {
|
|
2067
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2068
|
-
const instance = {};
|
|
2069
|
-
const node = ast;
|
|
2070
|
-
for (const it of node.properties) {
|
|
2071
|
-
if (it instanceof ObjectProperty) {
|
|
2072
|
-
let key = yield this.visit(it.key);
|
|
2073
|
-
key = isString(key) ? key : key.toString();
|
|
2074
|
-
instance[key] = yield this.visit(it.value);
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
return instance;
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
visitArrayExpression(ast) {
|
|
2081
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2082
|
-
const node = ast;
|
|
2083
|
-
const args = yield this.resolveArgumentsAsync(node.elements);
|
|
2084
|
-
return args;
|
|
2085
|
-
});
|
|
2086
|
-
}
|
|
2087
|
-
visitWhileLoopStatement(node) {
|
|
2088
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2089
|
-
this.log(`WhileLoopStatement ${node.test} ${node.body}`);
|
|
2090
|
-
const retainer = node.retain ? [] : undefined;
|
|
2091
|
-
while (_boolValue(yield this.visit(node.test))) {
|
|
2092
|
-
const ret = yield this.visit(node.body);
|
|
2093
|
-
if (ret instanceof BreakBranch) {
|
|
2094
|
-
break;
|
|
2095
|
-
}
|
|
2096
|
-
if (ret instanceof ContinueBranch) {
|
|
2097
|
-
continue;
|
|
2098
|
-
}
|
|
2099
|
-
if (ret instanceof ReturnBranch) {
|
|
2100
|
-
this.popScope();
|
|
2101
|
-
return ret;
|
|
2102
|
-
}
|
|
2103
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
2104
|
-
}
|
|
2105
|
-
return retainer;
|
|
2106
|
-
});
|
|
2107
|
-
}
|
|
2108
|
-
visitForLoopStatement(node) {
|
|
2109
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2110
|
-
const retainer = node.retain ? [] : undefined;
|
|
2111
|
-
const loopIdentifier = node.init.identifier;
|
|
2112
|
-
if (!(loopIdentifier instanceof IdentifierAST))
|
|
2113
|
-
throw new Error("Unexpected identifer found");
|
|
2114
|
-
this.pushScope("ForLoopStatement");
|
|
2115
|
-
const initialValue = yield this.visit(node.init.init);
|
|
2116
|
-
this.changeVariable(loopIdentifier.value, initialValue);
|
|
2117
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(initialValue);
|
|
2118
|
-
const test = () => __awaiter(this, void 0, void 0, function* () {
|
|
2119
|
-
const ret = yield this.visit(node.test);
|
|
2120
|
-
if (isNum(ret)) {
|
|
2121
|
-
const tmp = this.resolve(loopIdentifier.value);
|
|
2122
|
-
return node.direction.type === TokenType.up ? ret >= tmp : ret <= tmp;
|
|
2123
|
-
}
|
|
2124
|
-
return _boolValue(ret);
|
|
2125
|
-
});
|
|
2126
|
-
const update = () => __awaiter(this, void 0, void 0, function* () {
|
|
2127
|
-
const updateValue = yield this.visit(node.update);
|
|
2128
|
-
if (isNum(updateValue)) {
|
|
2129
|
-
// auto handle
|
|
2130
|
-
const tmp = this.resolve(loopIdentifier.value);
|
|
2131
|
-
if (!isNum(tmp))
|
|
2132
|
-
throw Error("Cant update value");
|
|
2133
|
-
this.changeVariable(loopIdentifier.value, node.direction.type === TokenType.up ? tmp + updateValue : tmp - updateValue);
|
|
2134
|
-
}
|
|
2135
|
-
else {
|
|
2136
|
-
throw Error("Update value cant be non number");
|
|
2137
|
-
}
|
|
2138
|
-
});
|
|
2139
|
-
while (yield test()) {
|
|
2140
|
-
const ret = yield this.visit(node.body);
|
|
2141
|
-
if (ret instanceof BreakBranch) {
|
|
2142
|
-
break;
|
|
2143
|
-
}
|
|
2144
|
-
if (ret instanceof ContinueBranch) {
|
|
2145
|
-
yield update();
|
|
2146
|
-
continue;
|
|
2147
|
-
}
|
|
2148
|
-
if (ret instanceof ReturnBranch) {
|
|
2149
|
-
this.popScope();
|
|
2150
|
-
return ret;
|
|
2151
|
-
}
|
|
2152
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
2153
|
-
// update
|
|
2154
|
-
yield update();
|
|
2155
|
-
}
|
|
2156
|
-
this.popScope();
|
|
2157
|
-
return retainer !== null && retainer !== void 0 ? retainer : null;
|
|
2158
|
-
});
|
|
2159
|
-
}
|
|
2160
|
-
visitForOfStatement(node) {
|
|
2161
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2162
|
-
const collection = yield this.visit(node.collection);
|
|
2163
|
-
if (!Array.isArray(collection)) {
|
|
2164
|
-
throw Error("Can iterate non array object");
|
|
2165
|
-
}
|
|
2166
|
-
const retainer = node.retain ? [] : undefined;
|
|
2167
|
-
this.pushScope("ForOfStatement");
|
|
2168
|
-
for (const it of collection) {
|
|
2169
|
-
this._declareForIdentifier(node.identifier, it);
|
|
2170
|
-
const ret = yield this.visit(node.body);
|
|
2171
|
-
if (ret instanceof BreakBranch) {
|
|
2172
|
-
break;
|
|
2173
|
-
}
|
|
2174
|
-
if (ret instanceof ContinueBranch) {
|
|
2175
|
-
continue;
|
|
2176
|
-
}
|
|
2177
|
-
if (ret instanceof ReturnBranch) {
|
|
2178
|
-
this.popScope();
|
|
2179
|
-
return ret;
|
|
2180
|
-
}
|
|
2181
|
-
retainer === null || retainer === void 0 ? void 0 : retainer.push(ret);
|
|
2182
|
-
}
|
|
2183
|
-
this.popScope();
|
|
2184
|
-
return retainer;
|
|
2185
|
-
});
|
|
2186
|
-
}
|
|
2187
|
-
visitReturnAST(node) {
|
|
2188
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2189
|
-
return new ReturnBranch(node.value != null ? yield this.visit(node.value) : null);
|
|
2190
|
-
});
|
|
2191
|
-
}
|
|
2192
|
-
resolveArgumentsAsync(args) {
|
|
2193
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2194
|
-
return yield Promise.all(args.map((it) => __awaiter(this, void 0, void 0, function* () {
|
|
2195
|
-
return yield this.visit(it);
|
|
2196
|
-
})));
|
|
2197
|
-
});
|
|
2198
|
-
}
|
|
2199
|
-
registerFunction(id, fn) {
|
|
2200
|
-
this._functionsRegistry[id] = fn;
|
|
2201
|
-
}
|
|
2202
|
-
unregisterFunction(id) {
|
|
2203
|
-
delete this._functionsRegistry[id];
|
|
2204
|
-
}
|
|
2205
|
-
execute(source, cache = true, input) {
|
|
2206
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2207
|
-
const module = MEvento.compile(source, cache);
|
|
2208
|
-
if (input) {
|
|
2209
|
-
Object.keys(input).forEach(k => this.changeVariable(k, input[k]));
|
|
2210
|
-
}
|
|
2211
|
-
return yield this.visit(module);
|
|
2212
|
-
});
|
|
2213
|
-
}
|
|
2214
|
-
static run(source, cache = false, input) {
|
|
2215
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2216
|
-
const mevento = new MEventoAsync();
|
|
2217
|
-
const module = MEvento.compile(source, cache);
|
|
2218
|
-
if (input) {
|
|
2219
|
-
Object.keys(input).forEach(k => mevento.changeVariable(k, input[k]));
|
|
2220
|
-
}
|
|
2221
|
-
return yield mevento.visit(module);
|
|
2222
|
-
});
|
|
2223
|
-
}
|
|
2224
|
-
static newInstance() {
|
|
2225
|
-
return new MEventoAsync();
|
|
2226
|
-
}
|
|
2227
|
-
clone() {
|
|
2228
|
-
var ret = new MEventoAsync();
|
|
2229
|
-
ret._functionsRegistry = Object.assign({}, this._functionsRegistry);
|
|
2230
|
-
ret.rootScope.memory = Object.assign({}, this.rootScope.memory);
|
|
2231
|
-
return ret;
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
|
|
2235
|
-
/*
|
|
2236
|
-
* Public API Surface of mevento
|
|
2237
|
-
*/
|
|
2238
|
-
|
|
2239
|
-
/**
|
|
2240
|
-
* Generated bundle index. Do not edit.
|
|
2241
|
-
*/
|
|
2242
|
-
|
|
2243
|
-
export { AST, ArrayExpression, AssignmentExpressionAST, BinaryExpressionAST, BlockStatementAST, BreakAST, BreakBranch, CallExpressionAST, ContinueAST, ContinueBranch, ExpressionStatementAST, ForLoopStatement, ForOfStatement, IdentifierAST, IfStatementAST, IndexAccessorAST, LexerDictionary, LiteralAST, LogicalExpressionAST, LoopControl, MEventScope, MEvento, MEventoAsync, NodeVisitor, ObjectExpression, ObjectProperty, ReturnAST, ReturnBranch, RootAST, Token, TokenType, TupleExpression, UnaryExpressionAST, WhileLoopStatement };
|
|
2244
|
-
//# sourceMappingURL=mevento.mjs.map
|