mevento 2.0.5 → 2.1.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.
@@ -181,6 +181,15 @@ class Lexer {
181
181
  this._currentChar = this._source[this._position].charCodeAt(0);
182
182
  this._col++;
183
183
  }
184
+ _jump(n) {
185
+ this._position += n;
186
+ if (this._position >= this._source.length) {
187
+ this._currentChar = -1;
188
+ return;
189
+ }
190
+ this._currentChar = this._source[this._position].charCodeAt(0);
191
+ this._col += n;
192
+ }
184
193
  _pick() {
185
194
  if (this._position + 1 >= this._source.length) {
186
195
  return -1;
@@ -315,28 +324,62 @@ class Lexer {
315
324
  const lastL = this._line;
316
325
  while (this._currentChar !== -1) {
317
326
  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;
327
+ if (this._currentChar == Chars.backslash) {
328
+ switch (next) {
329
+ case '\\':
330
+ ret += "\\";
331
+ break;
332
+ case '0':
333
+ ret += "\0";
334
+ break;
335
+ case 'a':
336
+ ret += "\a";
337
+ break;
338
+ case 'b':
339
+ ret += "\b";
340
+ break;
341
+ case 'f':
342
+ ret += "\f";
343
+ break;
344
+ case 'n':
345
+ ret += "\n";
346
+ break;
347
+ case 'r':
348
+ ret += "\r";
349
+ break;
350
+ case 't':
351
+ ret += "\t";
352
+ break;
353
+ case 'u':
354
+ ret += String.fromCharCode(Number.parseInt(this._source.substring(this._position + 2, this._position + 6), 16));
355
+ this._jump(4);
356
+ // consume 4 unicode chars
357
+ break;
358
+ case 'v':
359
+ ret += "\v";
360
+ break;
361
+ case 'x':
362
+ ret += String.fromCharCode(Number.parseInt(this._source.substring(this._position + 2, this._position + 4), 16));
363
+ this._jump(2);
364
+ break;
365
+ default:
366
+ {
367
+ if (String.fromCharCode(startChar) == next) {
368
+ ret += String.fromCharCode(startChar);
369
+ }
370
+ else {
371
+ this._advance();
372
+ lastChar = this._currentChar;
373
+ ret += String.fromCharCode(this._currentChar);
374
+ this._advance();
375
+ continue;
376
+ }
377
+ }
339
378
  }
379
+ // scape char
380
+ this._jump(2);
381
+ lastChar = this._currentChar;
382
+ continue;
340
383
  }
341
384
  if (this._currentChar === startChar && lastChar !== Chars.backslash) {
342
385
  // end
@@ -802,8 +845,33 @@ class ContinueAST extends AST {
802
845
  super(line, col);
803
846
  }
804
847
  }
848
+ class ListQueue {
849
+ constructor(capacity = Infinity) {
850
+ this.capacity = capacity;
851
+ this.storage = [];
852
+ }
853
+ push(item) {
854
+ if (this.size() === this.capacity) {
855
+ throw Error("Stack has reached max capacity, you cannot add more items");
856
+ }
857
+ this.storage.push(item);
858
+ }
859
+ pop() {
860
+ return this.storage.pop();
861
+ }
862
+ peek() {
863
+ return this.storage[this.size() - 1];
864
+ }
865
+ size() {
866
+ return this.storage.length;
867
+ }
868
+ get isEmpty() {
869
+ return this.storage.length === 0;
870
+ }
871
+ }
805
872
  class Parser {
806
873
  constructor(lexer) {
874
+ this._loopTrack = new ListQueue();
807
875
  this.currentToken = lexer.nextToken();
808
876
  this.lexer = lexer;
809
877
  }
@@ -881,10 +949,34 @@ class Parser {
881
949
  return this._objectExpression();
882
950
  case TokenType.IF:
883
951
  return this._ifStatement();
952
+ case TokenType.WHILE_TILL:
953
+ return this._whileLoop(true);
954
+ case TokenType.FOR_LOOP:
955
+ return this._forLoop(true);
956
+ case TokenType.BREAK:
957
+ return this._breakExpression();
958
+ case TokenType.CONTINUE:
959
+ return this._continueExpression();
884
960
  default:
885
961
  return this._variable();
886
962
  }
887
963
  }
964
+ _breakExpression() {
965
+ var _a, _b;
966
+ if (this._loopTrack.isEmpty) {
967
+ error(this.currentToken);
968
+ }
969
+ this._eat(TokenType.BREAK);
970
+ 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);
971
+ }
972
+ _continueExpression() {
973
+ var _a, _b;
974
+ if (this._loopTrack.isEmpty) {
975
+ error(this.currentToken);
976
+ }
977
+ this._eat(TokenType.CONTINUE);
978
+ return new ContinueAST((_a = this.currentToken) === null || _a === void 0 ? void 0 : _a.line, (_b = this.currentToken) === null || _b === void 0 ? void 0 : _b.col);
979
+ }
888
980
  _term() {
889
981
  let node = this._factor();
890
982
  node = this._tryParsingFunctionCall(node);
@@ -1123,12 +1215,20 @@ class Parser {
1123
1215
  }
1124
1216
  return new IfStatementAST(test, consequent, alternate);
1125
1217
  }
1126
- _whileLoop() {
1218
+ _pushLoop() {
1219
+ this._loopTrack.push(true);
1220
+ }
1221
+ _popLoop() {
1222
+ this._loopTrack.pop();
1223
+ }
1224
+ _whileLoop(retain = false) {
1127
1225
  const token = this.currentToken;
1128
1226
  this._eat(TokenType.WHILE_TILL);
1227
+ this._pushLoop();
1129
1228
  const test = this._expression();
1130
1229
  const body = this.currentToken.type === TokenType.lbrace ? this._blockStatement() : this._expression();
1131
- return new WhileLoopStatement(test, body, token, this.currentToken);
1230
+ this._popLoop();
1231
+ return new WhileLoopStatement(test, body, token, this.currentToken, retain);
1132
1232
  }
1133
1233
  _forOfIdentifier() {
1134
1234
  switch (this.currentToken.type) {
@@ -1154,9 +1254,10 @@ class Parser {
1154
1254
  * }
1155
1255
  * (seginka|for) mali kono a
1156
1256
  */
1157
- _forLoop() {
1257
+ _forLoop(retain = false) {
1158
1258
  const startToken = this.currentToken;
1159
1259
  this._eat(TokenType.FOR_LOOP);
1260
+ this._pushLoop();
1160
1261
  let forOf = [TokenType.lparen].includes(this.currentToken.type);
1161
1262
  let node;
1162
1263
  if (forOf) {
@@ -1192,13 +1293,15 @@ class Parser {
1192
1293
  update = new LiteralAST(new Token(TokenType.numberConst, 1, this.currentToken.line, this.currentToken.col), "1");
1193
1294
  }
1194
1295
  const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
1195
- node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken);
1296
+ node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken, retain);
1297
+ this._popLoop();
1196
1298
  }
1197
1299
  else if (forOf) {
1198
1300
  this._eat(TokenType.in);
1199
1301
  const collection = this._expression();
1200
1302
  const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
1201
- node = new ForOfStatement(node, collection, body, startToken, this.currentToken);
1303
+ node = new ForOfStatement(node, collection, body, startToken, this.currentToken, retain);
1304
+ this._popLoop();
1202
1305
  }
1203
1306
  else {
1204
1307
  error(this.currentToken);
@@ -1206,14 +1309,11 @@ class Parser {
1206
1309
  return node;
1207
1310
  }
1208
1311
  _statement() {
1209
- var _a, _b, _c, _d;
1210
1312
  switch (this.currentToken.type) {
1211
1313
  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);
1314
+ return this._breakExpression();
1214
1315
  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);
1316
+ return this._continueExpression();
1217
1317
  case TokenType.RETURN:
1218
1318
  this._eat(TokenType.RETURN);
1219
1319
  return this._return();
@@ -1498,17 +1598,17 @@ class MEvento extends NodeVisitor {
1498
1598
  if (isNum(lValue) && isNum(rValue)) {
1499
1599
  return lValue - rValue;
1500
1600
  }
1501
- if (isString(lValue) && isNum(rValue)) {
1502
- return lValue * rValue;
1503
- }
1504
- if (isNum(lValue) && isString(rValue)) {
1505
- return rValue * lValue;
1506
- }
1507
1601
  throw new Error(`Operation ${op.value} not allowed no num value`);
1508
1602
  case TokenType.mult:
1509
1603
  if (isNum(lValue) && isNum(rValue)) {
1510
1604
  return lValue * rValue;
1511
1605
  }
1606
+ if (isString(lValue) && isNum(rValue)) {
1607
+ return lValue.repeat(rValue);
1608
+ }
1609
+ if (isNum(lValue) && isString(rValue)) {
1610
+ return rValue.repeat(lValue);
1611
+ }
1512
1612
  throw new Error(`Operation ${op.value} not allowed no num value`);
1513
1613
  case TokenType.div:
1514
1614
  if (isNum(lValue) && isNum(rValue)) {
@@ -1670,7 +1770,7 @@ class MEvento extends NodeVisitor {
1670
1770
  this.pushScope("ForLoopStatement");
1671
1771
  const initialValue = this.visit(node.init.init);
1672
1772
  this.changeVariable(loopIdentifier.value, initialValue);
1673
- retainer === null || retainer === void 0 ? void 0 : retainer.push(initialValue);
1773
+ // retainer?.push(initialValue)
1674
1774
  const test = () => {
1675
1775
  const ret = this.visit(node.test);
1676
1776
  if (isNum(ret)) {
@@ -1928,10 +2028,10 @@ class MEventoAsync extends MEvento {
1928
2028
  return lValue - rValue;
1929
2029
  }
1930
2030
  if (isString(lValue) && isNum(rValue)) {
1931
- return lValue * rValue;
2031
+ return lValue.repeat(rValue);
1932
2032
  }
1933
2033
  if (isNum(lValue) && isString(rValue)) {
1934
- return rValue * lValue;
2034
+ return rValue.repeat(lValue);
1935
2035
  }
1936
2036
  throw new Error(`Operation ${op.value} not allowed no num value`);
1937
2037
  case TokenType.mult:
@@ -2114,7 +2214,7 @@ class MEventoAsync extends MEvento {
2114
2214
  this.pushScope("ForLoopStatement");
2115
2215
  const initialValue = yield this.visit(node.init.init);
2116
2216
  this.changeVariable(loopIdentifier.value, initialValue);
2117
- retainer === null || retainer === void 0 ? void 0 : retainer.push(initialValue);
2217
+ // retainer?.push(initialValue)
2118
2218
  const test = () => __awaiter(this, void 0, void 0, function* () {
2119
2219
  const ret = yield this.visit(node.test);
2120
2220
  if (isNum(ret)) {