vladx 1.3.2 → 1.5.1

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.
Files changed (43) hide show
  1. package/bin/vladx +4 -1
  2. package/examples/stdlib/ambiente.vx +8 -0
  3. package/examples/stdlib/archivio_extra.vx +11 -0
  4. package/examples/stdlib/asserzione.vx +11 -0
  5. package/examples/stdlib/client_web.vx +7 -0
  6. package/examples/stdlib/codifica.vx +8 -0
  7. package/examples/stdlib/collezioni.vx +11 -0
  8. package/examples/stdlib/compressione.vx +10 -0
  9. package/examples/stdlib/console.vx +14 -0
  10. package/examples/stdlib/cripto.vx +8 -0
  11. package/examples/stdlib/dati.vx +21 -0
  12. package/examples/stdlib/eventi.vx +10 -0
  13. package/examples/stdlib/json_extra.vx +7 -0
  14. package/examples/stdlib/matematica.vx +9 -0
  15. package/examples/stdlib/percorso.vx +9 -0
  16. package/examples/stdlib/processo.vx +9 -0
  17. package/examples/stdlib/server_web.vx +10 -0
  18. package/examples/stdlib/sql_helper.vx +7 -0
  19. package/examples/stdlib/tempo.vx +9 -0
  20. package/examples/stdlib/testo.vx +10 -0
  21. package/examples/stdlib/url.vx +11 -0
  22. package/examples/stdlib/validazione.vx +5 -0
  23. package/package.json +6 -2
  24. package/programs/1/index.vx +16 -4
  25. package/programs/main/index.vx +11 -8
  26. package/programs/main/passports/Alina.json +1 -0
  27. package/programs/main/passports/Tanya.json +1 -0
  28. package/programs/main/passports/vlad.json +1 -0
  29. package/programs/main/test_async.vx +25 -0
  30. package/programs/main/test_async_advanced.vx +35 -0
  31. package/programs/main/test_backend.vx +33 -0
  32. package/programs/tests/test_new_features.vx +53 -0
  33. package/programs/tests/test_stdlib.vx +26 -0
  34. package/programs/tests/test_templates.vx +8 -0
  35. package/src/cli/cli.js +8 -6
  36. package/src/interpreter/interpreter.js +388 -170
  37. package/src/lexer/lexer.js +5 -1
  38. package/src/lexer/tokens.js +9 -1
  39. package/src/parser/ast.js +59 -4
  40. package/src/parser/parser.js +152 -18
  41. package/src/repl/repl.js +5 -5
  42. package/src/stdlib/registry.js +301 -0
  43. /package/programs/main/passports/{Vlad.txt → Vlad.json} +0 -0
@@ -270,7 +270,11 @@ class Lexer {
270
270
  case ';': this.addToken(TokenType.PUNTO_VIRGOLA, ';'); break;
271
271
  case '.': this.addToken(TokenType.PUNTO, '.'); break;
272
272
  case ':': this.addToken(TokenType.DUE_PUNTI, ':'); break;
273
- case '?': this.addToken(TokenType.PUNTO_INTERROGATIVO, '?'); break;
273
+ case '?':
274
+ if (this.match('?')) this.addToken(TokenType.NULLISH, '??');
275
+ else if (this.match('.')) this.addToken(TokenType.OPTIONAL_CHAINING, '?.');
276
+ else this.addToken(TokenType.PUNTO_INTERROGATIVO, '?');
277
+ break;
274
278
 
275
279
  case '+':
276
280
  if (this.match('+')) this.addToken(TokenType.INCREMENTA, '++');
@@ -39,6 +39,9 @@ const TokenType = {
39
39
  ATTENDI: 'ATTENDI',
40
40
  INTERROMPI: 'INTERROMPI',
41
41
  CONTINUA: 'CONTINUA',
42
+ SCEGLI: 'SCEGLI',
43
+ CASO: 'CASO',
44
+ PREDEFINITO: 'PREDEFINITO',
42
45
 
43
46
  // Operators
44
47
  PIU: 'PIU',
@@ -62,6 +65,8 @@ const TokenType = {
62
65
  FRECCIA: 'FRECCIA',
63
66
  AND: 'AND',
64
67
  OR: 'OR',
68
+ NULLISH: 'NULLISH',
69
+ OPTIONAL_CHAINING: 'OPTIONAL_CHAINING',
65
70
 
66
71
  // Delimiters
67
72
  PARENTESI_APERTA: 'PARENTESI_APERTA',
@@ -116,7 +121,10 @@ const KEYWORDS = {
116
121
  'asincrono': TokenType.ASINCRONO,
117
122
  'attendi': TokenType.ATTENDI,
118
123
  'interrompi': TokenType.INTERROMPI,
119
- 'continua': TokenType.CONTINUA
124
+ 'continua': TokenType.CONTINUA,
125
+ 'scegli': TokenType.SCEGLI,
126
+ 'caso': TokenType.CASO,
127
+ 'predefinito': TokenType.PREDEFINITO
120
128
  };
121
129
 
122
130
  module.exports = { TokenType, KEYWORDS };
package/src/parser/ast.js CHANGED
@@ -27,12 +27,27 @@ class VariableDeclaration extends ASTNode {
27
27
  }
28
28
  }
29
29
 
30
+ class ArrayPattern extends ASTNode {
31
+ constructor(elements) {
32
+ super('ArrayPattern');
33
+ this.elements = elements;
34
+ }
35
+ }
36
+
37
+ class ObjectPattern extends ASTNode {
38
+ constructor(properties) {
39
+ super('ObjectPattern');
40
+ this.properties = properties;
41
+ }
42
+ }
43
+
30
44
  class FunctionDeclaration extends ASTNode {
31
- constructor(name, params, body) {
45
+ constructor(name, params, body, isAsync = false) {
32
46
  super('FunctionDeclaration');
33
47
  this.name = name;
34
48
  this.params = params;
35
49
  this.body = body;
50
+ this.isAsync = isAsync;
36
51
  }
37
52
  }
38
53
 
@@ -60,6 +75,13 @@ class NewExpression extends ASTNode {
60
75
  }
61
76
  }
62
77
 
78
+ class AwaitExpression extends ASTNode {
79
+ constructor(argument) {
80
+ super('AwaitExpression');
81
+ this.argument = argument;
82
+ }
83
+ }
84
+
63
85
  // === Statements ===
64
86
  class BlockStatement extends ASTNode {
65
87
  constructor(body) {
@@ -68,6 +90,22 @@ class BlockStatement extends ASTNode {
68
90
  }
69
91
  }
70
92
 
93
+ class SwitchStatement extends ASTNode {
94
+ constructor(discriminant, cases) {
95
+ super('SwitchStatement');
96
+ this.discriminant = discriminant;
97
+ this.cases = cases;
98
+ }
99
+ }
100
+
101
+ class SwitchCase extends ASTNode {
102
+ constructor(test, consequent) {
103
+ super('SwitchCase');
104
+ this.test = test; // null se predefinito
105
+ this.consequent = consequent;
106
+ }
107
+ }
108
+
71
109
  class IfStatement extends ASTNode {
72
110
  constructor(condition, consequent, alternate = null) {
73
111
  super('IfStatement');
@@ -254,19 +292,21 @@ class CallExpression extends ASTNode {
254
292
  }
255
293
 
256
294
  class MemberExpression extends ASTNode {
257
- constructor(object, property, computed = false) {
295
+ constructor(object, property, computed = false, optional = false) {
258
296
  super('MemberExpression');
259
297
  this.object = object;
260
298
  this.property = property;
261
299
  this.computed = computed;
300
+ this.optional = optional;
262
301
  }
263
302
  }
264
303
 
265
304
  class ArrowFunction extends ASTNode {
266
- constructor(params, body) {
305
+ constructor(params, body, isAsync = false) {
267
306
  super('ArrowFunction');
268
307
  this.params = params;
269
308
  this.body = body;
309
+ this.isAsync = isAsync;
270
310
  }
271
311
  }
272
312
 
@@ -279,6 +319,15 @@ class UpdateExpression extends ASTNode {
279
319
  }
280
320
  }
281
321
 
322
+ class ConditionalExpression extends ASTNode {
323
+ constructor(test, consequent, alternate) {
324
+ super('ConditionalExpression');
325
+ this.test = test;
326
+ this.consequent = consequent;
327
+ this.alternate = alternate;
328
+ }
329
+ }
330
+
282
331
  class LogicalExpression extends ASTNode {
283
332
  constructor(operator, left, right) {
284
333
  super('LogicalExpression');
@@ -350,5 +399,11 @@ module.exports = {
350
399
  LogicalExpression,
351
400
  ThisExpression,
352
401
  NewExpression,
353
- TemplateLiteral
402
+ TemplateLiteral,
403
+ AwaitExpression,
404
+ SwitchStatement,
405
+ SwitchCase,
406
+ ConditionalExpression,
407
+ ArrayPattern,
408
+ ObjectPattern
354
409
  };
@@ -73,7 +73,13 @@ class Parser {
73
73
  if (this.match(TokenType.ESPORTA)) return this.exportDeclaration();
74
74
  if (this.match(TokenType.VARIABILE)) return this.variableDeclaration(false);
75
75
  if (this.match(TokenType.COSTANTE)) return this.variableDeclaration(true);
76
- if (this.match(TokenType.FUNZIONE)) return this.functionDeclaration();
76
+
77
+ if (this.match(TokenType.ASINCRONO)) {
78
+ this.consume(TokenType.FUNZIONE, 'Atteso "funzione" dopo "asincrono"');
79
+ return this.functionDeclaration(true);
80
+ }
81
+
82
+ if (this.match(TokenType.FUNZIONE)) return this.functionDeclaration(false);
77
83
  if (this.match(TokenType.CLASSE)) return this.classDeclaration();
78
84
  return this.statement();
79
85
  } catch (error) {
@@ -83,6 +89,34 @@ class Parser {
83
89
  }
84
90
 
85
91
  variableDeclaration(isConstant) {
92
+ if (this.match(TokenType.QUADRA_APERTA)) {
93
+ const elements = [];
94
+ if (!this.check(TokenType.QUADRA_CHIUSA)) {
95
+ do {
96
+ elements.push(this.consume(TokenType.IDENTIFICATORE, 'Nome variabile atteso in destrutturazione array').value);
97
+ } while (this.match(TokenType.VIRGOLA));
98
+ }
99
+ this.consume(TokenType.QUADRA_CHIUSA, 'Atteso "]" dopo destrutturazione array');
100
+ this.consume(TokenType.ASSEGNA, 'Inizializzazione richiesta per destrutturazione');
101
+ const value = this.expression();
102
+ this.match(TokenType.PUNTO_VIRGOLA);
103
+ return new AST.VariableDeclaration(new AST.ArrayPattern(elements), value, isConstant);
104
+ }
105
+
106
+ if (this.match(TokenType.GRAFFA_APERTA)) {
107
+ const properties = [];
108
+ if (!this.check(TokenType.GRAFFA_CHIUSA)) {
109
+ do {
110
+ properties.push(this.consume(TokenType.IDENTIFICATORE, 'Nome proprietà atteso in destrutturazione oggetto').value);
111
+ } while (this.match(TokenType.VIRGOLA));
112
+ }
113
+ this.consume(TokenType.GRAFFA_CHIUSA, 'Atteso "}" dopo destrutturazione oggetto');
114
+ this.consume(TokenType.ASSEGNA, 'Inizializzazione richiesta per destrutturazione');
115
+ const value = this.expression();
116
+ this.match(TokenType.PUNTO_VIRGOLA);
117
+ return new AST.VariableDeclaration(new AST.ObjectPattern(properties), value, isConstant);
118
+ }
119
+
86
120
  const name = this.consume(TokenType.IDENTIFICATORE, 'Nome variabile atteso').value;
87
121
  let value = null;
88
122
  if (this.match(TokenType.ASSEGNA)) {
@@ -97,20 +131,24 @@ class Parser {
97
131
  const specifiers = [];
98
132
  if (!this.check(TokenType.GRAFFA_CHIUSA)) {
99
133
  do {
100
- const name = this.consume(TokenType.IDENTIFICATORE, 'Nome import atteso').value;
101
- specifiers.push(name);
134
+ specifiers.push(this.consume(TokenType.IDENTIFICATORE, 'Nome simbolo atteso').value);
102
135
  } while (this.match(TokenType.VIRGOLA));
103
136
  }
104
- this.consume(TokenType.GRAFFA_CHIUSA, 'Atteso "}" dopo i nomi importati');
105
- this.consume(TokenType.DA, 'Attesa parola chiave "da" dopo gli import');
106
- const source = this.consume(TokenType.STRINGA, 'Percorso modulo atteso come stringa').value;
137
+ this.consume(TokenType.GRAFFA_CHIUSA, 'Atteso "}" dopo i simboli');
138
+ this.consume(TokenType.DA, 'Atteso "da" dopo i simboli importati');
139
+ const source = this.consume(TokenType.STRINGA, 'Atteso percorso modulo').value;
107
140
  this.match(TokenType.PUNTO_VIRGOLA);
108
141
  return new AST.ImportDeclaration(specifiers, source);
109
142
  }
110
143
 
111
144
  exportDeclaration() {
145
+ if (this.match(TokenType.ASINCRONO)) {
146
+ this.consume(TokenType.FUNZIONE, 'Atteso "funzione" dopo "asincrono"');
147
+ const decl = this.functionDeclaration(true);
148
+ return new AST.ExportNamedDeclaration(decl);
149
+ }
112
150
  if (this.match(TokenType.FUNZIONE)) {
113
- const decl = this.functionDeclaration();
151
+ const decl = this.functionDeclaration(false);
114
152
  return new AST.ExportNamedDeclaration(decl);
115
153
  }
116
154
  if (this.match(TokenType.CLASSE)) {
@@ -128,7 +166,7 @@ class Parser {
128
166
  throw new ParserError('Atteso funzione, classe o variabile dopo "esporta"', this.peek());
129
167
  }
130
168
 
131
- functionDeclaration() {
169
+ functionDeclaration(isAsync = false) {
132
170
  const name = this.consume(TokenType.IDENTIFICATORE, 'Nome funzione atteso').value;
133
171
  this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo nome funzione');
134
172
  const params = [];
@@ -140,7 +178,7 @@ class Parser {
140
178
  this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo parametri');
141
179
  this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" prima del corpo funzione');
142
180
  const body = this.blockStatement();
143
- return new AST.FunctionDeclaration(name, params, body);
181
+ return new AST.FunctionDeclaration(name, params, body, isAsync);
144
182
  }
145
183
 
146
184
  classDeclaration() {
@@ -164,6 +202,11 @@ class Parser {
164
202
  const methods = [];
165
203
 
166
204
  while (!this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
205
+ let isAsync = false;
206
+ if (this.match(TokenType.ASINCRONO)) {
207
+ isAsync = true;
208
+ }
209
+
167
210
  if (this.match(TokenType.FUNZIONE)) {
168
211
  const funcName = this.consume(TokenType.IDENTIFICATORE, 'Nome metodo atteso').value;
169
212
  this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo nome metodo');
@@ -178,11 +221,13 @@ class Parser {
178
221
  const body = this.blockStatement();
179
222
 
180
223
  if (funcName === 'costruttore') {
181
- constructor = new AST.FunctionDeclaration('costruttore', params, body);
224
+ if (isAsync) throw new ParserError('Il costruttore non può essere asincrono', this.previous());
225
+ constructor = new AST.FunctionDeclaration('costruttore', params, body, false);
182
226
  } else {
183
- methods.push(new AST.FunctionDeclaration(funcName, params, body));
227
+ methods.push(new AST.FunctionDeclaration(funcName, params, body, isAsync));
184
228
  }
185
229
  } else {
230
+ if (isAsync) throw new ParserError('Atteso metodo dopo "asincrono"', this.peek());
186
231
  throw new ParserError('Atteso metodo nella classe', this.peek());
187
232
  }
188
233
  }
@@ -193,6 +238,7 @@ class Parser {
193
238
 
194
239
  statement() {
195
240
  if (this.match(TokenType.SE)) return this.ifStatement();
241
+ if (this.match(TokenType.SCEGLI)) return this.switchStatement();
196
242
  if (this.match(TokenType.MENTRE)) return this.whileStatement();
197
243
  if (this.match(TokenType.PER)) return this.forStatement();
198
244
  if (this.match(TokenType.RITORNA)) return this.returnStatement();
@@ -205,6 +251,38 @@ class Parser {
205
251
  return this.expressionStatement();
206
252
  }
207
253
 
254
+ switchStatement() {
255
+ this.consume(TokenType.PARENTESI_APERTA, 'Atteso "(" dopo "scegli"');
256
+ const discriminant = this.expression();
257
+ this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo discriminante');
258
+ this.consume(TokenType.GRAFFA_APERTA, 'Atteso "{" dopo "scegli"');
259
+
260
+ const cases = [];
261
+ while (!this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
262
+ if (this.match(TokenType.CASO)) {
263
+ const test = this.expression();
264
+ this.consume(TokenType.DUE_PUNTI, 'Atteso ":" dopo il caso');
265
+ const consequent = [];
266
+ while (!this.check(TokenType.CASO) && !this.check(TokenType.PREDEFINITO) && !this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
267
+ consequent.push(this.declaration());
268
+ }
269
+ cases.push(new AST.SwitchCase(test, consequent));
270
+ } else if (this.match(TokenType.PREDEFINITO)) {
271
+ this.consume(TokenType.DUE_PUNTI, 'Atteso ":" dopo "predefinito"');
272
+ const consequent = [];
273
+ while (!this.check(TokenType.CASO) && !this.check(TokenType.PREDEFINITO) && !this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
274
+ consequent.push(this.declaration());
275
+ }
276
+ cases.push(new AST.SwitchCase(null, consequent));
277
+ } else {
278
+ throw new ParserError('Atteso "caso" o "predefinito" all\'interno di "scegli"', this.peek());
279
+ }
280
+ }
281
+
282
+ this.consume(TokenType.GRAFFA_CHIUSA, 'Atteso "}" dopo "scegli"');
283
+ return new AST.SwitchStatement(discriminant, cases);
284
+ }
285
+
208
286
  blockStatement() {
209
287
  const statements = [];
210
288
  while (!this.check(TokenType.GRAFFA_CHIUSA) && !this.isAtEnd()) {
@@ -342,7 +420,7 @@ class Parser {
342
420
  }
343
421
 
344
422
  assignment() {
345
- const expr = this.logicalOr();
423
+ const expr = this.conditional();
346
424
 
347
425
  if (this.match(TokenType.ASSEGNA, TokenType.PIU_ASSEGNA, TokenType.MENO_ASSEGNA)) {
348
426
  const operator = this.previous().value;
@@ -353,18 +431,42 @@ class Parser {
353
431
  return expr;
354
432
  }
355
433
 
434
+ conditional() {
435
+ let expr = this.logicalOr();
436
+
437
+ if (this.match(TokenType.PUNTO_INTERROGATIVO)) {
438
+ const consequent = this.expression();
439
+ this.consume(TokenType.DUE_PUNTI, 'Atteso ":" dopo espressione del ternario');
440
+ const alternate = this.conditional();
441
+ return new AST.ConditionalExpression(expr, consequent, alternate);
442
+ }
443
+
444
+ return expr;
445
+ }
446
+
356
447
  logicalOr() {
357
- let expr = this.logicalAnd();
448
+ let expr = this.nullishCoalescing();
358
449
 
359
450
  while (this.match(TokenType.O, TokenType.OR)) {
360
451
  const operator = '||';
361
- const right = this.logicalAnd();
452
+ const right = this.nullishCoalescing();
362
453
  expr = new AST.LogicalExpression(operator, expr, right);
363
454
  }
364
455
 
365
456
  return expr;
366
457
  }
367
458
 
459
+ nullishCoalescing() {
460
+ let expr = this.logicalAnd();
461
+
462
+ while (this.match(TokenType.NULLISH)) {
463
+ const right = this.logicalAnd();
464
+ expr = new AST.LogicalExpression('??', expr, right);
465
+ }
466
+
467
+ return expr;
468
+ }
469
+
368
470
  logicalAnd() {
369
471
  let expr = this.equality();
370
472
 
@@ -426,6 +528,11 @@ class Parser {
426
528
  }
427
529
 
428
530
  unary() {
531
+ if (this.match(TokenType.ATTENDI)) {
532
+ const argument = this.unary();
533
+ return new AST.AwaitExpression(argument);
534
+ }
535
+
429
536
  if (this.match(TokenType.NON, TokenType.MENO)) {
430
537
  const operator = this.previous().value === 'non' ? '!' : this.previous().value;
431
538
  const argument = this.unary();
@@ -454,11 +561,14 @@ class Parser {
454
561
  expr = this.finishCall(expr);
455
562
  } else if (this.match(TokenType.PUNTO)) {
456
563
  const property = this.consume(TokenType.IDENTIFICATORE, 'Nome proprietà atteso dopo "."');
457
- expr = new AST.MemberExpression(expr, new AST.Identifier(property.value), false);
564
+ expr = new AST.MemberExpression(expr, new AST.Identifier(property.value), false, false);
565
+ } else if (this.match(TokenType.OPTIONAL_CHAINING)) {
566
+ const property = this.consume(TokenType.IDENTIFICATORE, 'Nome proprietà atteso dopo "?."');
567
+ expr = new AST.MemberExpression(expr, new AST.Identifier(property.value), false, true);
458
568
  } else if (this.match(TokenType.QUADRA_APERTA)) {
459
569
  const property = this.expression();
460
570
  this.consume(TokenType.QUADRA_CHIUSA, 'Atteso "]" dopo indice');
461
- expr = new AST.MemberExpression(expr, property, true);
571
+ expr = new AST.MemberExpression(expr, property, true, false);
462
572
  } else {
463
573
  break;
464
574
  }
@@ -548,6 +658,30 @@ class Parser {
548
658
  return this.objectLiteral();
549
659
  }
550
660
 
661
+ if (this.match(TokenType.ASINCRONO)) {
662
+ // Async Arrow Function: asincrono (param) => ...
663
+ if (this.match(TokenType.PARENTESI_APERTA)) {
664
+ const params = [];
665
+ if (!this.check(TokenType.PARENTESI_CHIUSA)) {
666
+ do {
667
+ params.push(this.consume(TokenType.IDENTIFICATORE, 'Nome parametro atteso').value);
668
+ } while (this.match(TokenType.VIRGOLA));
669
+ }
670
+ this.consume(TokenType.PARENTESI_CHIUSA, 'Atteso ")" dopo parametri');
671
+
672
+ if (this.match(TokenType.FRECCIA)) {
673
+ if (this.match(TokenType.GRAFFA_APERTA)) {
674
+ const body = this.blockStatement();
675
+ return new AST.ArrowFunction(params, body, true);
676
+ } else {
677
+ const body = this.expression();
678
+ return new AST.ArrowFunction(params, body, true);
679
+ }
680
+ }
681
+ }
682
+ throw new ParserError('Atteso funzione freccia asincrona', this.peek());
683
+ }
684
+
551
685
  if (this.match(TokenType.PARENTESI_APERTA)) {
552
686
  // Potrebbe essere una arrow function o un'espressione raggruppata
553
687
  const startPos = this.current - 1;
@@ -573,10 +707,10 @@ class Parser {
573
707
  // È una arrow function
574
708
  if (this.match(TokenType.GRAFFA_APERTA)) {
575
709
  const body = this.blockStatement();
576
- return new AST.ArrowFunction(params, body);
710
+ return new AST.ArrowFunction(params, body, false);
577
711
  } else {
578
712
  const body = this.expression();
579
- return new AST.ArrowFunction(params, body);
713
+ return new AST.ArrowFunction(params, body, false);
580
714
  }
581
715
  } else {
582
716
  // Non è una arrow function, torna indietro
package/src/repl/repl.js CHANGED
@@ -48,7 +48,7 @@ class REPL {
48
48
 
49
49
  rl.prompt();
50
50
 
51
- rl.on('line', (line) => {
51
+ rl.on('line', async (line) => {
52
52
  const trimmed = line.trim();
53
53
 
54
54
  // Handle special commands
@@ -92,7 +92,7 @@ class REPL {
92
92
 
93
93
  if (code) {
94
94
  this.history.push(code);
95
- this.execute(code);
95
+ await this.execute(code);
96
96
  }
97
97
 
98
98
  rl.setPrompt(colorize('vladx> ', 'green'));
@@ -105,7 +105,7 @@ class REPL {
105
105
  });
106
106
  }
107
107
 
108
- execute(code) {
108
+ async execute(code) {
109
109
  try {
110
110
  const lexer = new Lexer(code);
111
111
  const tokens = lexer.tokenize();
@@ -113,7 +113,7 @@ class REPL {
113
113
  const parser = new Parser(tokens);
114
114
  const ast = parser.parse();
115
115
 
116
- const result = this.interpreter.interpret(ast);
116
+ const result = await this.interpreter.interpret(ast);
117
117
 
118
118
  // Show result if it's not just print statements
119
119
  if (result.length === 0 && ast.body.length > 0) {
@@ -130,7 +130,7 @@ class REPL {
130
130
  tempInterpreter.environment = this.interpreter.environment;
131
131
 
132
132
  try {
133
- const value = tempInterpreter.evaluate(lastStmt.expression);
133
+ const value = await tempInterpreter.evaluate(lastStmt.expression);
134
134
  if (value !== undefined && value !== null) {
135
135
  console.log(colorize('→ ', 'dim') + colorize(this.interpreter.stringify(value), 'yellow'));
136
136
  }