mevento 1.0.0 → 1.2.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.
@@ -26,9 +26,7 @@ function hashCode(str) {
26
26
  return hash;
27
27
  for (i = 0; i < str.length; i++) {
28
28
  chr = str.charCodeAt(i);
29
- // tslint:disable-next-line:no-bitwise
30
29
  hash = ((hash << 5) - hash) + chr;
31
- // tslint:disable-next-line:no-bitwise
32
30
  hash |= 0; // Convert to 32bit integer
33
31
  }
34
32
  return hash;
@@ -71,6 +69,14 @@ TokenType.mult = 31;
71
69
  TokenType.mod = 32;
72
70
  TokenType.invalid = 33;
73
71
  TokenType.colon = 34;
72
+ TokenType.WHILE_TILL = 35;
73
+ TokenType.FOR_LOOP = 36;
74
+ TokenType.up = 37;
75
+ TokenType.down = 38;
76
+ TokenType.with = 39;
77
+ TokenType.in = 40;
78
+ TokenType.TILL = 41;
79
+ TokenType.BREAK = 42;
74
80
  class Token {
75
81
  constructor(type, value, line = 1, col = 1) {
76
82
  this.type = type;
@@ -474,15 +480,31 @@ Lexer._defaultLanguage = new LexerDictionary("en", {
474
480
  "true": "true",
475
481
  "false": "false",
476
482
  "null": "null",
483
+ "while": "while",
484
+ "for": "for",
485
+ "with": "with",
486
+ "up": "up",
487
+ "down": "down",
488
+ "till": "till",
489
+ "in": "in",
490
+ "break": "break",
477
491
  });
478
492
  Lexer.languages = [
479
493
  Lexer._defaultLanguage,
480
494
  new LexerDictionary("fr", {
481
495
  "si": "if",
482
496
  "sinon": "else",
483
- "vrai": "else",
497
+ "vrai": "true",
484
498
  "faux": "false",
485
499
  "nul": "null",
500
+ "tanque": "while",
501
+ "pour": "for",
502
+ "avec": "with",
503
+ "mon": "up",
504
+ "desc": "down",
505
+ "jusqua": "till",
506
+ "dans": "in",
507
+ "couper": "break",
486
508
  }),
487
509
  new LexerDictionary("bm", {
488
510
  "nii": "if",
@@ -490,6 +512,14 @@ Lexer.languages = [
490
512
  "tien": "true",
491
513
  "galon": "false",
492
514
  "gansan": "null",
515
+ "foo": "while",
516
+ "seginka": "for",
517
+ "niin": "with",
518
+ "kay": "up",
519
+ "kaj": "down",
520
+ "kata": "till",
521
+ "kono": "in",
522
+ "tike": "break",
493
523
  }),
494
524
  ];
495
525
  Lexer.RESERVED = {
@@ -498,6 +528,14 @@ Lexer.RESERVED = {
498
528
  "true": Token.from(TokenType.TRUE, true),
499
529
  "false": Token.from(TokenType.FALSE, false),
500
530
  "null": Token.from(TokenType.NULL, null),
531
+ "for": Token.from(TokenType.FOR_LOOP, "for"),
532
+ "while": Token.from(TokenType.WHILE_TILL, "while"),
533
+ "with": Token.from(TokenType.with, "with"),
534
+ "up": Token.from(TokenType.up, "up"),
535
+ "down": Token.from(TokenType.down, "down"),
536
+ "till": Token.from(TokenType.TILL, "till"),
537
+ "in": Token.from(TokenType.in, "in"),
538
+ "break": Token.from(TokenType.BREAK, "break"),
501
539
  };
502
540
  /**
503
541
  * Parser
@@ -612,7 +650,7 @@ class IfStatementAST extends AST {
612
650
  this.alternate = alternate;
613
651
  }
614
652
  toString() {
615
- return `if ${this.test} ${this.consequent} ${this.alternate !== null ? `else ${this.alternate} ` : ''}`;
653
+ return `if ${this.test} ${this.consequent} ${this.alternate ? `else ${this.alternate} ` : ''}`;
616
654
  }
617
655
  }
618
656
  class LogicalExpressionAST extends AST {
@@ -663,6 +701,47 @@ class ObjectProperty extends AST {
663
701
  this.key = key;
664
702
  }
665
703
  }
704
+ class WhileLoopStatement extends AST {
705
+ constructor(test, body, startToken, endToken, retain = false) {
706
+ super(startToken?.line, startToken?.col);
707
+ this.retain = false;
708
+ this.test = test;
709
+ this.body = body;
710
+ this.retain = retain;
711
+ }
712
+ }
713
+ class ForLoopStatement extends AST {
714
+ constructor(init, test, update, direction, body, startToken, endToken, retain = false) {
715
+ super(startToken?.line, startToken?.col);
716
+ this.init = init;
717
+ this.test = test;
718
+ this.update = update;
719
+ this.direction = direction;
720
+ this.body = body;
721
+ this.retain = retain;
722
+ }
723
+ }
724
+ class ForOfStatement extends AST {
725
+ constructor(identifier, collection, body, startToken, endToken, retain = false) {
726
+ super(startToken?.line, startToken?.col);
727
+ this.identifier = identifier;
728
+ this.collection = collection;
729
+ this.body = body;
730
+ this.retain = retain;
731
+ }
732
+ }
733
+ class TupleExpression extends AST {
734
+ constructor(first, second) {
735
+ super(first.line, first.col);
736
+ this.first = first;
737
+ this.second = second;
738
+ }
739
+ }
740
+ class BreakAST extends AST {
741
+ constructor(line, col) {
742
+ super(line, col);
743
+ }
744
+ }
666
745
  class Parser {
667
746
  constructor(lexer) {
668
747
  this.currentToken = lexer.nextToken();
@@ -905,6 +984,8 @@ class Parser {
905
984
  break;
906
985
  }
907
986
  body.push(this._statement());
987
+ if (this._expect(TokenType.rbrace))
988
+ break;
908
989
  if (this.currentToken.type !== TokenType.eol &&
909
990
  this.currentToken.type !== TokenType.semi &&
910
991
  this.currentToken.type !== TokenType.eof) {
@@ -916,7 +997,8 @@ class Parser {
916
997
  // endBlock
917
998
  this._eat(TokenType.rbrace);
918
999
  }
919
- return new BlockStatementAST(body, this.currentToken);
1000
+ const ret = new BlockStatementAST(body, this.currentToken);
1001
+ return ret;
920
1002
  }
921
1003
  _ifStatement() {
922
1004
  this._eat(TokenType.IF);
@@ -952,8 +1034,94 @@ class Parser {
952
1034
  }
953
1035
  return new IfStatementAST(test, consequent, alternate);
954
1036
  }
1037
+ _whileLoop() {
1038
+ const token = this.currentToken;
1039
+ this._eat(TokenType.WHILE_TILL);
1040
+ const test = this._expression();
1041
+ const body = this.currentToken.type == TokenType.lbrace ? this._blockStatement() : this._expression();
1042
+ return new WhileLoopStatement(test, body, token, this.currentToken);
1043
+ }
1044
+ _forOfIdentifier() {
1045
+ let node;
1046
+ switch (this.currentToken.type) {
1047
+ case TokenType.lparen: {
1048
+ // probable tuple
1049
+ this._eat(TokenType.lparen);
1050
+ const first = this._variable();
1051
+ this._eat(TokenType.comma);
1052
+ const second = this._variable();
1053
+ this._eat(TokenType.rparen);
1054
+ return new TupleExpression(first, second);
1055
+ }
1056
+ // TokenType.LBRACE -> objectPattern()
1057
+ // TokenType.LBRACKET -> arrayPattern()
1058
+ default:
1059
+ return this._variable();
1060
+ }
1061
+ }
1062
+ /**
1063
+ * # ForLoopStatement with step
1064
+ * (seginka|for) a=0 (foo|to) 10 (kay|kaj) niin 2 { # for a = 0; a<10; a+=2
1065
+ *
1066
+ * }
1067
+ * (seginka|for) mali kono a
1068
+ */
1069
+ _forLoop() {
1070
+ const startToken = this.currentToken;
1071
+ this._eat(TokenType.FOR_LOOP);
1072
+ let forOf = [TokenType.lparen].includes(this.currentToken.type);
1073
+ let node;
1074
+ if (forOf) {
1075
+ node = this._forOfIdentifier();
1076
+ }
1077
+ else {
1078
+ const expr = this._expression();
1079
+ if (!(expr instanceof AssignmentExpressionAST)) {
1080
+ forOf = true;
1081
+ }
1082
+ node = expr;
1083
+ }
1084
+ if (!forOf && node instanceof AssignmentExpressionAST) {
1085
+ // normal for
1086
+ this._eat(TokenType.TILL);
1087
+ const test = this._expression();
1088
+ let direction;
1089
+ if (this.currentToken.type === TokenType.up || this.currentToken.type === TokenType.down) {
1090
+ const t = this.currentToken;
1091
+ this._eat(t.type);
1092
+ direction = t;
1093
+ }
1094
+ else {
1095
+ direction = new Token(TokenType.up, "up");
1096
+ }
1097
+ let update;
1098
+ if (this._expect(TokenType.with)) {
1099
+ this._eat(TokenType.with);
1100
+ const expr = this._expression();
1101
+ update = expr;
1102
+ }
1103
+ else {
1104
+ update = new LiteralAST(new Token(TokenType.numberConst, 1, this.currentToken.line, this.currentToken.col), "1");
1105
+ }
1106
+ const body = (this.currentToken.type == TokenType.lbrace) ? this._blockStatement() : this._expression();
1107
+ node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken);
1108
+ }
1109
+ else if (forOf) {
1110
+ this._eat(TokenType.in);
1111
+ const collection = this._expression();
1112
+ const body = (this.currentToken.type == TokenType.lbrace) ? this._blockStatement() : this._expression();
1113
+ node = new ForOfStatement(node, collection, body, startToken, this.currentToken);
1114
+ }
1115
+ else {
1116
+ error(this.currentToken);
1117
+ }
1118
+ return node;
1119
+ }
955
1120
  _statement() {
956
1121
  switch (this.currentToken.type) {
1122
+ case TokenType.BREAK:
1123
+ this._eat(TokenType.BREAK);
1124
+ return new BreakAST(this.currentToken?.line, this.currentToken?.col);
957
1125
  case TokenType.semi:
958
1126
  this._eatSemi();
959
1127
  return this._statement();
@@ -962,6 +1130,10 @@ class Parser {
962
1130
  return this._statement();
963
1131
  case TokenType.IF:
964
1132
  return this._ifStatement();
1133
+ case TokenType.WHILE_TILL:
1134
+ return this._whileLoop();
1135
+ case TokenType.FOR_LOOP:
1136
+ return this._forLoop();
965
1137
  default:
966
1138
  return this._statementExpression();
967
1139
  }
@@ -969,32 +1141,31 @@ class Parser {
969
1141
  _expect(type) {
970
1142
  return this.currentToken?.type === type;
971
1143
  }
972
- _statements() {
973
- this._eatEOL();
1144
+ _definition() {
1145
+ this._eatSemiOrEOL();
974
1146
  if (this._expect(TokenType.eof)) {
975
1147
  return [];
976
1148
  }
977
1149
  const results = [this._statement()];
978
- while ((this.currentToken.type === TokenType.eol ||
979
- this.currentToken.type === TokenType.semi)) {
1150
+ while (true) {
980
1151
  this._eatSemiOrEOL();
981
1152
  if (this.currentToken.type === TokenType.eof) {
982
1153
  this._eat(TokenType.eof);
983
1154
  break;
984
1155
  }
985
1156
  results.push(this._statement());
986
- if (this.currentToken.type !== TokenType.eol &&
987
- this.currentToken.type !== TokenType.semi &&
988
- this.currentToken.type !== TokenType.eof) {
989
- error(this.currentToken);
990
- }
1157
+ // if (this.currentToken!.type !== TokenType.eol &&
1158
+ // this.currentToken!.type !== TokenType.semi &&
1159
+ // this.currentToken!.type !== TokenType.eof) {
1160
+ // error(this.currentToken!);
1161
+ // }
991
1162
  }
992
1163
  return results;
993
1164
  }
994
1165
  _root() {
995
1166
  const source = this.lexer.source;
996
1167
  const name = "<module>";
997
- const list = this._statements();
1168
+ const list = this._definition();
998
1169
  return new RootAST(list, name, source);
999
1170
  }
1000
1171
  parse() {
@@ -1014,6 +1185,8 @@ Parser._binopPrecdences = {
1014
1185
  [TokenType.div]: 40,
1015
1186
  [TokenType.mod]: 40,
1016
1187
  };
1188
+ class BreakBranch {
1189
+ }
1017
1190
  // AST Wallker
1018
1191
  class ANodeVisitor {
1019
1192
  constructor() {
@@ -1035,6 +1208,7 @@ class AsyncNodeVisitor extends ANodeVisitor {
1035
1208
  }
1036
1209
  class NodeVisitor extends ANodeVisitor {
1037
1210
  visit(node) {
1211
+ // console.log('node::', node);
1038
1212
  const methodName = `visit${node.constructor.name}`;
1039
1213
  // const fn = Object.getPrototypeOf(this)[methodName];
1040
1214
  const fn = this._nodesVisitors[methodName];
@@ -1045,6 +1219,7 @@ class MEvento extends NodeVisitor {
1045
1219
  constructor() {
1046
1220
  super();
1047
1221
  this._memory = {};
1222
+ this.debug = false;
1048
1223
  this._functionsRegistry = {};
1049
1224
  this.registerVisitor(RootAST, this.visitRootAST);
1050
1225
  this.registerVisitor(BlockStatementAST, this.visitBlockStatementAST);
@@ -1061,8 +1236,17 @@ class MEvento extends NodeVisitor {
1061
1236
  this.registerVisitor(ObjectProperty, this.visitObjectProperty);
1062
1237
  this.registerVisitor(ObjectExpression, this.visitObjectExpression);
1063
1238
  this.registerVisitor(ArrayExpression, this.visitArrayExpression);
1239
+ this.registerVisitor(WhileLoopStatement, this.visitWhileLoopStatement);
1240
+ this.registerVisitor(ForLoopStatement, this.visitForLoopStatement);
1241
+ this.registerVisitor(ForOfStatement, this.visitForOfStatement);
1242
+ this.registerVisitor(BreakAST, this.visitBreakAST);
1064
1243
  this._functionsRegistry = { ...MEvento._globalFunctionsRegistry };
1065
1244
  }
1245
+ log(message) {
1246
+ if (this.debug) {
1247
+ console.log(message);
1248
+ }
1249
+ }
1066
1250
  visitRootAST(node) {
1067
1251
  const list = node.body;
1068
1252
  let last;
@@ -1219,7 +1403,7 @@ class MEvento extends NodeVisitor {
1219
1403
  if (testBoolValue) {
1220
1404
  return this.visit(node.consequent);
1221
1405
  }
1222
- if (node.alternate !== null) {
1406
+ if (node.alternate) {
1223
1407
  return this.visit(node.alternate);
1224
1408
  }
1225
1409
  return null;
@@ -1267,6 +1451,85 @@ class MEvento extends NodeVisitor {
1267
1451
  const args = this.resolveArguments(node.elements);
1268
1452
  return args;
1269
1453
  }
1454
+ visitBreakAST(node) {
1455
+ return new BreakBranch();
1456
+ }
1457
+ visitWhileLoopStatement(node) {
1458
+ this.log(`WhileLoopStatement ${node.test} ${node.body}`);
1459
+ const retainer = node.retain ? [] : undefined;
1460
+ while (_boolValue(this.visit(node.test))) {
1461
+ const ret = this.visit(node.body);
1462
+ if (ret instanceof BreakBranch) {
1463
+ break;
1464
+ }
1465
+ retainer?.push(ret);
1466
+ }
1467
+ return retainer || null;
1468
+ }
1469
+ visitForLoopStatement(node) {
1470
+ const retainer = node.retain ? [] : undefined;
1471
+ const loopIdentifier = node.init.identifier;
1472
+ if (!(loopIdentifier instanceof IdentifierAST))
1473
+ throw new Error("Unexpected identifer found");
1474
+ const initialValue = this.visit(node.init.init);
1475
+ this._memory[loopIdentifier.value] = initialValue;
1476
+ retainer?.push(initialValue);
1477
+ const test = () => {
1478
+ const ret = this.visit(node.test);
1479
+ if (isNum(ret)) {
1480
+ const tmp = this._memory[loopIdentifier.value];
1481
+ return node.direction.type === TokenType.up ? ret >= tmp : ret <= tmp;
1482
+ }
1483
+ return _boolValue(ret);
1484
+ };
1485
+ while (test()) {
1486
+ const ret = this.visit(node.body);
1487
+ if (ret instanceof BreakBranch) {
1488
+ break;
1489
+ }
1490
+ retainer?.push(ret);
1491
+ // update
1492
+ if (node.update instanceof LiteralAST && isNum(node.update.value)) {
1493
+ // auto handle
1494
+ const tmp = this._memory[loopIdentifier.value];
1495
+ if (!isNum(tmp))
1496
+ throw Error("Can update value");
1497
+ this._memory[loopIdentifier.value] = node.direction.type === TokenType.up ? tmp + node.update.value : tmp - node.update.value;
1498
+ }
1499
+ else {
1500
+ this.visit(node.update);
1501
+ }
1502
+ }
1503
+ return retainer || null;
1504
+ }
1505
+ visitForOfStatement(node) {
1506
+ const collection = this.visit(node.collection);
1507
+ if (!Array.isArray(collection)) {
1508
+ throw Error("Can iterate non array object");
1509
+ }
1510
+ const retainer = node.retain ? [] : undefined;
1511
+ for (const it of collection) {
1512
+ this._declareForIdentifier(node.identifier, it);
1513
+ const ret = this.visit(node.body);
1514
+ if (ret instanceof BreakBranch) {
1515
+ break;
1516
+ }
1517
+ retainer?.push(ret);
1518
+ }
1519
+ return retainer || null;
1520
+ }
1521
+ _declareForIdentifier(node, value) {
1522
+ if (node instanceof TupleExpression) {
1523
+ if (!Array.isArray(value)) {
1524
+ throw Error("Unable to make a tuple from non Array element");
1525
+ }
1526
+ this._memory[node.first.value] = value[0];
1527
+ this._memory[node.second.value] = value[1];
1528
+ null;
1529
+ }
1530
+ this._memory[node.value] = value;
1531
+ null;
1532
+ }
1270
1533
  resolveArguments(args) {
1271
1534
  return args.map((it) => {
1272
1535
  return this.visit(it);
@@ -1476,7 +1739,7 @@ class MEventoAsync extends MEvento {
1476
1739
  if (testBoolValue) {
1477
1740
  return await this.visit(node.consequent);
1478
1741
  }
1479
- if (node.alternate !== null) {
1742
+ if (node.alternate) {
1480
1743
  return await this.visit(node.alternate);
1481
1744
  }
1482
1745
  return null;
@@ -1524,6 +1787,70 @@ class MEventoAsync extends MEvento {
1524
1787
  const args = await this.resolveArgumentsAsync(node.elements);
1525
1788
  return args;
1526
1789
  }
1790
+ async visitWhileLoopStatement(node) {
1791
+ this.log(`WhileLoopStatement ${node.test} ${node.body}`);
1792
+ const retainer = node.retain ? [] : undefined;
1793
+ while (_boolValue(this.visit(node.test))) {
1794
+ const ret = await this.visit(node.body);
1795
+ if (ret instanceof BreakBranch) {
1796
+ break;
1797
+ }
1798
+ retainer?.push(ret);
1799
+ }
1800
+ return retainer;
1801
+ }
1802
+ async visitForLoopStatement(node) {
1803
+ const retainer = node.retain ? [] : undefined;
1804
+ const loopIdentifier = node.init.identifier;
1805
+ if (!(loopIdentifier instanceof IdentifierAST))
1806
+ throw new Error("Unexpected identifer found");
1807
+ const initialValue = this.visit(node.init.init);
1808
+ this._memory[loopIdentifier.value] = initialValue;
1809
+ retainer?.push(initialValue);
1810
+ const test = () => {
1811
+ const ret = this.visit(node.test);
1812
+ if (isNum(ret)) {
1813
+ const tmp = this._memory[loopIdentifier.value];
1814
+ return node.direction.type === TokenType.up ? ret >= tmp : ret <= tmp;
1815
+ }
1816
+ return _boolValue(ret);
1817
+ };
1818
+ while (test()) {
1819
+ const ret = await this.visit(node.body);
1820
+ if (ret instanceof BreakBranch) {
1821
+ break;
1822
+ }
1823
+ retainer?.push(ret);
1824
+ // update
1825
+ if (node.update instanceof LiteralAST && isNum(node.update.value)) {
1826
+ // auto handle
1827
+ const tmp = this._memory[loopIdentifier.value];
1828
+ if (!isNum(tmp))
1829
+ throw Error("Can update value");
1830
+ this._memory[loopIdentifier.value] = node.direction.type === TokenType.up ? tmp + node.update.value : tmp - node.update.value;
1831
+ }
1832
+ else {
1833
+ this.visit(node.update);
1834
+ }
1835
+ }
1836
+ return retainer;
1837
+ }
1838
+ async visitForOfStatement(node) {
1839
+ const collection = this.visit(node.collection);
1840
+ if (!Array.isArray(collection)) {
1841
+ throw Error("Can iterate non array object");
1842
+ }
1843
+ const retainer = node.retain ? [] : undefined;
1844
+ for (const it of collection) {
1845
+ this._declareForIdentifier(node.identifier, it);
1846
+ const ret = await this.visit(node.body);
1847
+ if (ret instanceof BreakBranch) {
1848
+ break;
1849
+ }
1850
+ retainer?.push(ret);
1851
+ }
1852
+ return retainer;
1853
+ }
1527
1854
  async resolveArgumentsAsync(args) {
1528
1855
  return await Promise.all(args.map(async (it) => {
1529
1856
  return await this.visit(it);
@@ -1545,9 +1872,6 @@ class MEventoAsync extends MEvento {
1545
1872
  return await mevento.visit(module);
1546
1873
  }
1547
1874
  static newInstance() {
1548
- // const lexer = Lexer(source);
1549
- // const parser = Parser(lexer);
1550
- // const module = parser.parse();
1551
1875
  return new MEventoAsync();
1552
1876
  }
1553
1877
  clone() {