greybel-interpreter 4.0.7 → 4.0.9

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.
@@ -46,17 +46,19 @@ export declare enum OpCode {
46
46
  FUNCTION_DEFINITION = 40,
47
47
  GOTO_A = 41,
48
48
  GOTO_A_IF_FALSE = 42,
49
- PUSH_ITERATOR = 43,
50
- POP_ITERATOR = 44,
51
- NEXT = 45,
52
- BITWISE_OR = 46,
53
- BITWISE_AND = 47,
54
- BITWISE_LEFT_SHIFT = 48,
55
- BITWISE_RIGHT_SHIFT = 49,
56
- BITWISE_UNSIGNED_RIGHT_SHIFT = 50,
57
- BREAKPOINT = 51,
58
- BREAKPOINT_ENABLE = 52,
59
- IMPORT = 53
49
+ GOTO_A_IF_FALSE_AND_PUSH = 43,
50
+ GOTO_A_IF_TRUE_AND_PUSH = 44,
51
+ PUSH_ITERATOR = 45,
52
+ POP_ITERATOR = 46,
53
+ NEXT = 47,
54
+ BITWISE_OR = 48,
55
+ BITWISE_AND = 49,
56
+ BITWISE_LEFT_SHIFT = 50,
57
+ BITWISE_RIGHT_SHIFT = 51,
58
+ BITWISE_UNSIGNED_RIGHT_SHIFT = 52,
59
+ BREAKPOINT = 53,
60
+ BREAKPOINT_ENABLE = 54,
61
+ IMPORT = 55
60
62
  }
61
63
  export interface FunctionDefinitionInstructionArgument {
62
64
  name: CustomString;
@@ -108,7 +110,7 @@ export interface FunctionDefinitionInstruction extends BaseInstruction {
108
110
  ignoreOuter: boolean;
109
111
  }
110
112
  export interface GotoAInstruction extends BaseInstruction {
111
- op: OpCode.GOTO_A | OpCode.GOTO_A_IF_FALSE;
113
+ op: OpCode.GOTO_A | OpCode.GOTO_A_IF_FALSE | OpCode.GOTO_A_IF_FALSE_AND_PUSH | OpCode.GOTO_A_IF_TRUE_AND_PUSH;
112
114
  goto: Instruction;
113
115
  }
114
116
  export interface NextInstruction extends BaseInstruction {
@@ -46,15 +46,17 @@ var OpCode;
46
46
  OpCode[OpCode["FUNCTION_DEFINITION"] = 40] = "FUNCTION_DEFINITION";
47
47
  OpCode[OpCode["GOTO_A"] = 41] = "GOTO_A";
48
48
  OpCode[OpCode["GOTO_A_IF_FALSE"] = 42] = "GOTO_A_IF_FALSE";
49
- OpCode[OpCode["PUSH_ITERATOR"] = 43] = "PUSH_ITERATOR";
50
- OpCode[OpCode["POP_ITERATOR"] = 44] = "POP_ITERATOR";
51
- OpCode[OpCode["NEXT"] = 45] = "NEXT";
52
- OpCode[OpCode["BITWISE_OR"] = 46] = "BITWISE_OR";
53
- OpCode[OpCode["BITWISE_AND"] = 47] = "BITWISE_AND";
54
- OpCode[OpCode["BITWISE_LEFT_SHIFT"] = 48] = "BITWISE_LEFT_SHIFT";
55
- OpCode[OpCode["BITWISE_RIGHT_SHIFT"] = 49] = "BITWISE_RIGHT_SHIFT";
56
- OpCode[OpCode["BITWISE_UNSIGNED_RIGHT_SHIFT"] = 50] = "BITWISE_UNSIGNED_RIGHT_SHIFT";
57
- OpCode[OpCode["BREAKPOINT"] = 51] = "BREAKPOINT";
58
- OpCode[OpCode["BREAKPOINT_ENABLE"] = 52] = "BREAKPOINT_ENABLE";
59
- OpCode[OpCode["IMPORT"] = 53] = "IMPORT";
49
+ OpCode[OpCode["GOTO_A_IF_FALSE_AND_PUSH"] = 43] = "GOTO_A_IF_FALSE_AND_PUSH";
50
+ OpCode[OpCode["GOTO_A_IF_TRUE_AND_PUSH"] = 44] = "GOTO_A_IF_TRUE_AND_PUSH";
51
+ OpCode[OpCode["PUSH_ITERATOR"] = 45] = "PUSH_ITERATOR";
52
+ OpCode[OpCode["POP_ITERATOR"] = 46] = "POP_ITERATOR";
53
+ OpCode[OpCode["NEXT"] = 47] = "NEXT";
54
+ OpCode[OpCode["BITWISE_OR"] = 48] = "BITWISE_OR";
55
+ OpCode[OpCode["BITWISE_AND"] = 49] = "BITWISE_AND";
56
+ OpCode[OpCode["BITWISE_LEFT_SHIFT"] = 50] = "BITWISE_LEFT_SHIFT";
57
+ OpCode[OpCode["BITWISE_RIGHT_SHIFT"] = 51] = "BITWISE_RIGHT_SHIFT";
58
+ OpCode[OpCode["BITWISE_UNSIGNED_RIGHT_SHIFT"] = 52] = "BITWISE_UNSIGNED_RIGHT_SHIFT";
59
+ OpCode[OpCode["BREAKPOINT"] = 53] = "BREAKPOINT";
60
+ OpCode[OpCode["BREAKPOINT_ENABLE"] = 54] = "BREAKPOINT_ENABLE";
61
+ OpCode[OpCode["IMPORT"] = 55] = "IMPORT";
60
62
  })(OpCode = exports.OpCode || (exports.OpCode = {}));
@@ -33,6 +33,12 @@ function generateCustomValueFromASTLiteral(node) {
33
33
  throw new Error('Unexpected literal type.');
34
34
  }
35
35
  }
36
+ function unwrap(node) {
37
+ while (node instanceof miniscript_core_1.ASTParenthesisExpression) {
38
+ node = node.expression;
39
+ }
40
+ return node;
41
+ }
36
42
  class BytecodeGenerator {
37
43
  constructor(options) {
38
44
  var _a;
@@ -333,7 +339,8 @@ class BytecodeGenerator {
333
339
  }
334
340
  processMemberExpression(node, isInvoke = true) {
335
341
  return __awaiter(this, void 0, void 0, function* () {
336
- if (node.base instanceof miniscript_core_1.ASTIdentifier && node.base.name === 'super') {
342
+ const base = unwrap(node.base);
343
+ if (base instanceof miniscript_core_1.ASTIdentifier && base.name === 'super') {
337
344
  this.push({
338
345
  op: instruction_1.OpCode.PUSH,
339
346
  source: this.getSourceLocation(node.identifier),
@@ -346,7 +353,7 @@ class BytecodeGenerator {
346
353
  });
347
354
  }
348
355
  else {
349
- yield this.processSubNode(node.base);
356
+ yield this.processSubNode(base);
350
357
  if (node.identifier instanceof miniscript_core_1.ASTIdentifier) {
351
358
  yield this.processIdentifier(node.identifier, false, isInvoke);
352
359
  }
@@ -358,16 +365,17 @@ class BytecodeGenerator {
358
365
  }
359
366
  processIndexExpression(node, isInvoke = true) {
360
367
  return __awaiter(this, void 0, void 0, function* () {
361
- if (node.base instanceof miniscript_core_1.ASTIdentifier && node.base.name === 'super') {
368
+ const base = unwrap(node.base);
369
+ if (base instanceof miniscript_core_1.ASTIdentifier && base.name === 'super') {
362
370
  yield this.processSubNode(node.index);
363
371
  this.push({
364
372
  op: instruction_1.OpCode.GET_SUPER_PROPERTY,
365
- source: this.getSourceLocation(node),
373
+ source: this.getSourceLocation(base),
366
374
  invoke: isInvoke
367
375
  });
368
376
  }
369
377
  else {
370
- yield this.processSubNode(node.base);
378
+ yield this.processSubNode(base);
371
379
  yield this.processSubNode(node.index);
372
380
  this.push({
373
381
  op: instruction_1.OpCode.GET_PROPERTY,
@@ -453,9 +461,9 @@ class BytecodeGenerator {
453
461
  }
454
462
  processAssignmentStatement(node) {
455
463
  return __awaiter(this, void 0, void 0, function* () {
456
- let variable = node.variable;
464
+ let variable = unwrap(node.variable);
457
465
  if (variable instanceof miniscript_core_1.ASTUnaryExpression) {
458
- variable = variable.argument;
466
+ variable = unwrap(variable.argument);
459
467
  }
460
468
  if (variable instanceof miniscript_core_1.ASTMemberExpression) {
461
469
  yield this.processSubNode(variable.base);
@@ -507,7 +515,25 @@ class BytecodeGenerator {
507
515
  }
508
516
  processEvaluationExpression(node) {
509
517
  return __awaiter(this, void 0, void 0, function* () {
518
+ const skip = {
519
+ op: instruction_1.OpCode.NOOP,
520
+ source: this.getSourceLocation(node)
521
+ };
510
522
  yield this.processSubNode(node.left);
523
+ if (node.operator === miniscript_core_1.Operator.And) {
524
+ this.push({
525
+ op: instruction_1.OpCode.GOTO_A_IF_FALSE_AND_PUSH,
526
+ source: this.getSourceLocation(node),
527
+ goto: skip
528
+ });
529
+ }
530
+ else if (node.operator === miniscript_core_1.Operator.Or) {
531
+ this.push({
532
+ op: instruction_1.OpCode.GOTO_A_IF_TRUE_AND_PUSH,
533
+ source: this.getSourceLocation(node),
534
+ goto: skip
535
+ });
536
+ }
511
537
  yield this.processSubNode(node.right);
512
538
  switch (node.operator) {
513
539
  case miniscript_core_1.Operator.Isa: {
@@ -564,6 +590,7 @@ class BytecodeGenerator {
564
590
  op: instruction_1.OpCode.AND,
565
591
  source: this.getSourceLocation(node)
566
592
  });
593
+ this.push(skip);
567
594
  break;
568
595
  }
569
596
  case miniscript_core_1.Operator.Or: {
@@ -571,6 +598,7 @@ class BytecodeGenerator {
571
598
  op: instruction_1.OpCode.OR,
572
599
  source: this.getSourceLocation(node)
573
600
  });
601
+ this.push(skip);
574
602
  break;
575
603
  }
576
604
  case miniscript_core_1.Operator.Plus: {
@@ -797,7 +825,7 @@ class BytecodeGenerator {
797
825
  }
798
826
  processUnaryExpression(node) {
799
827
  return __awaiter(this, void 0, void 0, function* () {
800
- const arg = node.argument;
828
+ const arg = unwrap(node.argument);
801
829
  switch (node.operator) {
802
830
  case miniscript_core_1.Operator.Reference:
803
831
  if (arg instanceof miniscript_core_1.ASTMemberExpression) {
@@ -847,9 +875,10 @@ class BytecodeGenerator {
847
875
  yield this.processSubNode(arg);
848
876
  }
849
877
  });
850
- const left = node.base;
878
+ const left = unwrap(node.base);
851
879
  if (left instanceof miniscript_core_1.ASTMemberExpression) {
852
- if (left.base instanceof miniscript_core_1.ASTIdentifier && left.base.name === 'super') {
880
+ const base = unwrap(left.base);
881
+ if (base instanceof miniscript_core_1.ASTIdentifier && base.name === 'super') {
853
882
  this.push({
854
883
  op: instruction_1.OpCode.PUSH,
855
884
  source: this.getSourceLocation(left.identifier),
@@ -863,7 +892,7 @@ class BytecodeGenerator {
863
892
  });
864
893
  }
865
894
  else {
866
- yield this.processSubNode(left.base);
895
+ yield this.processSubNode(base);
867
896
  this.push({
868
897
  op: instruction_1.OpCode.PUSH,
869
898
  source: this.getSourceLocation(left.identifier),
@@ -878,7 +907,8 @@ class BytecodeGenerator {
878
907
  }
879
908
  }
880
909
  else if (left instanceof miniscript_core_1.ASTIndexExpression) {
881
- if (left.base instanceof miniscript_core_1.ASTIdentifier && left.base.name === 'super') {
910
+ const base = unwrap(left.base);
911
+ if (base instanceof miniscript_core_1.ASTIdentifier && base.name === 'super') {
882
912
  yield this.processSubNode(left.index);
883
913
  yield pushArgs();
884
914
  this.push({
@@ -888,7 +918,7 @@ class BytecodeGenerator {
888
918
  });
889
919
  }
890
920
  else {
891
- yield this.processSubNode(left.base);
921
+ yield this.processSubNode(base);
892
922
  yield this.processSubNode(left.index);
893
923
  yield pushArgs();
894
924
  this.push({
@@ -5,6 +5,7 @@ import { CustomMap } from '../types/map';
5
5
  import { CustomNil } from '../types/nil';
6
6
  import { CustomNumber } from '../types/number';
7
7
  import { CustomString } from '../types/string';
8
+ export declare const absClamp01: (d: number) => number;
8
9
  export declare function evalAdd(a: CustomValue, b: CustomValue): CustomNil | CustomNumber | CustomString | CustomMap | CustomList;
9
10
  export declare function evalSub(a: CustomValue, b: CustomValue): CustomValue | CustomNumber;
10
11
  export declare function evalMul(a: CustomValue, b: CustomValue): CustomValue | CustomNumber;
@@ -1,6 +1,6 @@
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 = void 0;
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;
4
4
  const boolean_1 = require("../types/boolean");
5
5
  const default_1 = require("../types/default");
6
6
  const function_1 = require("../types/function");
@@ -17,6 +17,7 @@ const absClamp01 = (d) => {
17
17
  return 1;
18
18
  return d;
19
19
  };
20
+ exports.absClamp01 = absClamp01;
20
21
  function evalAdd(a, b) {
21
22
  if (a instanceof string_1.CustomString || b instanceof string_1.CustomString) {
22
23
  if (a instanceof nil_1.CustomNil)
@@ -330,12 +331,12 @@ exports.evalPow = evalPow;
330
331
  function evalAnd(a, b) {
331
332
  const left = Number(a instanceof number_1.CustomNumber ? a.toNumber() : a.toTruthy());
332
333
  const right = Number(b instanceof number_1.CustomNumber ? b.toNumber() : b.toTruthy());
333
- return new number_1.CustomNumber(absClamp01(left * right));
334
+ return new number_1.CustomNumber((0, exports.absClamp01)(left * right));
334
335
  }
335
336
  exports.evalAnd = evalAnd;
336
337
  function evalOr(a, b) {
337
338
  const left = Number(a instanceof number_1.CustomNumber ? a.toNumber() : a.toTruthy());
338
339
  const right = Number(b instanceof number_1.CustomNumber ? b.toNumber() : b.toTruthy());
339
- return new number_1.CustomNumber(absClamp01(left + right - left * right));
340
+ return new number_1.CustomNumber((0, exports.absClamp01)(left + right - left * right));
340
341
  }
341
342
  exports.evalOr = evalOr;
package/dist/vm.d.ts CHANGED
@@ -36,7 +36,7 @@ export interface VMOptions {
36
36
  debugger: Debugger;
37
37
  environmentVariables?: Map<string, string>;
38
38
  imports?: Map<string, Instruction[]>;
39
- frames?: Stack<OperationContext>;
39
+ externalFrames?: Stack<OperationContext>;
40
40
  }
41
41
  export declare class VM {
42
42
  private readonly ACTIONS_PER_LOOP;
@@ -55,6 +55,7 @@ export declare class VM {
55
55
  readonly handler: HandlerContainer;
56
56
  readonly debugger: Debugger;
57
57
  readonly imports: Map<string, Instruction[]>;
58
+ readonly externalFrames: Stack<OperationContext>;
58
59
  constructor(options: VMOptions);
59
60
  getTime(): number;
60
61
  isPending(): boolean;
package/dist/vm.js CHANGED
@@ -96,13 +96,14 @@ class VM {
96
96
  this.sp = 0;
97
97
  this.time = -1;
98
98
  this.target = options.target;
99
- this.frames = (_a = options.frames) !== null && _a !== void 0 ? _a : new stack_1.Stack(options.globals);
99
+ this.frames = new stack_1.Stack(options.globals);
100
100
  this.contextTypeIntrinsics = options.contextTypeIntrinsics;
101
101
  this.handler = options.handler;
102
102
  this.debugger = options.debugger;
103
- this.environmentVariables = (_b = options.environmentVariables) !== null && _b !== void 0 ? _b : new Map();
103
+ this.environmentVariables = (_a = options.environmentVariables) !== null && _a !== void 0 ? _a : new Map();
104
104
  this.iterators = new stack_1.Stack();
105
- this.imports = (_c = options.imports) !== null && _c !== void 0 ? _c : new Map();
105
+ this.imports = (_b = options.imports) !== null && _b !== void 0 ? _b : new Map();
106
+ this.externalFrames = (_c = options.externalFrames) !== null && _c !== void 0 ? _c : new stack_1.Stack();
106
107
  }
107
108
  getTime() {
108
109
  return this.time;
@@ -111,10 +112,14 @@ class VM {
111
112
  return this.state === VMState.PENDING;
112
113
  }
113
114
  getStacktrace() {
115
+ const externalFrames = this.externalFrames.values();
114
116
  const frames = this.frames.values();
115
117
  const stacktrace = [];
116
- for (let index = frames.length - 1; index >= 0; index--) {
117
- stacktrace.push(frames[index].getCurrentInstruction());
118
+ for (let index = 0; index < externalFrames.length; index++) {
119
+ stacktrace.push(externalFrames[index].getCurrentInstruction());
120
+ }
121
+ for (let index = 0; index < frames.length; index++) {
122
+ stacktrace.unshift(frames[index].getCurrentInstruction());
118
123
  }
119
124
  return stacktrace;
120
125
  }
@@ -367,6 +372,28 @@ class VM {
367
372
  frame.ip = gotoAInstruction.goto.ip;
368
373
  break;
369
374
  }
375
+ case instruction_1.OpCode.GOTO_A_IF_FALSE_AND_PUSH: {
376
+ const condition = this.popStack();
377
+ const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
378
+ this.pushStack(new number_1.CustomNumber(value));
379
+ if (value >= 1) {
380
+ break;
381
+ }
382
+ const gotoAInstruction = instruction;
383
+ frame.ip = gotoAInstruction.goto.ip;
384
+ break;
385
+ }
386
+ case instruction_1.OpCode.GOTO_A_IF_TRUE_AND_PUSH: {
387
+ const condition = this.popStack();
388
+ const value = condition instanceof number_1.CustomNumber ? (0, evaluation_1.absClamp01)(condition.value) : +condition.toTruthy();
389
+ this.pushStack(new number_1.CustomNumber(value));
390
+ if (value < 1) {
391
+ break;
392
+ }
393
+ const gotoAInstruction = instruction;
394
+ frame.ip = gotoAInstruction.goto.ip;
395
+ break;
396
+ }
370
397
  case instruction_1.OpCode.GOTO_A: {
371
398
  const gotoAInstruction = instruction;
372
399
  frame.ip = gotoAInstruction.goto.ip;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greybel-interpreter",
3
- "version": "4.0.7",
3
+ "version": "4.0.9",
4
4
  "description": "Interpreter",
5
5
  "main": "dist/index",
6
6
  "typings": "dist/index",