greybel-interpreter 4.10.1 → 5.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.
@@ -1,5 +1,5 @@
1
1
  import { ASTFeatureEnvarExpression, ASTFeatureInjectExpression } from 'greybel-core';
2
- import { ASTBase, ASTCallExpression, ASTEvaluationExpression, ASTFunctionStatement, ASTIdentifier, ASTIndexExpression, ASTListConstructorExpression, ASTLiteral, ASTMapConstructorExpression, ASTMemberExpression, ASTSliceExpression, ASTUnaryExpression } from 'miniscript-core';
2
+ import { ASTBase, ASTBinaryExpression, ASTCallExpression, ASTComparisonGroupExpression, ASTFunctionStatement, ASTIdentifier, ASTIndexExpression, ASTIsaExpression, ASTListConstructorExpression, ASTLiteral, ASTLogicalExpression, ASTMapConstructorExpression, ASTMemberExpression, ASTSliceExpression, ASTUnaryExpression } from 'miniscript-core';
3
3
  import { Context } from './context';
4
4
  import { LineCallableContext, LineContext, LineIdentifierContext } from './line';
5
5
  import { IBytecodeExpressionGenerator, IBytecodeStatementGenerator, ParseCodeFunction } from './models';
@@ -14,7 +14,10 @@ export declare class BytecodeExpressionGenerator implements IBytecodeExpressionG
14
14
  processSliceExpression(node: ASTSliceExpression): Promise<void>;
15
15
  processIdentifier(node: ASTIdentifier, context?: LineIdentifierContext): Promise<void>;
16
16
  processLiteral(node: ASTLiteral): Promise<void>;
17
- processEvaluationExpression(node: ASTEvaluationExpression): Promise<void>;
17
+ processIsaExpression(node: ASTIsaExpression): Promise<void>;
18
+ processLogicalExpression(node: ASTLogicalExpression): Promise<void>;
19
+ private static binaryExpressionToOp;
20
+ processBinaryExpression(node: ASTBinaryExpression): Promise<void>;
18
21
  processMapConstructorExpression(node: ASTMapConstructorExpression): Promise<void>;
19
22
  processListConstructorExpression(node: ASTListConstructorExpression): Promise<void>;
20
23
  processFunctionDeclaration(node: ASTFunctionStatement, context?: LineContext): Promise<void>;
@@ -22,4 +25,5 @@ export declare class BytecodeExpressionGenerator implements IBytecodeExpressionG
22
25
  processCallExpression(node: ASTCallExpression): Promise<void>;
23
26
  processInjectExpression(node: ASTFeatureInjectExpression): Promise<void>;
24
27
  processEnvarExpression(node: ASTFeatureEnvarExpression): Promise<void>;
28
+ processComparisonGroupExpression(node: ASTComparisonGroupExpression): Promise<void>;
25
29
  }
@@ -48,9 +48,13 @@ class BytecodeExpressionGenerator {
48
48
  yield this.processLiteral(node);
49
49
  return;
50
50
  case miniscript_core_1.ASTType.IsaExpression:
51
+ yield this.processIsaExpression(node);
52
+ return;
51
53
  case miniscript_core_1.ASTType.BinaryExpression:
54
+ yield this.processBinaryExpression(node);
55
+ return;
52
56
  case miniscript_core_1.ASTType.LogicalExpression:
53
- yield this.processEvaluationExpression(node);
57
+ yield this.processLogicalExpression(node);
54
58
  return;
55
59
  case miniscript_core_1.ASTType.MapConstructorExpression:
56
60
  yield this.processMapConstructorExpression(node);
@@ -98,6 +102,9 @@ class BytecodeExpressionGenerator {
98
102
  return;
99
103
  case miniscript_core_1.ASTType.Comment:
100
104
  return;
105
+ case miniscript_core_1.ASTType.ComparisonGroupExpression:
106
+ yield this.processComparisonGroupExpression(node);
107
+ return;
101
108
  default: {
102
109
  const range = new miniscript_core_1.ASTRange(node.start, node.end);
103
110
  throw new error_1.PrepareError(`Unexpected AST type ${node.type}`, {
@@ -224,156 +231,65 @@ class BytecodeExpressionGenerator {
224
231
  }, node);
225
232
  });
226
233
  }
227
- processEvaluationExpression(node) {
234
+ processIsaExpression(node) {
235
+ return __awaiter(this, void 0, void 0, function* () {
236
+ yield this.process(node.left);
237
+ yield this.process(node.right);
238
+ if (node.type !== miniscript_core_1.ASTType.IsaExpression) {
239
+ throw new Error(`Unexpected evaluation expression operator. ("${node.operator}")`);
240
+ }
241
+ this.context.pushCode({
242
+ op: instruction_1.OpCode.ISA
243
+ }, node);
244
+ });
245
+ }
246
+ processLogicalExpression(node) {
228
247
  return __awaiter(this, void 0, void 0, function* () {
229
248
  const skip = {
230
249
  op: instruction_1.OpCode.NOOP
231
250
  };
232
- yield this.process(node.left);
251
+ let gotoOp;
252
+ let actionOp;
233
253
  if (node.operator === miniscript_core_1.Operator.And) {
234
- this.context.pushCode({
235
- op: instruction_1.OpCode.GOTO_A_IF_FALSE_AND_PUSH,
236
- goto: skip
237
- }, node);
254
+ gotoOp = instruction_1.OpCode.GOTO_A_IF_FALSE_AND_PUSH;
255
+ actionOp = instruction_1.OpCode.AND;
238
256
  }
239
257
  else if (node.operator === miniscript_core_1.Operator.Or) {
240
- this.context.pushCode({
241
- op: instruction_1.OpCode.GOTO_A_IF_TRUE_AND_PUSH,
242
- goto: skip
243
- }, node);
258
+ gotoOp = instruction_1.OpCode.GOTO_A_IF_TRUE_AND_PUSH;
259
+ actionOp = instruction_1.OpCode.OR;
244
260
  }
261
+ else {
262
+ throw new Error(`Unexpected evaluation expression operator. ("${node.operator}")`);
263
+ }
264
+ yield this.process(node.left);
265
+ this.context.pushCode({
266
+ op: gotoOp,
267
+ goto: skip
268
+ }, node);
245
269
  yield this.process(node.right);
246
- switch (node.operator) {
247
- case miniscript_core_1.Operator.Isa: {
248
- this.context.pushCode({
249
- op: instruction_1.OpCode.ISA
250
- }, node);
251
- break;
252
- }
253
- case miniscript_core_1.Operator.Equal: {
254
- this.context.pushCode({
255
- op: instruction_1.OpCode.EQUAL
256
- }, node);
257
- break;
258
- }
259
- case miniscript_core_1.Operator.NotEqual: {
260
- this.context.pushCode({
261
- op: instruction_1.OpCode.NOT_EQUAL
262
- }, node);
263
- break;
264
- }
265
- case miniscript_core_1.Operator.LessThan: {
266
- this.context.pushCode({
267
- op: instruction_1.OpCode.LESS_THAN
268
- }, node);
269
- break;
270
- }
271
- case miniscript_core_1.Operator.LessThanOrEqual: {
272
- this.context.pushCode({
273
- op: instruction_1.OpCode.LESS_THAN_OR_EQUAL
274
- }, node);
275
- break;
276
- }
277
- case miniscript_core_1.Operator.GreaterThan: {
278
- this.context.pushCode({
279
- op: instruction_1.OpCode.GREATER_THAN
280
- }, node);
281
- break;
282
- }
283
- case miniscript_core_1.Operator.GreaterThanOrEqual: {
284
- this.context.pushCode({
285
- op: instruction_1.OpCode.GREATER_THAN_OR_EQUAL
286
- }, node);
287
- break;
288
- }
289
- case miniscript_core_1.Operator.And: {
290
- this.context.pushCode({
291
- op: instruction_1.OpCode.AND
292
- }, node);
293
- this.context.pushCode(skip, node);
294
- break;
295
- }
296
- case miniscript_core_1.Operator.Or: {
297
- this.context.pushCode({
298
- op: instruction_1.OpCode.OR
299
- }, node);
300
- this.context.pushCode(skip, node);
301
- break;
302
- }
303
- case miniscript_core_1.Operator.Plus: {
304
- this.context.pushCode({
305
- op: instruction_1.OpCode.ADD
306
- }, node);
307
- break;
308
- }
309
- case miniscript_core_1.Operator.Minus: {
310
- this.context.pushCode({
311
- op: instruction_1.OpCode.SUB
312
- }, node);
313
- break;
314
- }
315
- case miniscript_core_1.Operator.Asterik: {
316
- this.context.pushCode({
317
- op: instruction_1.OpCode.MUL
318
- }, node);
319
- break;
320
- }
321
- case miniscript_core_1.Operator.Slash: {
322
- this.context.pushCode({
323
- op: instruction_1.OpCode.DIV
324
- }, node);
325
- break;
326
- }
327
- case miniscript_core_1.Operator.Modulo: {
328
- this.context.pushCode({
329
- op: instruction_1.OpCode.MOD
330
- }, node);
331
- break;
332
- }
333
- case miniscript_core_1.Operator.Power: {
334
- this.context.pushCode({
335
- op: instruction_1.OpCode.POW
336
- }, node);
337
- break;
338
- }
339
- case greybel_core_1.Operator.BitwiseAnd: {
340
- this.context.pushCode({
341
- op: instruction_1.OpCode.BITWISE_AND
342
- }, node);
343
- break;
344
- }
345
- case greybel_core_1.Operator.BitwiseOr: {
346
- this.context.pushCode({
347
- op: instruction_1.OpCode.BITWISE_OR
348
- }, node);
349
- break;
350
- }
351
- case greybel_core_1.Operator.LeftShift: {
352
- this.context.pushCode({
353
- op: instruction_1.OpCode.BITWISE_LEFT_SHIFT
354
- }, node);
355
- break;
356
- }
357
- case greybel_core_1.Operator.RightShift: {
358
- this.context.pushCode({
359
- op: instruction_1.OpCode.BITWISE_RIGHT_SHIFT
360
- }, node);
361
- break;
362
- }
363
- case greybel_core_1.Operator.UnsignedRightShift: {
364
- this.context.pushCode({
365
- op: instruction_1.OpCode.BITWISE_UNSIGNED_RIGHT_SHIFT
366
- }, node);
367
- break;
368
- }
369
- default:
370
- throw new Error(`Unexpected evaluation expression operator. ("${node.operator}")`);
270
+ this.context.pushCode({
271
+ op: actionOp
272
+ }, node);
273
+ this.context.pushCode(skip, node);
274
+ });
275
+ }
276
+ processBinaryExpression(node) {
277
+ return __awaiter(this, void 0, void 0, function* () {
278
+ yield this.process(node.left);
279
+ yield this.process(node.right);
280
+ const opCode = BytecodeExpressionGenerator.binaryExpressionToOp[node.operator];
281
+ if (opCode == null) {
282
+ throw new Error(`Unexpected binary expression operator. ("${node.operator}")`);
371
283
  }
284
+ this.context.pushCode({
285
+ op: opCode
286
+ }, node);
372
287
  });
373
288
  }
374
289
  processMapConstructorExpression(node) {
375
290
  return __awaiter(this, void 0, void 0, function* () {
376
- for (const field of node.fields) {
291
+ for (let index = 0; index < node.fields.length; index++) {
292
+ const field = node.fields[index];
377
293
  yield this.process(field.key);
378
294
  yield this.process(field.value);
379
295
  }
@@ -385,7 +301,8 @@ class BytecodeExpressionGenerator {
385
301
  }
386
302
  processListConstructorExpression(node) {
387
303
  return __awaiter(this, void 0, void 0, function* () {
388
- for (const field of node.fields) {
304
+ for (let index = 0; index < node.fields.length; index++) {
305
+ const field = node.fields[index];
389
306
  yield this.process(field.value);
390
307
  }
391
308
  this.context.pushCode({
@@ -397,7 +314,8 @@ class BytecodeExpressionGenerator {
397
314
  processFunctionDeclaration(node, context) {
398
315
  return __awaiter(this, void 0, void 0, function* () {
399
316
  const args = [];
400
- for (const item of node.parameters) {
317
+ for (let index = 0; index < node.parameters.length; index++) {
318
+ const item = node.parameters[index];
401
319
  if (item instanceof miniscript_core_1.ASTIdentifier) {
402
320
  args.push({
403
321
  name: new string_1.CustomString(item.name),
@@ -417,7 +335,8 @@ class BytecodeExpressionGenerator {
417
335
  }
418
336
  const mod = this.context.module.peek();
419
337
  mod.pushContext();
420
- for (const item of node.body) {
338
+ for (let index = 0; index < node.body.length; index++) {
339
+ const item = node.body[index];
421
340
  yield this.stmtGenerator.process(item);
422
341
  }
423
342
  this.context.pushInternalCode({
@@ -486,7 +405,8 @@ class BytecodeExpressionGenerator {
486
405
  processCallExpression(node) {
487
406
  return __awaiter(this, void 0, void 0, function* () {
488
407
  const pushArgs = () => __awaiter(this, void 0, void 0, function* () {
489
- for (const arg of node.arguments) {
408
+ for (let index = 0; index < node.arguments.length; index++) {
409
+ const arg = node.arguments[index];
490
410
  yield this.process(arg);
491
411
  }
492
412
  });
@@ -588,5 +508,35 @@ class BytecodeExpressionGenerator {
588
508
  }, node);
589
509
  });
590
510
  }
511
+ processComparisonGroupExpression(node) {
512
+ return __awaiter(this, void 0, void 0, function* () {
513
+ for (let index = node.expressions.length - 1; index >= 0; index--) {
514
+ yield this.process(node.expressions[index]);
515
+ }
516
+ this.context.pushCode({
517
+ op: instruction_1.OpCode.COMPARISON_GROUP,
518
+ operators: node.operators
519
+ }, node);
520
+ });
521
+ }
591
522
  }
523
+ BytecodeExpressionGenerator.binaryExpressionToOp = {
524
+ [miniscript_core_1.Operator.Equal]: instruction_1.OpCode.EQUAL,
525
+ [miniscript_core_1.Operator.NotEqual]: instruction_1.OpCode.NOT_EQUAL,
526
+ [miniscript_core_1.Operator.LessThan]: instruction_1.OpCode.LESS_THAN,
527
+ [miniscript_core_1.Operator.LessThanOrEqual]: instruction_1.OpCode.LESS_THAN_OR_EQUAL,
528
+ [miniscript_core_1.Operator.GreaterThan]: instruction_1.OpCode.GREATER_THAN,
529
+ [miniscript_core_1.Operator.GreaterThanOrEqual]: instruction_1.OpCode.GREATER_THAN_OR_EQUAL,
530
+ [miniscript_core_1.Operator.Plus]: instruction_1.OpCode.ADD,
531
+ [miniscript_core_1.Operator.Minus]: instruction_1.OpCode.SUB,
532
+ [miniscript_core_1.Operator.Asterik]: instruction_1.OpCode.MUL,
533
+ [miniscript_core_1.Operator.Slash]: instruction_1.OpCode.DIV,
534
+ [miniscript_core_1.Operator.Modulo]: instruction_1.OpCode.MOD,
535
+ [miniscript_core_1.Operator.Power]: instruction_1.OpCode.POW,
536
+ [greybel_core_1.Operator.BitwiseAnd]: instruction_1.OpCode.BITWISE_AND,
537
+ [greybel_core_1.Operator.BitwiseOr]: instruction_1.OpCode.BITWISE_OR,
538
+ [greybel_core_1.Operator.LeftShift]: instruction_1.OpCode.BITWISE_LEFT_SHIFT,
539
+ [greybel_core_1.Operator.RightShift]: instruction_1.OpCode.BITWISE_RIGHT_SHIFT,
540
+ [greybel_core_1.Operator.UnsignedRightShift]: instruction_1.OpCode.BITWISE_UNSIGNED_RIGHT_SHIFT
541
+ };
592
542
  exports.BytecodeExpressionGenerator = BytecodeExpressionGenerator;
@@ -40,26 +40,27 @@ export declare enum OpCode {
40
40
  LESS_THAN_OR_EQUAL = 34,
41
41
  GREATER_THAN = 35,
42
42
  GREATER_THAN_OR_EQUAL = 36,
43
- AND = 37,
44
- OR = 38,
45
- RETURN = 39,
46
- FUNCTION_DEFINITION = 40,
47
- GOTO_A = 41,
48
- GOTO_A_IF_FALSE = 42,
49
- GOTO_A_IF_FALSE_AND_PUSH = 43,
50
- GOTO_A_IF_TRUE = 44,
51
- GOTO_A_IF_TRUE_AND_PUSH = 45,
52
- PUSH_ITERATOR = 46,
53
- POP_ITERATOR = 47,
54
- NEXT = 48,
55
- BITWISE_OR = 49,
56
- BITWISE_AND = 50,
57
- BITWISE_LEFT_SHIFT = 51,
58
- BITWISE_RIGHT_SHIFT = 52,
59
- BITWISE_UNSIGNED_RIGHT_SHIFT = 53,
60
- BREAKPOINT = 54,
61
- BREAKPOINT_ENABLE = 55,
62
- IMPORT = 56
43
+ COMPARISON_GROUP = 37,
44
+ AND = 38,
45
+ OR = 39,
46
+ RETURN = 40,
47
+ FUNCTION_DEFINITION = 41,
48
+ GOTO_A = 42,
49
+ GOTO_A_IF_FALSE = 43,
50
+ GOTO_A_IF_FALSE_AND_PUSH = 44,
51
+ GOTO_A_IF_TRUE = 45,
52
+ GOTO_A_IF_TRUE_AND_PUSH = 46,
53
+ PUSH_ITERATOR = 47,
54
+ POP_ITERATOR = 48,
55
+ NEXT = 49,
56
+ BITWISE_OR = 50,
57
+ BITWISE_AND = 51,
58
+ BITWISE_LEFT_SHIFT = 52,
59
+ BITWISE_RIGHT_SHIFT = 53,
60
+ BITWISE_UNSIGNED_RIGHT_SHIFT = 54,
61
+ BREAKPOINT = 55,
62
+ BREAKPOINT_ENABLE = 56,
63
+ IMPORT = 57
63
64
  }
64
65
  export interface FunctionDefinitionInstructionArgument {
65
66
  name: CustomString;
@@ -127,4 +128,8 @@ export interface ImportInstruction extends BaseInstruction {
127
128
  op: OpCode.IMPORT;
128
129
  path: string;
129
130
  }
130
- export type Instruction = BaseInstruction | GetVariableInstruction | PushInstruction | ConstructMapInstruction | ConstructListInstruction | FunctionDefinitionInstruction | GotoAInstruction | GetPropertyInstruction | CallInstruction | NextInstruction | CallInternalInstruction | ImportInstruction;
131
+ export interface ComparisonGroupInstruction extends BaseInstruction {
132
+ op: OpCode.COMPARISON_GROUP;
133
+ operators: string[];
134
+ }
135
+ export type Instruction = BaseInstruction | GetVariableInstruction | PushInstruction | ConstructMapInstruction | ConstructListInstruction | FunctionDefinitionInstruction | GotoAInstruction | GetPropertyInstruction | CallInstruction | NextInstruction | CallInternalInstruction | ImportInstruction | ComparisonGroupInstruction;
@@ -40,24 +40,25 @@ var OpCode;
40
40
  OpCode[OpCode["LESS_THAN_OR_EQUAL"] = 34] = "LESS_THAN_OR_EQUAL";
41
41
  OpCode[OpCode["GREATER_THAN"] = 35] = "GREATER_THAN";
42
42
  OpCode[OpCode["GREATER_THAN_OR_EQUAL"] = 36] = "GREATER_THAN_OR_EQUAL";
43
- OpCode[OpCode["AND"] = 37] = "AND";
44
- OpCode[OpCode["OR"] = 38] = "OR";
45
- OpCode[OpCode["RETURN"] = 39] = "RETURN";
46
- OpCode[OpCode["FUNCTION_DEFINITION"] = 40] = "FUNCTION_DEFINITION";
47
- OpCode[OpCode["GOTO_A"] = 41] = "GOTO_A";
48
- OpCode[OpCode["GOTO_A_IF_FALSE"] = 42] = "GOTO_A_IF_FALSE";
49
- OpCode[OpCode["GOTO_A_IF_FALSE_AND_PUSH"] = 43] = "GOTO_A_IF_FALSE_AND_PUSH";
50
- OpCode[OpCode["GOTO_A_IF_TRUE"] = 44] = "GOTO_A_IF_TRUE";
51
- OpCode[OpCode["GOTO_A_IF_TRUE_AND_PUSH"] = 45] = "GOTO_A_IF_TRUE_AND_PUSH";
52
- OpCode[OpCode["PUSH_ITERATOR"] = 46] = "PUSH_ITERATOR";
53
- OpCode[OpCode["POP_ITERATOR"] = 47] = "POP_ITERATOR";
54
- OpCode[OpCode["NEXT"] = 48] = "NEXT";
55
- OpCode[OpCode["BITWISE_OR"] = 49] = "BITWISE_OR";
56
- OpCode[OpCode["BITWISE_AND"] = 50] = "BITWISE_AND";
57
- OpCode[OpCode["BITWISE_LEFT_SHIFT"] = 51] = "BITWISE_LEFT_SHIFT";
58
- OpCode[OpCode["BITWISE_RIGHT_SHIFT"] = 52] = "BITWISE_RIGHT_SHIFT";
59
- OpCode[OpCode["BITWISE_UNSIGNED_RIGHT_SHIFT"] = 53] = "BITWISE_UNSIGNED_RIGHT_SHIFT";
60
- OpCode[OpCode["BREAKPOINT"] = 54] = "BREAKPOINT";
61
- OpCode[OpCode["BREAKPOINT_ENABLE"] = 55] = "BREAKPOINT_ENABLE";
62
- OpCode[OpCode["IMPORT"] = 56] = "IMPORT";
43
+ OpCode[OpCode["COMPARISON_GROUP"] = 37] = "COMPARISON_GROUP";
44
+ OpCode[OpCode["AND"] = 38] = "AND";
45
+ OpCode[OpCode["OR"] = 39] = "OR";
46
+ OpCode[OpCode["RETURN"] = 40] = "RETURN";
47
+ OpCode[OpCode["FUNCTION_DEFINITION"] = 41] = "FUNCTION_DEFINITION";
48
+ OpCode[OpCode["GOTO_A"] = 42] = "GOTO_A";
49
+ OpCode[OpCode["GOTO_A_IF_FALSE"] = 43] = "GOTO_A_IF_FALSE";
50
+ OpCode[OpCode["GOTO_A_IF_FALSE_AND_PUSH"] = 44] = "GOTO_A_IF_FALSE_AND_PUSH";
51
+ OpCode[OpCode["GOTO_A_IF_TRUE"] = 45] = "GOTO_A_IF_TRUE";
52
+ OpCode[OpCode["GOTO_A_IF_TRUE_AND_PUSH"] = 46] = "GOTO_A_IF_TRUE_AND_PUSH";
53
+ OpCode[OpCode["PUSH_ITERATOR"] = 47] = "PUSH_ITERATOR";
54
+ OpCode[OpCode["POP_ITERATOR"] = 48] = "POP_ITERATOR";
55
+ OpCode[OpCode["NEXT"] = 49] = "NEXT";
56
+ OpCode[OpCode["BITWISE_OR"] = 50] = "BITWISE_OR";
57
+ OpCode[OpCode["BITWISE_AND"] = 51] = "BITWISE_AND";
58
+ OpCode[OpCode["BITWISE_LEFT_SHIFT"] = 52] = "BITWISE_LEFT_SHIFT";
59
+ OpCode[OpCode["BITWISE_RIGHT_SHIFT"] = 53] = "BITWISE_RIGHT_SHIFT";
60
+ OpCode[OpCode["BITWISE_UNSIGNED_RIGHT_SHIFT"] = 54] = "BITWISE_UNSIGNED_RIGHT_SHIFT";
61
+ OpCode[OpCode["BREAKPOINT"] = 55] = "BREAKPOINT";
62
+ OpCode[OpCode["BREAKPOINT_ENABLE"] = 56] = "BREAKPOINT_ENABLE";
63
+ OpCode[OpCode["IMPORT"] = 57] = "IMPORT";
63
64
  })(OpCode = exports.OpCode || (exports.OpCode = {}));
@@ -1,5 +1,5 @@
1
1
  import { ASTFeatureEnvarExpression, ASTFeatureImportExpression, ASTFeatureIncludeExpression, ASTFeatureInjectExpression } from 'greybel-core';
2
- import { ASTAssignmentStatement, ASTBase, ASTCallExpression, ASTEvaluationExpression, ASTForGenericStatement, ASTFunctionStatement, ASTIdentifier, ASTIfStatement, ASTIndexExpression, ASTListConstructorExpression, ASTLiteral, ASTMapConstructorExpression, ASTMemberExpression, ASTReturnStatement, ASTSliceExpression, ASTUnaryExpression, ASTWhileStatement } from 'miniscript-core';
2
+ import { ASTAssignmentStatement, ASTBase, ASTBinaryExpression, ASTCallExpression, ASTComparisonGroupExpression, ASTForGenericStatement, ASTFunctionStatement, ASTIdentifier, ASTIfStatement, ASTIndexExpression, ASTIsaExpression, ASTListConstructorExpression, ASTLiteral, ASTLogicalExpression, ASTMapConstructorExpression, ASTMemberExpression, ASTReturnStatement, ASTSliceExpression, ASTUnaryExpression, ASTWhileStatement } from 'miniscript-core';
3
3
  import { LineCallableContext, LineContext, LineIdentifierContext } from './line';
4
4
  export interface ParseCodeFunction {
5
5
  (code: string): ASTBase;
@@ -10,7 +10,6 @@ export interface IBytecodeStatementGenerator {
10
10
  processIndexExpression(node: ASTIndexExpression, context?: LineCallableContext): Promise<void>;
11
11
  processIdentifier(node: ASTIdentifier, context?: LineIdentifierContext): Promise<void>;
12
12
  processAssignmentStatement(node: ASTAssignmentStatement): Promise<void>;
13
- processEvaluationExpression(node: ASTEvaluationExpression): Promise<void>;
14
13
  processReturn(node: ASTReturnStatement): Promise<void>;
15
14
  processBreak(node: ASTBase): Promise<void>;
16
15
  processContinue(node: ASTBase): Promise<void>;
@@ -32,7 +31,9 @@ export interface IBytecodeExpressionGenerator {
32
31
  processSliceExpression(node: ASTSliceExpression): Promise<void>;
33
32
  processIdentifier(node: ASTIdentifier, context?: LineIdentifierContext): Promise<void>;
34
33
  processLiteral(node: ASTLiteral): Promise<void>;
35
- processEvaluationExpression(node: ASTEvaluationExpression): Promise<void>;
34
+ processBinaryExpression(node: ASTBinaryExpression): Promise<void>;
35
+ processIsaExpression(node: ASTIsaExpression): Promise<void>;
36
+ processLogicalExpression(node: ASTLogicalExpression): Promise<void>;
36
37
  processMapConstructorExpression(node: ASTMapConstructorExpression): Promise<void>;
37
38
  processListConstructorExpression(node: ASTListConstructorExpression): Promise<void>;
38
39
  processFunctionDeclaration(node: ASTFunctionStatement, context?: LineContext): Promise<void>;
@@ -40,4 +41,5 @@ export interface IBytecodeExpressionGenerator {
40
41
  processCallExpression(node: ASTCallExpression): Promise<void>;
41
42
  processInjectExpression(node: ASTFeatureInjectExpression): Promise<void>;
42
43
  processEnvarExpression(node: ASTFeatureEnvarExpression): Promise<void>;
44
+ processComparisonGroupExpression(node: ASTComparisonGroupExpression): Promise<void>;
43
45
  }
@@ -1,5 +1,5 @@
1
1
  import { ASTFeatureImportExpression, ASTFeatureIncludeExpression } from 'greybel-core';
2
- import { ASTAssignmentStatement, ASTBase, ASTCallExpression, ASTEvaluationExpression, ASTForGenericStatement, ASTIdentifier, ASTIfStatement, ASTIndexExpression, ASTListConstructorExpression, ASTMapConstructorExpression, ASTMemberExpression, ASTReturnStatement, ASTUnaryExpression, ASTWhileStatement } from 'miniscript-core';
2
+ import { ASTAssignmentStatement, ASTBase, ASTCallExpression, ASTForGenericStatement, ASTIdentifier, ASTIfStatement, ASTIndexExpression, ASTListConstructorExpression, ASTMapConstructorExpression, ASTMemberExpression, ASTReturnStatement, ASTUnaryExpression, ASTWhileStatement } from 'miniscript-core';
3
3
  import { Context } from './context';
4
4
  import { LineCallableContext, LineIdentifierContext } from './line';
5
5
  import { IBytecodeExpressionGenerator, IBytecodeStatementGenerator, ParseCodeFunction } from './models';
@@ -13,7 +13,6 @@ export declare class BytecodeStatementGenerator implements IBytecodeStatementGen
13
13
  processIndexExpression(node: ASTIndexExpression, context?: LineCallableContext): Promise<void>;
14
14
  processIdentifier(node: ASTIdentifier, context?: LineIdentifierContext): Promise<void>;
15
15
  processAssignmentStatement(node: ASTAssignmentStatement): Promise<void>;
16
- processEvaluationExpression(node: ASTEvaluationExpression): Promise<void>;
17
16
  processReturn(node: ASTReturnStatement): Promise<void>;
18
17
  processBreak(node: ASTBase): Promise<void>;
19
18
  processContinue(node: ASTBase): Promise<void>;
@@ -51,9 +51,8 @@ class BytecodeStatementGenerator {
51
51
  return;
52
52
  case miniscript_core_1.ASTType.Chunk: {
53
53
  const chunk = node;
54
- for (const item of chunk.body) {
55
- yield this.process(item);
56
- }
54
+ for (let index = 0; index < chunk.body.length; yield this.process(chunk.body[index++]))
55
+ ;
57
56
  return;
58
57
  }
59
58
  case miniscript_core_1.ASTType.BooleanLiteral:
@@ -63,8 +62,9 @@ class BytecodeStatementGenerator {
63
62
  return;
64
63
  case miniscript_core_1.ASTType.IsaExpression:
65
64
  case miniscript_core_1.ASTType.BinaryExpression:
65
+ return;
66
66
  case miniscript_core_1.ASTType.LogicalExpression:
67
- yield this.processEvaluationExpression(node);
67
+ yield this.exprGenerator.processLogicalExpression(node);
68
68
  return;
69
69
  case miniscript_core_1.ASTType.ReturnStatement:
70
70
  yield this.processReturn(node);
@@ -95,7 +95,7 @@ class BytecodeStatementGenerator {
95
95
  yield this.processUnaryExpression(node);
96
96
  return;
97
97
  case miniscript_core_1.ASTType.CallStatement:
98
- yield this.process(node.expression);
98
+ yield this.processCallExpression(node.expression);
99
99
  return;
100
100
  case miniscript_core_1.ASTType.CallExpression:
101
101
  yield this.processCallExpression(node);
@@ -251,56 +251,6 @@ class BytecodeStatementGenerator {
251
251
  }, node);
252
252
  });
253
253
  }
254
- processEvaluationExpression(node) {
255
- return __awaiter(this, void 0, void 0, function* () {
256
- const skip = {
257
- op: instruction_1.OpCode.NOOP
258
- };
259
- yield this.exprGenerator.process(node.left);
260
- if (node.operator === miniscript_core_1.Operator.And) {
261
- this.context.pushCode({
262
- op: instruction_1.OpCode.GOTO_A_IF_FALSE,
263
- goto: skip
264
- }, node);
265
- }
266
- else if (node.operator === miniscript_core_1.Operator.Or) {
267
- this.context.pushCode({
268
- op: instruction_1.OpCode.GOTO_A_IF_TRUE,
269
- goto: skip
270
- }, node);
271
- }
272
- yield this.process(node.right);
273
- switch (node.operator) {
274
- case miniscript_core_1.Operator.And:
275
- case miniscript_core_1.Operator.Or: {
276
- this.context.pushCode(skip, node);
277
- break;
278
- }
279
- case miniscript_core_1.Operator.Isa:
280
- case miniscript_core_1.Operator.Equal:
281
- case miniscript_core_1.Operator.NotEqual:
282
- case miniscript_core_1.Operator.LessThan:
283
- case miniscript_core_1.Operator.LessThanOrEqual:
284
- case miniscript_core_1.Operator.GreaterThan:
285
- case miniscript_core_1.Operator.GreaterThanOrEqual:
286
- case miniscript_core_1.Operator.Plus:
287
- case miniscript_core_1.Operator.Minus:
288
- case miniscript_core_1.Operator.Asterik:
289
- case miniscript_core_1.Operator.Slash:
290
- case miniscript_core_1.Operator.Modulo:
291
- case miniscript_core_1.Operator.Power:
292
- case greybel_core_1.Operator.BitwiseAnd:
293
- case greybel_core_1.Operator.BitwiseOr:
294
- case greybel_core_1.Operator.LeftShift:
295
- case greybel_core_1.Operator.RightShift:
296
- case greybel_core_1.Operator.UnsignedRightShift: {
297
- break;
298
- }
299
- default:
300
- throw new Error(`Unexpected evaluation expression operator. ("${node.operator}")`);
301
- }
302
- });
303
- }
304
254
  processReturn(node) {
305
255
  return __awaiter(this, void 0, void 0, function* () {
306
256
  const mod = this.context.module.peek();
@@ -352,7 +302,8 @@ class BytecodeStatementGenerator {
352
302
  }
353
303
  processMapConstructorExpression(node) {
354
304
  return __awaiter(this, void 0, void 0, function* () {
355
- for (const field of node.fields) {
305
+ for (let index = 0; index < node.fields.length; index++) {
306
+ const field = node.fields[index];
356
307
  yield this.exprGenerator.process(field.key);
357
308
  yield this.exprGenerator.process(field.value);
358
309
  }
@@ -365,7 +316,8 @@ class BytecodeStatementGenerator {
365
316
  }
366
317
  processListConstructorExpression(node) {
367
318
  return __awaiter(this, void 0, void 0, function* () {
368
- for (const field of node.fields) {
319
+ for (let index = 0; index < node.fields.length; index++) {
320
+ const field = node.fields[index];
369
321
  yield this.exprGenerator.process(field.value);
370
322
  }
371
323
  this.context.pushCode({
@@ -391,9 +343,8 @@ class BytecodeStatementGenerator {
391
343
  goto: end
392
344
  }, node.condition);
393
345
  mod.pushJumppoint(start, end);
394
- for (const item of node.body) {
395
- yield this.process(item);
396
- }
346
+ for (let index = 0; index < node.body.length; yield this.process(node.body[index++]))
347
+ ;
397
348
  mod.popJumppoint();
398
349
  this.context.pushCode({
399
350
  op: instruction_1.OpCode.GOTO_A,
@@ -452,7 +403,8 @@ class BytecodeStatementGenerator {
452
403
  processCallExpression(node) {
453
404
  return __awaiter(this, void 0, void 0, function* () {
454
405
  const pushArgs = () => __awaiter(this, void 0, void 0, function* () {
455
- for (const arg of node.arguments) {
406
+ for (let index = 0; index < node.arguments.length; index++) {
407
+ const arg = node.arguments[index];
456
408
  yield this.exprGenerator.process(arg);
457
409
  }
458
410
  });
@@ -535,7 +487,8 @@ class BytecodeStatementGenerator {
535
487
  const end = {
536
488
  op: instruction_1.OpCode.NOOP
537
489
  };
538
- for (const clause of node.clauses) {
490
+ for (let index = 0; index < node.clauses.length; index++) {
491
+ const clause = node.clauses[index];
539
492
  if (clause instanceof miniscript_core_1.ASTIfClause) {
540
493
  const next = {
541
494
  op: instruction_1.OpCode.NOOP
@@ -545,9 +498,8 @@ class BytecodeStatementGenerator {
545
498
  op: instruction_1.OpCode.GOTO_A_IF_FALSE,
546
499
  goto: next
547
500
  }, node);
548
- for (const item of clause.body) {
549
- yield this.process(item);
550
- }
501
+ for (let index = 0; index < clause.body.length; yield this.process(clause.body[index++]))
502
+ ;
551
503
  this.context.pushCode({
552
504
  op: instruction_1.OpCode.GOTO_A,
553
505
  goto: end
@@ -555,9 +507,8 @@ class BytecodeStatementGenerator {
555
507
  this.context.pushCode(next, clause);
556
508
  }
557
509
  else if (clause instanceof miniscript_core_1.ASTElseClause) {
558
- for (const item of clause.body) {
559
- yield this.process(item);
560
- }
510
+ for (let index = 0; index < clause.body.length; yield this.process(clause.body[index++]))
511
+ ;
561
512
  }
562
513
  }
563
514
  this.context.pushCode(end, node);
@@ -600,9 +551,8 @@ class BytecodeStatementGenerator {
600
551
  op: instruction_1.OpCode.GOTO_A_IF_FALSE,
601
552
  goto: end
602
553
  }, node.iterator);
603
- for (const item of node.body) {
604
- yield this.process(item);
605
- }
554
+ for (let index = 0; index < node.body.length; yield this.process(node.body[index++]))
555
+ ;
606
556
  this.context.pushCode({
607
557
  op: instruction_1.OpCode.GOTO_A,
608
558
  goto: start
@@ -25,3 +25,4 @@ export declare function evalMod(a: CustomValue, b: CustomValue): CustomNil | Cus
25
25
  export declare function evalPow(a: CustomValue, b: CustomValue): CustomNil | CustomNumber;
26
26
  export declare function evalAnd(a: CustomValue, b: CustomValue): CustomNumber;
27
27
  export declare function evalOr(a: CustomValue, b: CustomValue): CustomNumber;
28
+ export declare function evalComparisonGroup(values: CustomValue[], operators: string[]): CustomNumber;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.evalOr = exports.evalAnd = exports.evalPow = exports.evalMod = exports.evalNotEqual = exports.evalEqual = exports.evalGreaterThanOrEqual = exports.evalGreaterThan = exports.evalLessThanOrEqual = exports.evalLessThan = exports.evalBitwiseLeftShift = exports.evalBitwiseUnsignedRightShift = exports.evalBitwiseRightShift = exports.evalBitwiseAnd = exports.evalBitwiseOr = exports.evalDiv = exports.evalMul = exports.evalSub = exports.evalAdd = exports.absClamp01 = void 0;
3
+ exports.evalComparisonGroup = exports.evalOr = exports.evalAnd = exports.evalPow = exports.evalMod = exports.evalNotEqual = exports.evalEqual = exports.evalGreaterThanOrEqual = exports.evalGreaterThan = exports.evalLessThanOrEqual = exports.evalLessThan = exports.evalBitwiseLeftShift = exports.evalBitwiseUnsignedRightShift = exports.evalBitwiseRightShift = exports.evalBitwiseAnd = exports.evalBitwiseOr = exports.evalDiv = exports.evalMul = exports.evalSub = exports.evalAdd = exports.absClamp01 = void 0;
4
+ const miniscript_core_1 = require("miniscript-core");
4
5
  const boolean_1 = require("../types/boolean");
5
6
  const default_1 = require("../types/default");
6
7
  const function_1 = require("../types/function");
@@ -340,3 +341,36 @@ function evalOr(a, b) {
340
341
  return new number_1.CustomNumber((0, exports.absClamp01)(left + right - left * right));
341
342
  }
342
343
  exports.evalOr = evalOr;
344
+ function evalComparisonGroup(values, operators) {
345
+ for (let index = 0; index < operators.length; index++) {
346
+ const operator = operators[index];
347
+ const left = values[index];
348
+ const right = values[index + 1];
349
+ let result;
350
+ switch (operator) {
351
+ case miniscript_core_1.Operator.Equal:
352
+ result = evalEqual(left, right);
353
+ break;
354
+ case miniscript_core_1.Operator.NotEqual:
355
+ result = evalNotEqual(left, right);
356
+ break;
357
+ case miniscript_core_1.Operator.GreaterThan:
358
+ result = evalGreaterThan(left, right);
359
+ break;
360
+ case miniscript_core_1.Operator.GreaterThanOrEqual:
361
+ result = evalGreaterThanOrEqual(left, right);
362
+ break;
363
+ case miniscript_core_1.Operator.LessThan:
364
+ result = evalLessThan(left, right);
365
+ break;
366
+ case miniscript_core_1.Operator.LessThanOrEqual:
367
+ result = evalLessThanOrEqual(left, right);
368
+ break;
369
+ }
370
+ if (!result.toTruthy()) {
371
+ return default_1.DefaultType.False;
372
+ }
373
+ }
374
+ return default_1.DefaultType.True;
375
+ }
376
+ exports.evalComparisonGroup = evalComparisonGroup;
package/dist/vm.js CHANGED
@@ -176,22 +176,28 @@ class VM {
176
176
  return new Promise((resolve, reject) => {
177
177
  this.state = VMState.PENDING;
178
178
  this.time = Date.now();
179
- this.resume((err) => {
179
+ this.signal.on('done', (err) => {
180
+ this.signal.removeAllListeners('cycle');
181
+ this.signal.removeAllListeners('resume');
182
+ this.signal.removeAllListeners('done');
180
183
  if (err) {
181
184
  reject(err);
182
185
  return;
183
186
  }
184
187
  resolve();
185
188
  });
189
+ this.signal.on('cycle', () => (0, non_blocking_schedule_1.schedule)(() => this.resume()));
190
+ this.signal.on('resume', () => this.resume());
191
+ this.resume();
186
192
  });
187
193
  });
188
194
  }
189
- resume(done) {
195
+ resume() {
190
196
  var _a, _b, _c, _d, _e;
191
197
  try {
192
198
  while (true) {
193
199
  if (!this.isPending()) {
194
- done();
200
+ this.signal.emit('done');
195
201
  return;
196
202
  }
197
203
  const frame = this.getFrame();
@@ -357,42 +363,40 @@ class VM {
357
363
  }
358
364
  case instruction_1.OpCode.GOTO_A_IF_FALSE: {
359
365
  const condition = this.popStack();
360
- if (condition.toTruthy()) {
361
- break;
366
+ const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
367
+ if (value === 0) {
368
+ const gotoAInstruction = instruction;
369
+ frame.ip = gotoAInstruction.goto.ip;
362
370
  }
363
- const gotoAInstruction = instruction;
364
- frame.ip = gotoAInstruction.goto.ip;
365
371
  break;
366
372
  }
367
373
  case instruction_1.OpCode.GOTO_A_IF_FALSE_AND_PUSH: {
368
374
  const condition = this.popStack();
369
375
  const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
370
376
  this.pushStack(new number_1.CustomNumber(value));
371
- if (value >= 1) {
372
- break;
377
+ if (value === 0) {
378
+ const gotoAInstruction = instruction;
379
+ frame.ip = gotoAInstruction.goto.ip;
373
380
  }
374
- const gotoAInstruction = instruction;
375
- frame.ip = gotoAInstruction.goto.ip;
376
381
  break;
377
382
  }
378
383
  case instruction_1.OpCode.GOTO_A_IF_TRUE: {
379
384
  const condition = this.popStack();
380
- if (!condition.toTruthy()) {
381
- break;
385
+ const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
386
+ if (value === 1) {
387
+ const gotoAInstruction = instruction;
388
+ frame.ip = gotoAInstruction.goto.ip;
382
389
  }
383
- const gotoAInstruction = instruction;
384
- frame.ip = gotoAInstruction.goto.ip;
385
390
  break;
386
391
  }
387
392
  case instruction_1.OpCode.GOTO_A_IF_TRUE_AND_PUSH: {
388
393
  const condition = this.popStack();
389
394
  const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
390
395
  this.pushStack(new number_1.CustomNumber(value));
391
- if (value < 1) {
392
- break;
396
+ if (value === 1) {
397
+ const gotoAInstruction = instruction;
398
+ frame.ip = gotoAInstruction.goto.ip;
393
399
  }
394
- const gotoAInstruction = instruction;
395
- frame.ip = gotoAInstruction.goto.ip;
396
400
  break;
397
401
  }
398
402
  case instruction_1.OpCode.GOTO_A: {
@@ -512,8 +516,10 @@ class VM {
512
516
  if (immediateRet === null || immediateRet === void 0 ? void 0 : immediateRet.then) {
513
517
  immediateRet.then((ret) => {
514
518
  this.pushStack(ret);
515
- this.resume(done);
516
- }).catch(done);
519
+ this.signal.emit('resume');
520
+ }).catch((err) => {
521
+ this.signal.emit('done', err);
522
+ });
517
523
  return;
518
524
  }
519
525
  this.pushStack(immediateRet);
@@ -587,6 +593,15 @@ class VM {
587
593
  this.pushStack((0, evaluation_1.evalBitwiseUnsignedRightShift)(a, b));
588
594
  break;
589
595
  }
596
+ case instruction_1.OpCode.COMPARISON_GROUP: {
597
+ const comparisonGroupInstruction = instruction;
598
+ const values = [];
599
+ for (let index = 0; index <= comparisonGroupInstruction.operators.length; index++) {
600
+ values.push(this.popStack());
601
+ }
602
+ this.pushStack((0, evaluation_1.evalComparisonGroup)(values, comparisonGroupInstruction.operators));
603
+ break;
604
+ }
590
605
  case instruction_1.OpCode.ADD: {
591
606
  const b = this.popStack();
592
607
  const a = this.popStack();
@@ -689,8 +704,10 @@ class VM {
689
704
  if (this.debugger.getBreakpoint(this)) {
690
705
  this.debugger.interact(this, instruction.source);
691
706
  this.debugger.resume().then(() => {
692
- this.resume(done);
693
- }).catch(done);
707
+ this.signal.emit('resume');
708
+ }).catch((err) => {
709
+ this.signal.emit('done', err);
710
+ });
694
711
  return;
695
712
  }
696
713
  break;
@@ -702,21 +719,18 @@ class VM {
702
719
  case instruction_1.OpCode.HALT: {
703
720
  this.state = VMState.FINISHED;
704
721
  this.signal.emit('done');
705
- done();
706
722
  return;
707
723
  }
708
724
  }
709
725
  if (this.actionCount++ === this.maxActionsPerLoop) {
710
726
  this.actionCount = 0;
711
- (0, non_blocking_schedule_1.schedule)(() => {
712
- this.resume(done);
713
- });
727
+ this.signal.emit('cycle');
714
728
  return;
715
729
  }
716
730
  }
717
731
  }
718
732
  catch (err) {
719
- done(err);
733
+ this.signal.emit('done', err);
720
734
  }
721
735
  }
722
736
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greybel-interpreter",
3
- "version": "4.10.1",
3
+ "version": "5.0.0",
4
4
  "description": "Interpreter",
5
5
  "main": "dist/index",
6
6
  "typings": "dist/index",
@@ -49,7 +49,7 @@
49
49
  "typescript": "^5.0.4"
50
50
  },
51
51
  "dependencies": {
52
- "greybel-core": "~1.8.4",
52
+ "greybel-core": "~2.0.1",
53
53
  "hyperid": "^3.2.0",
54
54
  "non-blocking-schedule": "^0.1.0"
55
55
  },