starlight-cli 1.0.24 → 1.0.26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starlight-cli",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "Starlight Programming Language CLI",
5
5
  "bin": {
6
6
  "starlight": "index.js"
package/src/evaluator.js CHANGED
@@ -73,63 +73,100 @@ class Evaluator {
73
73
  }
74
74
  return n;
75
75
  });
76
+ this.global.define('fetch', async (url, options = {}) => {
77
+ const res = await fetch(url, options);
78
+ return {
79
+ status: res.status,
80
+ ok: res.ok,
81
+ text: async () => await res.text(),
82
+ json: async () => await res.json()
83
+ };
84
+ });
85
+
86
+ // GET request
87
+ this.global.define('get', async (url) => {
88
+ const res = await fetch(url);
89
+ return await res.json();
90
+ });
76
91
 
92
+ this.global.define('post', async (url, data) => {
93
+ const res = await fetch(url, {
94
+ method: 'POST',
95
+ headers: { 'Content-Type': 'application/json' },
96
+ body: JSON.stringify(data)
97
+ });
98
+ return await res.json();
99
+ });
100
+
101
+ this.global.define('sleep', async (ms) => {
102
+ return new Promise(resolve => setTimeout(resolve, ms));
103
+ });
77
104
  this.global.define('str', arg => {
78
105
  return String(arg);
79
106
  });
80
107
 
81
108
  }
82
109
 
83
-
84
- evaluate(node, env = this.global) {
85
- switch (node.type) {
86
- case 'Program': return this.evalProgram(node, env);
87
- case 'BlockStatement': return this.evalBlock(node, new Environment(env));
88
- case 'VarDeclaration': return this.evalVarDeclaration(node, env);
89
- case 'AssignmentExpression': return this.evalAssignment(node, env);
90
- case 'CompoundAssignment': return this.evalCompoundAssignment(node, env);
91
- case 'SldeployStatement': return this.evalSldeploy(node, env);
92
- case 'AskStatement': return this.evalAsk(node, env);
93
- case 'DefineStatement': return this.evalDefine(node, env);
94
- case 'ExpressionStatement': return this.evaluate(node.expression, env);
95
- case 'BinaryExpression': return this.evalBinary(node, env);
96
- case 'LogicalExpression': return this.evalLogical(node, env);
97
- case 'UnaryExpression': return this.evalUnary(node, env);
98
- case 'Literal': return node.value;
99
- case 'Identifier': return env.get(node.name);
100
- case 'IfStatement': return this.evalIf(node, env);
101
- case 'WhileStatement': return this.evalWhile(node, env);
102
- case 'ForStatement': return this.evalFor(node, env);
103
- case 'BreakStatement': throw new BreakSignal();
104
- case 'ContinueStatement': throw new ContinueSignal();
105
- case 'ImportStatement': return this.evalImport(node, env);
106
- case 'FunctionDeclaration': return this.evalFunctionDeclaration(node, env);
107
- case 'CallExpression': return this.evalCall(node, env);
108
- case 'ArrowFunctionExpression':
109
- return this.evalArrowFunction(node, env);
110
-
111
- case 'ReturnStatement': {
112
- const val = node.argument ? this.evaluate(node.argument, env) : null;
113
- throw new ReturnValue(val);
110
+ async evaluate(node, env = this.global) {
111
+ switch (node.type) {
112
+ case 'Program': return await this.evalProgram(node, env);
113
+ case 'BlockStatement': return await this.evalBlock(node, new Environment(env));
114
+ case 'VarDeclaration': return await this.evalVarDeclaration(node, env);
115
+ case 'AssignmentExpression': return await this.evalAssignment(node, env);
116
+ case 'CompoundAssignment': return await this.evalCompoundAssignment(node, env);
117
+ case 'SldeployStatement': return await this.evalSldeploy(node, env);
118
+ case 'AskStatement': return await this.evalAsk(node, env);
119
+ case 'DefineStatement': return await this.evalDefine(node, env);
120
+ case 'ExpressionStatement': return await this.evaluate(node.expression, env);
121
+ case 'BinaryExpression': return await this.evalBinary(node, env);
122
+ case 'LogicalExpression': return await this.evalLogical(node, env);
123
+ case 'UnaryExpression': return await this.evalUnary(node, env);
124
+ case 'Literal': return node.value;
125
+ case 'Identifier': return env.get(node.name);
126
+ case 'IfStatement': return await this.evalIf(node, env);
127
+ case 'WhileStatement': return await this.evalWhile(node, env);
128
+ case 'ForStatement': return await this.evalFor(node, env);
129
+ case 'BreakStatement': throw new BreakSignal();
130
+ case 'ContinueStatement': throw new ContinueSignal();
131
+ case 'ImportStatement': return await this.evalImport(node, env);
132
+ case 'FunctionDeclaration': return this.evalFunctionDeclaration(node, env);
133
+ case 'CallExpression': return await this.evalCall(node, env);
134
+ case 'ArrowFunctionExpression': return this.evalArrowFunction(node, env);
135
+ case 'ReturnStatement': {
136
+ const val = node.argument ? await this.evaluate(node.argument, env) : null;
137
+ throw new ReturnValue(val);
138
+ }
139
+
140
+ case 'ArrayExpression':
141
+ return await Promise.all(node.elements.map(el => this.evaluate(el, env)));
142
+ case 'IndexExpression': return await this.evalIndex(node, env);
143
+ case 'ObjectExpression': {
144
+ const out = {};
145
+ for (const p of node.props) {
146
+ out[p.key] = await this.evaluate(p.value, env);
114
147
  }
115
- case 'ArrayExpression': return node.elements.map(el => this.evaluate(el, env));
116
- case 'IndexExpression': return this.evalIndex(node, env);
117
- case 'ObjectExpression': return this.evalObject(node, env);
118
- case 'MemberExpression': return this.evalMember(node, env);
119
- case 'UpdateExpression': return this.evalUpdate(node, env);
120
- default:
121
- throw new Error(`Unknown node type in evaluator: ${node.type}`);
148
+ return out;
122
149
  }
150
+ case 'MemberExpression': return await this.evalMember(node, env);
151
+ case 'UpdateExpression': return await this.evalUpdate(node, env);
152
+ case 'AwaitExpression': {
153
+ const val = await this.evaluate(node.argument, env);
154
+ return val;
155
+ }
156
+ default:
157
+ throw new Error(`Unknown node type in evaluator: ${node.type}`);
123
158
  }
159
+ }
124
160
 
125
- evalProgram(node, env) {
126
- let result = null;
127
- for (const stmt of node.body) {
128
- result = this.evaluate(stmt, env);
129
- }
130
- return result;
161
+ async evalProgram(node, env) {
162
+ let result = null;
163
+ for (const stmt of node.body) {
164
+ result = await this.evaluate(stmt, env);
131
165
  }
132
- evalImport(node, env) {
166
+ return result;
167
+ }
168
+
169
+ async evalImport(node, env) {
133
170
  const spec = node.path;
134
171
  let lib;
135
172
 
@@ -152,7 +189,7 @@ evalImport(node, env) {
152
189
  const ast = new Parser(tokens).parse();
153
190
 
154
191
  const moduleEnv = new Environment(env);
155
- this.evaluate(ast, moduleEnv);
192
+ await this.evaluate(ast, moduleEnv);
156
193
 
157
194
  lib = {};
158
195
  for (const key of Object.keys(moduleEnv.store)) {
@@ -180,259 +217,265 @@ evalImport(node, env) {
180
217
  return null;
181
218
  }
182
219
 
183
-
184
- evalBlock(node, env) {
185
- let result = null;
186
- for (const stmt of node.body) {
187
- try {
188
- result = this.evaluate(stmt, env);
189
- } catch (e) {
190
- if (e instanceof ReturnValue || e instanceof BreakSignal || e instanceof ContinueSignal) throw e;
191
- throw e;
192
- }
220
+ async evalBlock(node, env) {
221
+ let result = null;
222
+ for (const stmt of node.body) {
223
+ try {
224
+ result = await this.evaluate(stmt, env);
225
+ } catch (e) {
226
+ if (e instanceof ReturnValue || e instanceof BreakSignal || e instanceof ContinueSignal) throw e;
227
+ throw e;
193
228
  }
194
- return result;
195
229
  }
230
+ return result;
231
+ }
232
+
233
+ async evalVarDeclaration(node, env) {
234
+ const val = await this.evaluate(node.expr, env);
235
+ return env.define(node.id, val);
236
+ }
196
237
 
197
- evalVarDeclaration(node, env) {
198
- const val = this.evaluate(node.expr, env);
199
- return env.define(node.id, val);
200
- }
201
238
  evalArrowFunction(node, env) {
202
239
  return {
203
240
  params: node.params,
204
241
  body: node.body,
205
242
  env: env,
206
- arrow: true
243
+ arrow: true,
244
+ async: node.async || false
207
245
  };
208
246
  }
209
247
 
210
- evalAssignment(node, env) {
211
- const rightVal = this.evaluate(node.right, env);
212
- const left = node.left;
213
-
214
- if (left.type === 'Identifier') return env.set(left.name, rightVal);
215
- if (left.type === 'MemberExpression') {
216
- const obj = this.evaluate(left.object, env);
217
- obj[left.property] = rightVal;
218
- return rightVal;
219
- }
220
- if (left.type === 'IndexExpression') {
221
- const obj = this.evaluate(left.object, env);
222
- const idx = this.evaluate(left.indexer, env);
223
- obj[idx] = rightVal;
224
- return rightVal;
225
- }
248
+ async evalAssignment(node, env) {
249
+ const rightVal = await this.evaluate(node.right, env);
250
+ const left = node.left;
226
251
 
227
- throw new Error('Invalid assignment target');
252
+ if (left.type === 'Identifier') return env.set(left.name, rightVal);
253
+ if (left.type === 'MemberExpression') {
254
+ const obj = await this.evaluate(left.object, env);
255
+ obj[left.property] = rightVal;
256
+ return rightVal;
228
257
  }
229
-
230
- evalCompoundAssignment(node, env) {
231
- const left = node.left;
232
- let current;
233
-
234
- if (left.type === 'Identifier') current = env.get(left.name);
235
- else if (left.type === 'MemberExpression') current = this.evalMember(left, env);
236
- else if (left.type === 'IndexExpression') current = this.evalIndex(left, env);
237
- else throw new Error('Invalid compound assignment target');
238
-
239
- const rhs = this.evaluate(node.right, env);
240
- let computed;
241
- switch (node.operator) {
242
- case 'PLUSEQ': computed = current + rhs; break;
243
- case 'MINUSEQ': computed = current - rhs; break;
244
- case 'STAREQ': computed = current * rhs; break;
245
- case 'SLASHEQ': computed = current / rhs; break;
246
- case 'MODEQ': computed = current % rhs; break;
247
- default: throw new Error('Unknown compound operator');
248
- }
249
-
250
- if (left.type === 'Identifier') env.set(left.name, computed);
251
- else if (left.type === 'MemberExpression') this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
252
- else this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
253
-
254
- return computed;
258
+ if (left.type === 'IndexExpression') {
259
+ const obj = await this.evaluate(left.object, env);
260
+ const idx = await this.evaluate(left.indexer, env);
261
+ obj[idx] = rightVal;
262
+ return rightVal;
255
263
  }
256
264
 
257
- evalSldeploy(node, env) {
258
- const val = this.evaluate(node.expr, env);
259
- console.log(val);
260
- return val;
261
- }
265
+ throw new Error('Invalid assignment target');
266
+ }
262
267
 
263
- evalAsk(node, env) {
264
- const prompt = this.evaluate(node.prompt, env);
265
- const input = readlineSync.question(prompt + ' ');
266
- return input;
268
+ async evalCompoundAssignment(node, env) {
269
+ const left = node.left;
270
+ let current;
271
+
272
+ if (left.type === 'Identifier') current = env.get(left.name);
273
+ else if (left.type === 'MemberExpression') current = await this.evalMember(left, env);
274
+ else if (left.type === 'IndexExpression') current = await this.evalIndex(left, env);
275
+ else throw new Error('Invalid compound assignment target');
276
+
277
+ const rhs = await this.evaluate(node.right, env);
278
+ let computed;
279
+ switch (node.operator) {
280
+ case 'PLUSEQ': computed = current + rhs; break;
281
+ case 'MINUSEQ': computed = current - rhs; break;
282
+ case 'STAREQ': computed = current * rhs; break;
283
+ case 'SLASHEQ': computed = current / rhs; break;
284
+ case 'MODEQ': computed = current % rhs; break;
285
+ default: throw new Error('Unknown compound operator');
267
286
  }
268
287
 
269
- evalDefine(node, env) {
270
- const val = node.expr ? this.evaluate(node.expr, env) : null;
271
- return this.global.define(node.id, val);
272
- }
288
+ if (left.type === 'Identifier') env.set(left.name, computed);
289
+ else if (left.type === 'MemberExpression') await this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
290
+ else await this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
273
291
 
274
- evalBinary(node, env) {
275
- const l = this.evaluate(node.left, env);
276
- const r = this.evaluate(node.right, env);
292
+ return computed;
293
+ }
277
294
 
278
- if (node.operator === 'SLASH' && r === 0) {
279
- throw new Error('Division by zero');
280
- }
295
+ async evalSldeploy(node, env) {
296
+ const val = await this.evaluate(node.expr, env);
297
+ console.log(val);
298
+ return val;
299
+ }
281
300
 
282
- switch (node.operator) {
283
- case 'PLUS': return l + r;
284
- case 'MINUS': return l - r;
285
- case 'STAR': return l * r;
286
- case 'SLASH': return l / r;
287
- case 'MOD': return l % r;
288
- case 'EQEQ': return l === r;
289
- case 'NOTEQ': return l !== r;
290
- case 'LT': return l < r;
291
- case 'LTE': return l <= r;
292
- case 'GT': return l > r;
293
- case 'GTE': return l >= r;
294
- default: throw new Error(`Unknown binary operator ${node.operator}`);
295
- }
301
+ async evalAsk(node, env) {
302
+ const prompt = await this.evaluate(node.prompt, env);
303
+ const input = readlineSync.question(prompt + ' ');
304
+ return input;
305
+ }
306
+
307
+ async evalDefine(node, env) {
308
+ const val = node.expr ? await this.evaluate(node.expr, env) : null;
309
+ return this.global.define(node.id, val);
296
310
  }
297
311
 
312
+ async evalBinary(node, env) {
313
+ const l = await this.evaluate(node.left, env);
314
+ const r = await this.evaluate(node.right, env);
298
315
 
299
- evalLogical(node, env) {
300
- const l = this.evaluate(node.left, env);
301
- if (node.operator === 'AND') return l && this.evaluate(node.right, env);
302
- if (node.operator === 'OR') return l || this.evaluate(node.right, env);
303
- throw new Error(`Unknown logical operator ${node.operator}`);
316
+ if (node.operator === 'SLASH' && r === 0) {
317
+ throw new Error('Division by zero');
304
318
  }
305
319
 
306
- evalUnary(node, env) {
307
- const val = this.evaluate(node.argument, env);
308
- switch (node.operator) {
309
- case 'NOT': return !val;
310
- case 'MINUS': return -val;
311
- case 'PLUS': return +val;
312
- default: throw new Error(`Unknown unary operator ${node.operator}`);
313
- }
320
+ switch (node.operator) {
321
+ case 'PLUS': return l + r;
322
+ case 'MINUS': return l - r;
323
+ case 'STAR': return l * r;
324
+ case 'SLASH': return l / r;
325
+ case 'MOD': return l % r;
326
+ case 'EQEQ': return l === r;
327
+ case 'NOTEQ': return l !== r;
328
+ case 'LT': return l < r;
329
+ case 'LTE': return l <= r;
330
+ case 'GT': return l > r;
331
+ case 'GTE': return l >= r;
332
+ default: throw new Error(`Unknown binary operator ${node.operator}`);
314
333
  }
334
+ }
315
335
 
316
- evalIf(node, env) {
317
- const test = this.evaluate(node.test, env);
318
- if (test) return this.evaluate(node.consequent, env);
319
- if (node.alternate) return this.evaluate(node.alternate, env);
320
- return null;
336
+ async evalLogical(node, env) {
337
+ const l = await this.evaluate(node.left, env);
338
+ if (node.operator === 'AND') return l && await this.evaluate(node.right, env);
339
+ if (node.operator === 'OR') return l || await this.evaluate(node.right, env);
340
+ throw new Error(`Unknown logical operator ${node.operator}`);
341
+ }
342
+
343
+ async evalUnary(node, env) {
344
+ const val = await this.evaluate(node.argument, env);
345
+ switch (node.operator) {
346
+ case 'NOT': return !val;
347
+ case 'MINUS': return -val;
348
+ case 'PLUS': return +val;
349
+ default: throw new Error(`Unknown unary operator ${node.operator}`);
321
350
  }
351
+ }
322
352
 
323
- evalWhile(node, env) {
324
- while (this.evaluate(node.test, env)) {
325
- try { this.evaluate(node.body, env); }
326
- catch (e) {
327
- if (e instanceof BreakSignal) break;
328
- if (e instanceof ContinueSignal) continue;
329
- throw e;
330
- }
353
+ async evalIf(node, env) {
354
+ const test = await this.evaluate(node.test, env);
355
+ if (test) return await this.evaluate(node.consequent, env);
356
+ if (node.alternate) return await this.evaluate(node.alternate, env);
357
+ return null;
358
+ }
359
+
360
+ async evalWhile(node, env) {
361
+ while (await this.evaluate(node.test, env)) {
362
+ try { await this.evaluate(node.body, env); }
363
+ catch (e) {
364
+ if (e instanceof BreakSignal) break;
365
+ if (e instanceof ContinueSignal) continue;
366
+ throw e;
331
367
  }
332
- return null;
333
368
  }
369
+ return null;
370
+ }
334
371
 
335
- evalFor(node, env) {
336
- const local = new Environment(env);
337
- if (node.init) this.evaluate(node.init, local);
338
- while (!node.test || this.evaluate(node.test, local)) {
339
- try { this.evaluate(node.body, local); }
340
- catch (e) {
341
- if (e instanceof BreakSignal) break;
342
- if (e instanceof ContinueSignal) { if (node.update) this.evaluate(node.update, local); continue; }
343
- throw e;
372
+ async evalFor(node, env) {
373
+ const local = new Environment(env);
374
+ if (node.init) await this.evaluate(node.init, local);
375
+ while (!node.test || await this.evaluate(node.test, local)) {
376
+ try { await this.evaluate(node.body, local); }
377
+ catch (e) {
378
+ if (e instanceof BreakSignal) break;
379
+ if (e instanceof ContinueSignal) {
380
+ if (node.update) await this.evaluate(node.update, local);
381
+ continue;
344
382
  }
345
- if (node.update) this.evaluate(node.update, local);
383
+ throw e;
346
384
  }
347
- return null;
348
- }
349
-
350
- evalFunctionDeclaration(node, env) {
351
- const fn = { params: node.params, body: node.body, env };
352
- env.define(node.name, fn);
353
- return null;
385
+ if (node.update) await this.evaluate(node.update, local);
354
386
  }
387
+ return null;
388
+ }
355
389
 
356
- evalCall(node, env) {
357
- const calleeEvaluated = this.evaluate(node.callee, env);
358
- if (typeof calleeEvaluated === 'function') {
359
- const args = node.arguments.map(a => this.evaluate(a, env));
360
- return calleeEvaluated(...args);
361
- }
362
- if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) {
363
- throw new Error('Call to non-function');
364
- }
365
- const fn = calleeEvaluated;
366
- const callEnv = new Environment(fn.env);
367
- fn.params.forEach((p, i) => {
368
- const argVal = node.arguments[i] ? this.evaluate(node.arguments[i], env) : null;
369
- callEnv.define(p, argVal);
370
- });
371
- try {
372
- const result = this.evaluate(fn.body, callEnv);
373
- return fn.arrow ? result : result;
374
- } catch (e) {
375
- if (e instanceof ReturnValue) return e.value;
376
- throw e;
390
+ evalFunctionDeclaration(node, env) {
391
+ const fn = { params: node.params, body: node.body, env, async: node.async || false };
392
+ env.define(node.name, fn);
393
+ return null;
377
394
  }
378
395
 
396
+ async evalCall(node, env) {
397
+ const calleeEvaluated = await this.evaluate(node.callee, env);
398
+ if (typeof calleeEvaluated === 'function') {
399
+ const args = [];
400
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
401
+ return calleeEvaluated(...args);
402
+ }
403
+ if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) {
404
+ throw new Error('Call to non-function');
379
405
  }
380
406
 
381
- evalIndex(node, env) {
382
- const obj = this.evaluate(node.object, env);
383
- const idx = this.evaluate(node.indexer, env);
407
+ const fn = calleeEvaluated;
408
+ const callEnv = new Environment(fn.env);
384
409
 
385
- if (obj == null) throw new Error('Indexing null or undefined');
386
- if (Array.isArray(obj) && (idx < 0 || idx >= obj.length)) {
387
- throw new Error('Array index out of bounds');
388
- }
389
- if (typeof obj === 'object' && !(idx in obj)) {
390
- throw new Error(`Property '${idx}' does not exist`);
391
- }
410
+ for (let i = 0; i < fn.params.length; i++) {
411
+ const argVal = node.arguments[i] ? await this.evaluate(node.arguments[i], env) : null;
412
+ callEnv.define(fn.params[i], argVal);
413
+ }
392
414
 
393
- return obj[idx];
415
+ try {
416
+ const result = await this.evaluate(fn.body, callEnv);
417
+ return fn.arrow ? result : result;
418
+ } catch (e) {
419
+ if (e instanceof ReturnValue) return e.value;
420
+ throw e;
421
+ }
394
422
  }
395
423
 
424
+ async evalIndex(node, env) {
425
+ const obj = await this.evaluate(node.object, env);
426
+ const idx = await this.evaluate(node.indexer, env);
396
427
 
397
- evalObject(node, env) {
398
- const out = {};
399
- for (const p of node.props) out[p.key] = this.evaluate(p.value, env);
400
- return out;
428
+ if (obj == null) throw new Error('Indexing null or undefined');
429
+ if (Array.isArray(obj) && (idx < 0 || idx >= obj.length)) {
430
+ throw new Error('Array index out of bounds');
431
+ }
432
+ if (typeof obj === 'object' && !(idx in obj)) {
433
+ throw new Error(`Property '${idx}' does not exist`);
401
434
  }
402
435
 
403
- evalMember(node, env) {
404
- const obj = this.evaluate(node.object, env);
405
- if (obj == null) throw new Error('Member access of null or undefined');
406
- if (!(node.property in obj)) throw new Error(`Property '${node.property}' does not exist`);
407
- return obj[node.property];
436
+ return obj[idx];
408
437
  }
409
438
 
439
+ async evalObject(node, env) {
440
+ const out = {};
441
+ for (const p of node.props) out[p.key] = await this.evaluate(p.value, env);
442
+ return out;
443
+ }
444
+
445
+ async evalMember(node, env) {
446
+ const obj = await this.evaluate(node.object, env);
447
+ if (obj == null) throw new Error('Member access of null or undefined');
448
+ if (!(node.property in obj)) throw new Error(`Property '${node.property}' does not exist`);
449
+ return obj[node.property];
450
+ }
451
+
452
+ async evalUpdate(node, env) {
453
+ const arg = node.argument;
454
+ const getCurrent = async () => {
455
+ if (arg.type === 'Identifier') return env.get(arg.name);
456
+ if (arg.type === 'MemberExpression') return await this.evalMember(arg, env);
457
+ if (arg.type === 'IndexExpression') return await this.evalIndex(arg, env);
458
+ throw new Error('Invalid update target');
459
+ };
460
+ const setValue = async (v) => {
461
+ if (arg.type === 'Identifier') env.set(arg.name, v);
462
+ else if (arg.type === 'MemberExpression') {
463
+ const obj = await this.evaluate(arg.object, env);
464
+ obj[arg.property] = v;
465
+ } else if (arg.type === 'IndexExpression') {
466
+ const obj = await this.evaluate(arg.object, env);
467
+ const idx = await this.evaluate(arg.indexer, env);
468
+ obj[idx] = v;
469
+ }
470
+ };
471
+
472
+ const current = await getCurrent();
473
+ const newVal = (node.operator === 'PLUSPLUS') ? current + 1 : current - 1;
474
+
475
+ if (node.prefix) { await setValue(newVal); return newVal; }
476
+ else { await setValue(newVal); return current; }
477
+ }
410
478
 
411
- evalUpdate(node, env) {
412
- const arg = node.argument;
413
- const getCurrent = () => {
414
- if (arg.type === 'Identifier') return env.get(arg.name);
415
- if (arg.type === 'MemberExpression') return this.evalMember(arg, env);
416
- if (arg.type === 'IndexExpression') return this.evalIndex(arg, env);
417
- throw new Error('Invalid update target');
418
- };
419
- const setValue = (v) => {
420
- if (arg.type === 'Identifier') env.set(arg.name, v);
421
- else if (arg.type === 'MemberExpression') {
422
- const obj = this.evaluate(arg.object, env);
423
- obj[arg.property] = v;
424
- }
425
- else if (arg.type === 'IndexExpression') {
426
- const obj = this.evaluate(arg.object, env);
427
- const idx = this.evaluate(arg.indexer, env);
428
- obj[idx] = v;
429
- }
430
- };
431
- const current = getCurrent();
432
- const newVal = (node.operator === 'PLUSPLUS') ? current + 1 : current - 1;
433
- if (node.prefix) { setValue(newVal); return newVal; }
434
- else { setValue(newVal); return current; }
435
- }
436
479
  }
437
480
 
438
- module.exports = Evaluator;
481
+ module.exports = Evaluator;
package/src/lexer.js CHANGED
@@ -79,10 +79,13 @@ class Lexer {
79
79
  }
80
80
 
81
81
  const keywords = [
82
- 'let', 'sldeploy', 'if', 'else', 'while', 'for',
83
- 'break', 'continue', 'func', 'return', 'true', 'false', 'null',
84
- 'ask', 'define', 'import', 'from', 'as'
85
- ];
82
+ 'let', 'sldeploy', 'if', 'else', 'while', 'for',
83
+ 'break', 'continue', 'func', 'return',
84
+ 'true', 'false', 'null',
85
+ 'ask', 'define', 'import', 'from', 'as',
86
+ 'async', 'await'
87
+ ];
88
+
86
89
 
87
90
  if (keywords.includes(result)) {
88
91
  return { type: result.toUpperCase(), value: result, line: startLine, column: startCol };