UNPKG

361 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var Ast = require('ts-simple-ast');
8var Ast__default = _interopDefault(Ast);
9var stringify = _interopDefault(require('safe-stable-stringify'));
10var _ = _interopDefault(require('lodash'));
11var clientCore = require('@neo-one/client-core');
12var BN = _interopDefault(require('bn.js'));
13var path = require('path');
14var path__default = _interopDefault(path);
15require('app-root-dir');
16var fs = require('fs-extra');
17var Blockchain = _interopDefault(require('@neo-one/node-blockchain'));
18var levelup = _interopDefault(require('levelup'));
19var levelUpStorage = _interopDefault(require('@neo-one/node-storage-levelup'));
20var memdown = _interopDefault(require('memdown'));
21var nodeNeoSettings = require('@neo-one/node-neo-settings');
22var vm = _interopDefault(require('@neo-one/node-vm'));
23
24function _defineProperty(obj, key, value) {
25 if (key in obj) {
26 Object.defineProperty(obj, key, {
27 value: value,
28 enumerable: true,
29 configurable: true,
30 writable: true
31 });
32 } else {
33 obj[key] = value;
34 }
35
36 return obj;
37}
38
39function _objectSpread(target) {
40 for (var i = 1; i < arguments.length; i++) {
41 var source = arguments[i] != null ? arguments[i] : {};
42 var ownKeys = Object.keys(source);
43
44 if (typeof Object.getOwnPropertySymbols === 'function') {
45 ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
46 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
47 }));
48 }
49
50 ownKeys.forEach(function (key) {
51 _defineProperty(target, key, source[key]);
52 });
53 }
54
55 return target;
56}
57
58class JumpTable {
59 constructor() {
60 Object.defineProperty(this, "jumpNumber", {
61 configurable: true,
62 enumerable: true,
63 writable: true,
64 value: 0
65 });
66 Object.defineProperty(this, "table", {
67 configurable: true,
68 enumerable: true,
69 writable: true,
70 value: []
71 });
72 }
73
74 add(sb, node, body) {
75 const jumpNumber = this.jumpNumber;
76 this.jumpNumber += 1;
77 const {
78 bytecode
79 } = sb.capture(() => {
80 body();
81 });
82 this.table.push({
83 jumpNumber,
84 node,
85 bytecode
86 });
87 return jumpNumber;
88 }
89
90 emitTable(sb, outerNode) {
91 // TODO: Binary search over table - O(logn) ops vs O(n) currently
92 this.table.forEach(({
93 node,
94 jumpNumber,
95 bytecode
96 }) => {
97 sb.emitHelper(node, {}, sb.helpers.if({
98 condition: () => {
99 sb.emitOp(node, 'DUP');
100 sb.emitPushInt(node, jumpNumber);
101 sb.emitOp(node, 'NUMEQUAL');
102 },
103 whenTrue: () => {
104 sb.emitOp(node, 'DROP');
105 sb.emitBytecode(bytecode);
106 }
107 }));
108 });
109 sb.emitOp(outerNode, 'THROW');
110 }
111
112}
113
114class ProgramCounter {}
115
116class DeferredProgramCounter extends ProgramCounter {
117 constructor(offset) {
118 super();
119 this.offset = offset;
120 Object.defineProperty(this, "pc", {
121 configurable: true,
122 enumerable: true,
123 writable: true,
124 value: void 0
125 });
126 }
127
128 plus(offset) {
129 return new DeferredProgramCounter((this.offset || 0) + offset);
130 }
131
132 equals(other) {
133 return this === other;
134 }
135
136 setPC(pc) {
137 this.pc = pc;
138 }
139
140 getPC() {
141 if (this.pc == null) {
142 throw new Error('Unknown PC');
143 }
144
145 return this.pc.getPC() + (this.offset || 0);
146 }
147
148}
149
150class Jump {
151 constructor(op, pc) {
152 this.op = op;
153 this.pc = pc;
154 }
155
156}
157
158class Call extends Jump {
159 constructor(pc) {
160 super('CALL', pc);
161 }
162
163 plus(pc) {
164 return new Call(this.pc.plus(pc));
165 }
166
167}
168
169class Jmp extends Jump {
170 constructor(op, pc) {
171 super(op, pc);
172 }
173
174 plus(pc) {
175 return new Jmp(this.op, this.pc.plus(pc));
176 }
177
178}
179
180class KnownProgramCounter extends ProgramCounter {
181 constructor(pc) {
182 super();
183 this.pc = pc;
184 }
185
186 plus(offset) {
187 return new KnownProgramCounter(this.pc + offset);
188 }
189
190 equals(other) {
191 return other instanceof KnownProgramCounter && this.pc === other.pc;
192 }
193
194 getPC() {
195 return this.pc;
196 }
197
198}
199
200class LastProgramCounter extends ProgramCounter {
201 constructor(startPC, offset) {
202 super();
203 this.startPC = startPC;
204 this.offset = offset;
205 Object.defineProperty(this, "pc", {
206 configurable: true,
207 enumerable: true,
208 writable: true,
209 value: void 0
210 });
211 Object.defineProperty(this, "children", {
212 configurable: true,
213 enumerable: true,
214 writable: true,
215 value: []
216 });
217 }
218
219 plus(offset) {
220 const pc = new LastProgramCounter(this.startPC, (this.offset || 0) + offset);
221 this.children.push(pc);
222
223 if (this.pc != null) {
224 pc.setPC(this.pc);
225 }
226
227 return pc;
228 }
229
230 equals(other) {
231 return other instanceof LastProgramCounter && this.startPC === other.startPC && this.offset === other.offset;
232 }
233
234 setPC(pc) {
235 this.pc = pc;
236 this.children.forEach(child => {
237 child.setPC(pc);
238 });
239 }
240
241 getPC() {
242 if (this.pc == null) {
243 throw new Error('Unknown PC');
244 }
245
246 return this.pc + (this.offset || 0);
247 }
248
249}
250
251class ProgramCounterHelper {
252 constructor(pc) {
253 Object.defineProperty(this, "pc", {
254 configurable: true,
255 enumerable: true,
256 writable: true,
257 value: void 0
258 });
259 Object.defineProperty(this, "first", {
260 configurable: true,
261 enumerable: true,
262 writable: true,
263 value: void 0
264 });
265 Object.defineProperty(this, "last", {
266 configurable: true,
267 enumerable: true,
268 writable: true,
269 value: void 0
270 });
271 this.pc = pc;
272 this.first = new KnownProgramCounter(this.pc());
273 this.last = new LastProgramCounter(this.pc());
274 }
275
276 getFirst() {
277 return this.first;
278 }
279
280 getCurrent() {
281 return new KnownProgramCounter(this.pc());
282 }
283
284 getLast() {
285 return this.last;
286 }
287
288 setLast() {
289 this.last.setPC(this.pc());
290 }
291
292}
293
294class NodeCompiler {
295 constructor() {
296 Object.defineProperty(this, "kind", {
297 configurable: true,
298 enumerable: true,
299 writable: true,
300 value: void 0
301 });
302 }
303
304}
305
306class Helper {
307 emitGlobal(sb, node, options) {// do nothing
308 }
309
310}
311
312// Input: [array]
313// Output: [array]
314class ArrFilterHelper extends Helper {
315 constructor(options) {
316 super();
317 Object.defineProperty(this, "map", {
318 configurable: true,
319 enumerable: true,
320 writable: true,
321 value: void 0
322 });
323 Object.defineProperty(this, "withIndex", {
324 configurable: true,
325 enumerable: true,
326 writable: true,
327 value: void 0
328 });
329 this.map = options.map;
330 this.withIndex = options.withIndex || false;
331 }
332
333 emit(sb, node, options) {
334 if (!options.pushValue) {
335 sb.emitOp(node, 'DROP');
336 return;
337 } // [size, ...array]
338
339
340 sb.emitOp(node, 'UNPACK'); // [0, size, ...array]
341
342 sb.emitPushInt(node, 0); // [arr, size, ...array]
343
344 sb.emitOp(node, 'NEWARRAY'); // [size, arr, ...array]
345
346 sb.emitOp(node, 'SWAP'); // [idx, size, arr, ...array]
347
348 sb.emitPushInt(node, 0);
349 sb.emitHelper(node, options, sb.helpers.forLoop({
350 condition: () => {
351 // [size, idx, arr, ...array]
352 sb.emitOp(node, 'SWAP'); // [size, idx, size, arr, ...array]
353
354 sb.emitOp(node, 'TUCK'); // [idx, size, idx, size, arr, ...array]
355
356 sb.emitOp(node, 'OVER'); // size > idx
357 // [size > idx, idx, size, arr, ...array]
358
359 sb.emitOp(node, 'GT');
360 },
361 each: () => {
362 // [arr, idx, size, ...array]
363 sb.emitOp(node, 'ROT'); // [idx, arr, idx, size, ...array]
364
365 sb.emitOp(node, 'OVER');
366
367 if (this.withIndex) {
368 // [4, idx, arr, idx, size, ...array]
369 sb.emitPushInt(node, 4); // [value, idx, arr, idx, size, ...array]
370
371 sb.emitOp(node, 'ROLL'); // [value, idx, value, arr, idx, size, ...array]
372
373 sb.emitOp(node, 'TUCK');
374 } else {
375 // [3, arr, idx, size, ...array]
376 sb.emitPushInt(node, 3); // [value, arr, idx, size, ...array]
377
378 sb.emitOp(node, 'ROLL'); // [value, value, arr, idx, size, ...array]
379
380 sb.emitOp(node, 'DUP');
381 }
382
383 sb.emitHelper(node, options, sb.helpers.if({
384 condition: () => {
385 // [keepVal, value, arr, idx, size, ...array]
386 this.map(); // TODO: This should be toBoolean
387 // [keep, value, arr, idx, size, ...array]
388
389 sb.emitHelper(node, options, sb.helpers.getBoolean);
390 },
391 whenTrue: () => {
392 // [arr, value, arr, idx, size, ...array]
393 sb.emitOp(node, 'OVER'); // [value, arr, arr, idx, size, ...array]
394
395 sb.emitOp(node, 'SWAP'); // [arr, idx, size, ...array]
396
397 sb.emitOp(node, 'APPEND');
398 },
399 whenFalse: () => {
400 // [arr, idx, size, ...array]
401 sb.emitOp(node, 'DROP');
402 }
403 })); // [size, arr, idx, ...array]
404
405 sb.emitOp(node, 'ROT'); // [idx, size, arr, ...array]
406
407 sb.emitOp(node, 'ROT');
408 },
409 incrementor: () => {
410 // [idx, size, arr, ...array]
411 sb.emitOp(node, 'INC');
412 }
413 })); // [size, arr]
414
415 sb.emitOp(node, 'DROP'); // [arr]
416
417 sb.emitOp(node, 'DROP');
418 }
419
420}
421
422// Input: [array]
423// Output: []
424class ArrForEachHelper extends Helper {
425 constructor(options) {
426 super();
427 Object.defineProperty(this, "each", {
428 configurable: true,
429 enumerable: true,
430 writable: true,
431 value: void 0
432 });
433 Object.defineProperty(this, "withIndex", {
434 configurable: true,
435 enumerable: true,
436 writable: true,
437 value: void 0
438 });
439 this.each = options.each;
440 this.withIndex = options.withIndex || false;
441 }
442
443 emit(sb, node, options) {
444 if (!options.pushValue) {
445 sb.emitOp(node, 'DROP');
446 return;
447 } // [size, ...array]
448
449
450 sb.emitOp(node, 'UNPACK'); // [idx, size, ...array]
451
452 sb.emitPushInt(node, 0);
453 sb.emitHelper(node, options, sb.helpers.forLoop({
454 condition: () => {
455 // [size, idx, ...array]
456 sb.emitOp(node, 'SWAP'); // [size, idx, size, ...array]
457
458 sb.emitOp(node, 'TUCK'); // [idx, size, idx, size, ...array]
459
460 sb.emitOp(node, 'OVER'); // size > idx
461 // [size > idx, idx, size, ...array]
462
463 sb.emitOp(node, 'GT');
464 },
465 each: () => {
466 // [value, idx, size, ...array]
467 sb.emitOp(node, 'ROT');
468
469 if (this.withIndex) {
470 // [idx, value, idx, size, ...array]
471 sb.emitOp(node, 'OVER'); // [value, idx, idx, size, ...array]
472
473 sb.emitOp(node, 'SWAP');
474 } // [idx, size, ...array]
475
476
477 this.each();
478 },
479 incrementor: () => {
480 // [idx, size, ...array]
481 sb.emitOp(node, 'INC');
482 }
483 })); // [size]
484
485 sb.emitOp(node, 'DROP'); // []
486
487 sb.emitOp(node, 'DROP');
488 }
489
490}
491
492// Input: [array]
493// Output: [array]
494class ArrMapHelper extends Helper {
495 constructor(options) {
496 super();
497 Object.defineProperty(this, "map", {
498 configurable: true,
499 enumerable: true,
500 writable: true,
501 value: void 0
502 });
503 Object.defineProperty(this, "withIndex", {
504 configurable: true,
505 enumerable: true,
506 writable: true,
507 value: void 0
508 });
509 this.map = options.map;
510 this.withIndex = options.withIndex || false;
511 }
512
513 emit(sb, node, options) {
514 if (!options.pushValue) {
515 sb.emitOp(node, 'DROP');
516 return;
517 } // [size, ...array]
518
519
520 sb.emitOp(node, 'UNPACK'); // [idx, size, ...array]
521
522 sb.emitPushInt(node, 0);
523 sb.emitHelper(node, options, sb.helpers.forLoop({
524 condition: () => {
525 // [size, idx, ...array]
526 sb.emitOp(node, 'SWAP'); // [size, idx, size, ...array]
527
528 sb.emitOp(node, 'TUCK'); // [idx, size, idx, size, ...array]
529
530 sb.emitOp(node, 'OVER'); // size > idx
531 // [size > idx, idx, size, ...array]
532
533 sb.emitOp(node, 'GT');
534 },
535 each: () => {
536 // [idx, idx, size, ...array]
537 sb.emitOp(node, 'DUP'); // [3, idx, idx, size, ...array]
538
539 sb.emitPushInt(node, 3); // [idx + 3, idx, size, ...array]
540
541 sb.emitOp(node, 'ADD');
542
543 if (this.withIndex) {
544 // [idx, idx + 3, idx, size, ...array]
545 sb.emitOp(node, 'OVER'); // [idx, idx, idx + 3, idx, size, ...array]
546
547 sb.emitOp(node, 'DUP'); // [4, idx, idx, idx + 3, idx, size, ...array]
548
549 sb.emitPushInt(node, 4); // [idx + 4, idx, idx + 3, idx, size, ...array]
550
551 sb.emitOp(node, 'ADD'); // [value, idx, idx + 3, idx, size, ...array]
552
553 sb.emitOp(node, 'ROLL');
554 } else {
555 // [idx + 3, idx + 3, idx, size, ...array]
556 sb.emitOp(node, 'DUP'); // [value, idx + 3, idx, size, ...array]
557
558 sb.emitOp(node, 'ROLL');
559 } // [value, idx + 3, idx, size, ...array]
560
561
562 this.map(); // [idx + 3, value, idx, size, ...array]
563
564 sb.emitOp(node, 'SWAP'); // [value, idx, size, ...array]
565
566 sb.emitOp(node, 'XTUCK'); // [idx, size, ...array]
567
568 sb.emitOp(node, 'DROP');
569 },
570 incrementor: () => {
571 // [idx, size, ...array]
572 sb.emitOp(node, 'INC');
573 }
574 })); // [size, ...array]
575
576 sb.emitOp(node, 'DROP'); // [array]
577
578 sb.emitOp(node, 'PACK');
579 }
580
581}
582
583// Input: [array]
584// Output: [array]
585class CloneArrayHelper extends Helper {
586 emit(sb, node, options) {
587 if (!options.pushValue) {
588 sb.emitOp(node, 'DROP');
589 return;
590 } // [array]
591
592
593 sb.emitOp(node, 'UNPACK'); // [...array]
594
595 sb.emitOp(node, 'PACK');
596 }
597
598}
599
600// Input: [length, arr]
601// Output: []
602class ExtendArrayHelper extends Helper {
603 emit(sb, node, optionsIn) {
604 const options = sb.pushValueOptions(optionsIn); // [arr, length, arr]
605
606 sb.emitOp(node, 'OVER'); // [currentLength, length, arr]
607
608 sb.emitOp(node, 'ARRAYSIZE');
609 sb.emitHelper(node, options, sb.helpers.forLoop({
610 condition: () => {
611 // [currentLength, length, currentLength, arr]
612 sb.emitOp(node, 'TUCK'); // [length, currentLength, length, currentLength, arr]
613
614 sb.emitOp(node, 'OVER'); // [expectedLengthGTCurrentLength, length, currentLength, arr]
615
616 sb.emitOp(node, 'LT');
617 },
618 each: () => {
619 // [arr, length, currentLength]
620 sb.emitOp(node, 'ROT'); // [arr, arr, length, currentLength]
621
622 sb.emitOp(node, 'DUP'); // [undefinedVal, arr, arr, length, currentLength]
623
624 sb.emitHelper(node, options, sb.helpers.createUndefined); // [arr, length, currentLength]
625
626 sb.emitOp(node, 'APPEND');
627 },
628 incrementor: () => {
629 // [currentLength, arr, length]
630 sb.emitOp(node, 'ROT'); // [currentLength, arr, length]
631
632 sb.emitOp(node, 'INC'); // [length, currentLength, arr]
633
634 sb.emitOp(node, 'ROT'); // [currentLength, length, arr]
635
636 sb.emitOp(node, 'SWAP');
637 }
638 })); // [length, arr]
639
640 sb.emitOp(node, 'DROP'); // [arr]
641
642 sb.emitOp(node, 'DROP'); // []
643
644 sb.emitOp(node, 'DROP');
645 }
646
647}
648
649// Input: [val]
650// Output: []
651class ForTypeHelper extends Helper {
652 constructor({
653 types,
654 defaultCase
655 }) {
656 super();
657 Object.defineProperty(this, "types", {
658 configurable: true,
659 enumerable: true,
660 writable: true,
661 value: void 0
662 });
663 Object.defineProperty(this, "defaultCase", {
664 configurable: true,
665 enumerable: true,
666 writable: true,
667 value: void 0
668 });
669 this.types = types;
670 this.defaultCase = defaultCase;
671 }
672
673 emit(sb, node, optionsIn) {
674 const noCastOptions = sb.noCastOptions(optionsIn);
675 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn));
676 let type = optionsIn.cast;
677
678 if (type == null) {
679 type = sb.getType(node);
680 }
681
682 const types = this.types.filter(testType => testType.isType(type));
683
684 const defaultCase = this.defaultCase || (innerOptions => {
685 sb.emitOp(node, 'DROP');
686 sb.emitHelper(node, innerOptions, sb.helpers.throwTypeError);
687 });
688
689 if (types.length === 0) {
690 defaultCase(noCastOptions);
691 } else if (types.length === 1) {
692 types[0].process(noCastOptions);
693 } else {
694 sb.emitHelper(node, options, sb.helpers.case(types.map(forType => ({
695 condition: () => {
696 sb.emitOp(node, 'DUP');
697 forType.isRuntimeType(options);
698 },
699 whenTrue: () => {
700 forType.process(noCastOptions);
701 }
702 })), () => {
703 defaultCase(noCastOptions);
704 }));
705 }
706 }
707
708}
709
710let SerializableType;
711
712(function (SerializableType) {
713 SerializableType[SerializableType["Array"] = 7] = "Array";
714 SerializableType[SerializableType["Buffer"] = 8] = "Buffer";
715})(SerializableType || (SerializableType = {}));
716
717const invokeGlobal = (sb, node, options, name) => {
718 // [1, val]
719 sb.emitPushInt(node, 1); // [argsarr]
720
721 sb.emitOp(node, 'PACK'); // [globalObjectVal, argsarr]
722
723 sb.scope.getGlobal(sb, node, options); // [name, globalObjectVal, argsarr]
724
725 sb.emitPushString(node, name); // [objectVal, argsarr]
726
727 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty); // [val]
728
729 sb.emitHelper(node, options, sb.helpers.invokeCall());
730};
731
732const SERIALIZE_NAME = 'genericSerialize';
733const invokeSerialize = (sb, node, options) => invokeGlobal(sb, node, options, SERIALIZE_NAME);
734const DESERIALIZE_NAME = 'genericDeserialize';
735const invokeDeserialize = (sb, node, options) => invokeGlobal(sb, node, options, DESERIALIZE_NAME);
736const serializeType = (sb, node, options, type) => {
737 // [type, arr]
738 sb.emitPushInt(node, type); // [2, type, arr]
739
740 sb.emitPushInt(node, 2); // [arr]
741
742 sb.emitOp(node, 'PACK');
743};
744const deserializeType = (sb, node, options) => {
745 // [1, arr]
746 sb.emitPushInt(node, 1); // [value]
747
748 sb.emitOp(node, 'PICKITEM');
749};
750
751const isSerializedType = (sb, node, options, type) => {
752 // [0, val]
753 sb.emitPushInt(node, 0); // [type]
754
755 sb.emitOp(node, 'PICKITEM'); // [type, type]
756
757 sb.emitPushInt(node, type); // [isSerializedType]
758
759 sb.emitOp(node, 'NUMEQUAL');
760};
761
762const getTypes = (sb, node, options) => [{
763 isRuntimeType: () => {
764 // [isBoolean]
765 sb.emitHelper(node, options, sb.helpers.isBoolean);
766 },
767 serialize: () => {// do nothing
768 },
769 isSerializedType: () => {
770 // [isBoolean]
771 sb.emitHelper(node, options, sb.helpers.isBoolean);
772 },
773 deserialize: () => {// do nothing
774 }
775}, {
776 isRuntimeType: () => {
777 // [isString]
778 sb.emitHelper(node, options, sb.helpers.isString);
779 },
780 serialize: () => {// do nothing
781 },
782 isSerializedType: () => {
783 // [isString]
784 sb.emitHelper(node, options, sb.helpers.isString);
785 },
786 deserialize: () => {// do nothing
787 }
788}, {
789 isRuntimeType: () => {
790 // [isNumber]
791 sb.emitHelper(node, options, sb.helpers.isNumber);
792 },
793 serialize: () => {// do nothing
794 },
795 isSerializedType: () => {
796 // [isNumber]
797 sb.emitHelper(node, options, sb.helpers.isNumber);
798 },
799 deserialize: () => {// do nothing
800 }
801}, {
802 isRuntimeType: () => {
803 // [Array, val]
804 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
805 property: 'Buffer'
806 })); // [val instanceof Array]
807
808 sb.emitHelper(node, options, sb.helpers.instanceof);
809 },
810 serialize: () => {
811 // [bytearray]
812 sb.emitHelper(node, options, sb.helpers.unwrapBuffer); // [arr]
813
814 serializeType(sb, node, options, SerializableType.Buffer);
815 },
816 isSerializedType: () => {
817 isSerializedType(sb, node, options, SerializableType.Buffer);
818 },
819 deserialize: () => {
820 deserializeType(sb, node, options); // [val]
821
822 sb.emitHelper(node, options, sb.helpers.wrapBuffer);
823 }
824}, {
825 isRuntimeType: () => {
826 // [Array, val]
827 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
828 property: 'Array'
829 })); // [val instanceof Array]
830
831 sb.emitHelper(node, options, sb.helpers.instanceof);
832 },
833 serialize: () => {
834 // [arr]
835 sb.emitHelper(node, options, sb.helpers.unwrapArray); // [arr]
836
837 sb.emitHelper(node, options, sb.helpers.arrMap({
838 map: () => {
839 invokeSerialize(sb, node, options);
840 }
841 })); // [value]
842
843 serializeType(sb, node, options, SerializableType.Array);
844 },
845 isSerializedType: () => {
846 isSerializedType(sb, node, options, SerializableType.Array);
847 },
848 deserialize: () => {
849 // [arr]
850 deserializeType(sb, node, options); // [arr]
851
852 sb.emitHelper(node, options, sb.helpers.arrMap({
853 map: () => {
854 invokeDeserialize(sb, node, options);
855 }
856 })); // [val]
857
858 sb.emitHelper(node, options, sb.helpers.wrapArray);
859 }
860}];
861
862// Input: []
863// Output: [argsArray]
864class ArgumentsHelper extends Helper {
865 emit(sb, node, options) {
866 // Push the arguments
867 const args = [...node.getArguments()].reverse();
868
869 for (const arg of args) {
870 sb.visit(arg, sb.pushValueOptions(options));
871 } // [length, ...args]
872
873
874 sb.emitPushInt(node, args.length); // [argsarr]
875
876 sb.emitOp(node, 'PACK');
877 }
878
879}
880
881let InternalFunctionProperties;
882
883(function (InternalFunctionProperties) {
884 InternalFunctionProperties["CALL"] = "call";
885 InternalFunctionProperties["CONSTRUCT"] = "construct";
886})(InternalFunctionProperties || (InternalFunctionProperties = {}));
887
888// Output: [objectVal]
889
890// Input: [objectVal, this]
891// Output: [objectVal]
892class BindFunctionObjectThisHelper extends Helper {
893 constructor(options) {
894 super();
895 Object.defineProperty(this, "property", {
896 configurable: true,
897 enumerable: true,
898 writable: true,
899 value: void 0
900 });
901 Object.defineProperty(this, "both", {
902 configurable: true,
903 enumerable: true,
904 writable: true,
905 value: void 0
906 });
907 Object.defineProperty(this, "overwrite", {
908 configurable: true,
909 enumerable: true,
910 writable: true,
911 value: void 0
912 });
913
914 if (options.type === 'both') {
915 this.property = InternalFunctionProperties.CALL;
916 this.both = true;
917 } else {
918 this.property = options.property;
919 this.both = false;
920 }
921
922 this.overwrite = options.overwrite;
923 }
924
925 emit(sb, node, options) {
926 if (!options.pushValue) {
927 sb.emitOp(node, 'DROP');
928 return;
929 } // [objectVal, this]
930
931
932 sb.emitHelper(node, options, sb.helpers.cloneFunctionObject(this.both ? {
933 type: 'both'
934 } : {
935 type: 'single',
936 property: this.property
937 })); // [this, objectVal]
938
939 sb.emitOp(node, 'SWAP');
940
941 if (this.both) {
942 this.bindThis(sb, node, options, InternalFunctionProperties.CALL);
943 this.bindThis(sb, node, options, InternalFunctionProperties.CONSTRUCT);
944 } else {
945 this.bindThis(sb, node, options, this.property);
946 }
947
948 sb.emitOp(node, 'DROP');
949 }
950
951 bindThis(sb, node, options, property) {
952 // [this, objectVal, this]
953 sb.emitOp(node, 'TUCK'); // [objectVal, this, objectVal, this]
954
955 sb.emitOp(node, 'OVER'); // [property, objectVal, this, objectVal, this]
956
957 sb.emitPushString(node, property); // [func, this, objectVal, this]
958
959 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty); // [func, objectVal, this]
960
961 sb.emitHelper(node, options, sb.helpers.bindFunctionThis({
962 overwrite: this.overwrite
963 })); // [objectVal, this]
964
965 sb.emitOp(node, 'DROP'); // [this, objectVal]
966
967 sb.emitOp(node, 'SWAP');
968 }
969
970}
971
972// Input: [func, this]
973// Output: [func]
974class BindFunctionThisHelper extends Helper {
975 constructor(options) {
976 super();
977 Object.defineProperty(this, "overwrite", {
978 configurable: true,
979 enumerable: true,
980 writable: true,
981 value: void 0
982 });
983 this.overwrite = options.overwrite;
984 }
985
986 emit(sb, node, options) {
987 if (!options.pushValue) {
988 sb.emitOp(node, 'DROP');
989 sb.emitOp(node, 'DROP');
990 return;
991 }
992
993 let whenTrue;
994
995 if (this.overwrite) {
996 whenTrue = () => {
997 // [this, func, func]
998 sb.emitOp(node, 'SWAP'); // [2, this, func, func]
999
1000 sb.emitPushInt(node, 2); // [func]
1001
1002 sb.emitOp(node, 'SETITEM');
1003 };
1004 } else {
1005 whenTrue = () => {
1006 // [this, func]
1007 sb.emitOp(node, 'DROP'); // [func]
1008
1009 sb.emitOp(node, 'DROP');
1010 };
1011 } // [func, this]
1012
1013
1014 sb.emitHelper(node, options, sb.helpers.cloneFunction); // [func, this, func]
1015
1016 sb.emitOp(node, 'TUCK'); // [func, func, this, func]
1017
1018 sb.emitOp(node, 'DUP'); // [func]
1019
1020 sb.emitHelper(node, options, sb.helpers.if({
1021 condition: () => {
1022 // [size, func, this, func]
1023 sb.emitOp(node, 'ARRAYSIZE'); // [3, size, func, this, func]
1024
1025 sb.emitPushInt(node, 3); // [hasThis, func, this, func]
1026
1027 sb.emitOp(node, 'NUMEQUAL');
1028 },
1029 whenTrue,
1030 whenFalse: () => {
1031 // [this, func, func]
1032 sb.emitOp(node, 'SWAP'); // [func]
1033
1034 sb.emitOp(node, 'APPEND');
1035 }
1036 }));
1037 }
1038
1039}
1040
1041class CallHelper extends Helper {
1042 emit(sb, node, optionsIn) {
1043 const options = sb.pushValueOptions(optionsIn); // Push the scopes and this to the alt stack
1044 // [func, func]
1045
1046 sb.emitOp(node, 'DUP'); // [1, func, func]
1047
1048 sb.emitPushInt(node, 1); // [[scopes, this], func]
1049
1050 sb.emitOp(node, 'PICKITEM'); // [[scopes, this], func]
1051
1052 sb.emitHelper(node, options, sb.helpers.cloneArray); // [[scopes, this], [scopes, this], func]
1053
1054 sb.emitOp(node, 'DUP'); // [0, [scopes, this], [scopes, this], func]
1055
1056 sb.emitPushInt(node, 0); // [[scopes, this], 0, [scopes, this], [scopes, this], func]
1057
1058 sb.emitOp(node, 'OVER'); // [0, [scopes, this], 0, [scopes, this], [scopes, this], func]
1059
1060 sb.emitPushInt(node, 0); // [scopes, 0, [scopes, this], [scopes, this], func]
1061
1062 sb.emitOp(node, 'PICKITEM'); // [scopes, 0, [scopes, this], [scopes, this], func]
1063
1064 sb.emitHelper(node, options, sb.helpers.cloneArray); // [[scopes, this], func]
1065
1066 sb.emitOp(node, 'SETITEM'); // [func, [scopes, this], func]
1067
1068 sb.emitOp(node, 'OVER'); // [[scopes, this], func]
1069
1070 sb.emitHelper(node, options, sb.helpers.if({
1071 condition: () => {
1072 // [size, [scopes, this], func]
1073 sb.emitOp(node, 'ARRAYSIZE'); // [3, size, [scopes, this], func]
1074
1075 sb.emitPushInt(node, 3); // [size === 3, [scopes, this], func]
1076
1077 sb.emitOp(node, 'NUMEQUAL');
1078 },
1079 whenTrue: () => {
1080 // [func, [scopes, this], func]
1081 sb.emitOp(node, 'OVER'); // [2, func, [scopes, this], func]
1082
1083 sb.emitPushInt(node, 2); // [this, [scopes, this], func]
1084
1085 sb.emitOp(node, 'PICKITEM'); // [[scopes, this], this, [scopes, this], func]
1086
1087 sb.emitOp(node, 'OVER'); // [1, [scopes, this], this, [scopes, this], func]
1088
1089 sb.emitPushInt(node, 1); // [this, 1, [scopes, this], [scopes, this], func]
1090
1091 sb.emitOp(node, 'ROT'); // [[scopes, this], func]
1092
1093 sb.emitOp(node, 'SETITEM');
1094 }
1095 })); // [func]
1096
1097 sb.emitOp(node, 'TOALTSTACK'); // Push the target on the stack
1098 // [0, func]
1099
1100 sb.emitPushInt(node, 0); // [target]
1101
1102 sb.emitOp(node, 'PICKITEM'); // Call function
1103
1104 sb.emitCall(node); // Remove scope
1105
1106 sb.emitOp(node, 'FROMALTSTACK');
1107 sb.emitOp(node, 'DROP');
1108
1109 if (optionsIn.pushValue) {
1110 sb.emitOp(node, 'DUP');
1111 }
1112
1113 sb.emitHelper(node, options, sb.helpers.handleCompletion);
1114
1115 if (optionsIn.pushValue) {
1116 sb.emitHelper(node, options, sb.helpers.getCompletionVal);
1117 }
1118 }
1119
1120}
1121
1122// Input: [func]
1123// Output: [func]
1124class CloneFunctionHelper extends Helper {
1125 emit(sb, node, options) {
1126 if (!options.pushValue) {
1127 sb.emitOp(node, 'DROP');
1128 return;
1129 }
1130
1131 sb.emitHelper(node, options, sb.helpers.cloneArray);
1132 }
1133
1134}
1135
1136// Input: [objectVal]
1137// Output: [objectVal]
1138class CloneFunctionObjectHelper extends Helper {
1139 constructor(options) {
1140 super();
1141 Object.defineProperty(this, "property", {
1142 configurable: true,
1143 enumerable: true,
1144 writable: true,
1145 value: void 0
1146 });
1147 Object.defineProperty(this, "both", {
1148 configurable: true,
1149 enumerable: true,
1150 writable: true,
1151 value: void 0
1152 });
1153
1154 if (options.type === 'both') {
1155 this.property = InternalFunctionProperties.CALL;
1156 this.both = true;
1157 } else {
1158 this.property = options.property;
1159 this.both = false;
1160 }
1161 }
1162
1163 emit(sb, node, options) {
1164 if (!options.pushValue) {
1165 sb.emitOp(node, 'DROP');
1166 return;
1167 } // [objectVal]
1168
1169
1170 sb.emitHelper(node, options, sb.helpers.shallowCloneObject);
1171
1172 if (this.both) {
1173 // [objectVal]
1174 this.cloneFunction(sb, node, options, InternalFunctionProperties.CALL); // [objectVal]
1175
1176 this.cloneFunction(sb, node, options, InternalFunctionProperties.CONSTRUCT);
1177 } else {
1178 // [objectVal]
1179 this.cloneFunction(sb, node, options, this.property);
1180 }
1181 }
1182
1183 cloneFunction(sb, node, options, property) {
1184 // [objectVal, objectVal]
1185 sb.emitOp(node, 'DUP'); // [property, objectVal, objectVal]
1186
1187 sb.emitPushString(node, property); // [func, objectVal]
1188
1189 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty); // [func, objectVal]
1190
1191 sb.emitHelper(node, options, sb.helpers.cloneFunction); // [objectVal, func, objectVal]
1192
1193 sb.emitOp(node, 'OVER'); // [property, objectVal, func, objectVal]
1194
1195 sb.emitPushString(node, property); // [func, property, objectVal, objectVal]
1196
1197 sb.emitOp(node, 'ROT'); // [objectVal]
1198
1199 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
1200 }
1201
1202}
1203
1204// Input: []
1205// Output: [farr]
1206class CreateCallArrayHelper extends Helper {
1207 emit(sb, node, outerOptions) {
1208 if (!outerOptions.pushValue) {
1209 return;
1210 }
1211
1212 sb.emitHelper(node, outerOptions, sb.helpers.createFunctionArray({
1213 body: () => {
1214 sb.withScope(node, outerOptions, options => {
1215 sb.emitHelper(node, options, sb.helpers.parameters);
1216 let body;
1217
1218 if (Ast.TypeGuards.isBodyableNode(node)) {
1219 body = node.getBodyOrThrow();
1220 } else {
1221 body = node.getBody();
1222 }
1223
1224 if (Ast.TypeGuards.isExpression(body)) {
1225 // [val]
1226 sb.visit(body, options); // [completion]
1227
1228 sb.emitHelper(node, options, sb.helpers.createNormalCompletion); // [completion]
1229
1230 sb.emitOp(node, 'RET');
1231 } else {
1232 sb.visit(body, options); // [undefinedVal]
1233
1234 sb.emitHelper(node, options, sb.helpers.createUndefined); // [completion]
1235
1236 sb.emitHelper(node, options, sb.helpers.createNormalCompletion); // [completion]
1237
1238 sb.emitOp(node, 'RET');
1239 }
1240 });
1241 }
1242 }));
1243 }
1244
1245}
1246
1247// Input: []
1248// Output: [farr]
1249class CreateConstructArrayHelper extends Helper {
1250 constructor({
1251 body,
1252 withoutScope
1253 }) {
1254 super();
1255 Object.defineProperty(this, "body", {
1256 configurable: true,
1257 enumerable: true,
1258 writable: true,
1259 value: void 0
1260 });
1261 Object.defineProperty(this, "withoutScope", {
1262 configurable: true,
1263 enumerable: true,
1264 writable: true,
1265 value: void 0
1266 });
1267 this.body = body;
1268 this.withoutScope = withoutScope || false;
1269 }
1270
1271 emit(sb, node, outerOptions) {
1272 if (!outerOptions.pushValue) {
1273 return;
1274 }
1275
1276 const emit = options => {
1277 // []
1278 this.body(); // [undefinedVal]
1279
1280 sb.emitHelper(node, options, sb.helpers.createUndefined); // [completion]
1281
1282 sb.emitHelper(node, options, sb.helpers.createNormalCompletion); // [completion]
1283
1284 sb.emitOp(node, 'RET');
1285 };
1286
1287 sb.emitHelper(node, outerOptions, sb.helpers.createFunctionArray({
1288 body: () => {
1289 if (this.withoutScope) {
1290 emit(outerOptions);
1291 } else {
1292 sb.withScope(node, outerOptions, options => {
1293 emit(options);
1294 });
1295 }
1296 }
1297 }));
1298 }
1299
1300}
1301
1302// Input: []
1303// Output: [farr]
1304class CreateFunctionArrayHelper extends Helper {
1305 constructor({
1306 body
1307 }) {
1308 super();
1309 Object.defineProperty(this, "body", {
1310 configurable: true,
1311 enumerable: true,
1312 writable: true,
1313 value: void 0
1314 });
1315 this.body = body;
1316 }
1317
1318 emit(sb, node, options) {
1319 if (options.pushValue) {
1320 // TODO: This might break if this/global change after copying?
1321
1322 /* create function */
1323 // [[scopes, this]]
1324 sb.scope.pushAll(sb, node, options); // [[scopes, this]]
1325
1326 sb.emitHelper(node, options, sb.helpers.cloneArray); // [[scopes, this], [scopes, this]]
1327
1328 sb.emitOp(node, 'DUP'); // [0, [scopes, this], [scopes, this]]
1329
1330 sb.emitPushInt(node, 0); // [[scopes, this], 0, [scopes, this], [scopes, this]]
1331
1332 sb.emitOp(node, 'OVER'); // [0, [scopes, this], 0, [scopes, this], [scopes, this]]
1333
1334 sb.emitOp(node, 'OVER'); // [scopes, 0, [scopes, this], [scopes, this]]
1335
1336 sb.emitOp(node, 'PICKITEM'); // [scopes, 0, [scopes, this], [scopes, this]]
1337
1338 sb.emitHelper(node, options, sb.helpers.cloneArray); // [[scopes, this]]
1339
1340 sb.emitOp(node, 'SETITEM'); // [target, scopes]
1341
1342 sb.emitHelper(node, options, sb.helpers.function({
1343 body: this.body
1344 })); // [2, target, scopes]
1345
1346 sb.emitPushInt(node, 2); // [arr]
1347
1348 sb.emitOp(node, 'PACK');
1349 }
1350 }
1351
1352}
1353
1354// Input: [farr]
1355// Output: [objectVal]
1356class CreateFunctionObjectHelper extends Helper {
1357 constructor({
1358 property
1359 }) {
1360 super();
1361 Object.defineProperty(this, "property", {
1362 configurable: true,
1363 enumerable: true,
1364 writable: true,
1365 value: void 0
1366 });
1367 this.property = property;
1368 }
1369
1370 emit(sb, node, options) {
1371 if (options.pushValue) {
1372 // [objectVal, farr]
1373 sb.emitHelper(node, options, sb.helpers.createObject); // [objectVal, farr, objectVal]
1374
1375 sb.emitOp(node, 'TUCK'); // ['call', objectVal, farr, objectVal]
1376
1377 sb.emitPushString(node, this.property); // [farr, 'call', objectVal, objectVal]
1378
1379 sb.emitOp(node, 'ROT'); // [objectVal]
1380
1381 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
1382 }
1383 }
1384
1385}
1386
1387// Input: []
1388// Output: [jumpTarget]
1389class FunctionHelper extends Helper {
1390 constructor({
1391 body
1392 }) {
1393 super();
1394 Object.defineProperty(this, "body", {
1395 configurable: true,
1396 enumerable: true,
1397 writable: true,
1398 value: void 0
1399 });
1400 this.body = body;
1401 }
1402
1403 emit(sb, node, options) {
1404 if (options.pushValue) {
1405 const jump = sb.jumpTable.add(sb, node, () => {
1406 this.body();
1407 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createUndefined);
1408 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createNormalCompletion);
1409 sb.emitOp(node, 'RET');
1410 });
1411 sb.emitPushInt(node, jump);
1412 }
1413 }
1414
1415}
1416
1417// Input: [objectVal, ?thisVal, ?argsarray]
1418// Output: [val]
1419class InvokeCallHelper extends Helper {
1420 static getKey(options = {
1421 bindThis: false,
1422 noArgs: false
1423 }) {
1424 const bindThis = options.bindThis || false;
1425 const overwriteThis = options.overwriteThis || false;
1426 const noArgs = options.noArgs || false;
1427 return stringify({
1428 bindThis,
1429 overwriteThis,
1430 noArgs
1431 });
1432 }
1433
1434 constructor(options = {
1435 bindThis: false,
1436 noArgs: false
1437 }) {
1438 super();
1439 Object.defineProperty(this, "bindThis", {
1440 configurable: true,
1441 enumerable: true,
1442 writable: true,
1443 value: void 0
1444 });
1445 Object.defineProperty(this, "overwriteThis", {
1446 configurable: true,
1447 enumerable: true,
1448 writable: true,
1449 value: void 0
1450 });
1451 Object.defineProperty(this, "noArgs", {
1452 configurable: true,
1453 enumerable: true,
1454 writable: true,
1455 value: void 0
1456 });
1457 this.bindThis = options.bindThis || false;
1458 this.overwriteThis = options.overwriteThis || false;
1459 this.noArgs = options.noArgs || false;
1460 }
1461
1462 emit(sb, node, optionsIn) {
1463 const options = sb.pushValueOptions(optionsIn); // ['call', objectVal, ?thisVal, ?argsarray]
1464
1465 sb.emitPushString(node, InternalFunctionProperties.CALL); // [func, ?thisVal, ?argsarray]
1466
1467 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty);
1468
1469 if (this.bindThis) {
1470 // [func, ?argsarray]
1471 sb.emitHelper(node, options, sb.helpers.bindFunctionThis({
1472 overwrite: this.overwriteThis
1473 }));
1474 }
1475
1476 if (this.noArgs) {
1477 // [0, func]
1478 sb.emitPushInt(node, 0); // [argsarray, func]
1479
1480 sb.emitOp(node, 'NEWARRAY'); // [func, argsarray]
1481
1482 sb.emitOp(node, 'SWAP');
1483 } // [val]
1484
1485
1486 sb.emitHelper(node, optionsIn, sb.helpers.call);
1487 }
1488
1489}
1490
1491// Input: [objectVal, thisObjectVal, ?argsarray]
1492// Output: []
1493class InvokeConstructHelper extends Helper {
1494 constructor(options = {
1495 noArgs: false
1496 }) {
1497 super();
1498 Object.defineProperty(this, "noArgs", {
1499 configurable: true,
1500 enumerable: true,
1501 writable: true,
1502 value: void 0
1503 });
1504 this.noArgs = options.noArgs || false;
1505 }
1506
1507 emit(sb, node, optionsIn) {
1508 const options = sb.pushValueOptions(optionsIn); // ['construct', objectVal, thisObjectVal, ?argsarray]
1509
1510 sb.emitPushString(node, InternalFunctionProperties.CONSTRUCT); // [func, thisObjectVal, ?argsarray]
1511
1512 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty); // [func, ?argsarray]
1513
1514 sb.emitHelper(node, options, sb.helpers.bindFunctionThis({
1515 overwrite: true
1516 }));
1517
1518 if (this.noArgs) {
1519 // [0, func]
1520 sb.emitPushInt(node, 0); // [argsarray, func]
1521
1522 sb.emitOp(node, 'NEWARRAY'); // [func, argsarray]
1523
1524 sb.emitOp(node, 'SWAP');
1525 } // []
1526
1527
1528 sb.emitHelper(node, sb.noPushValueOptions(optionsIn), sb.helpers.call);
1529 }
1530
1531}
1532
1533// Input: [objectVal, ?argsarr]
1534// Output: [thisVal]
1535class NewHelper extends Helper {
1536 constructor(options = {
1537 noArgs: false
1538 }) {
1539 super();
1540 Object.defineProperty(this, "noArgs", {
1541 configurable: true,
1542 enumerable: true,
1543 writable: true,
1544 value: void 0
1545 });
1546 this.noArgs = options.noArgs || false;
1547 }
1548
1549 emit(sb, node, optionsIn) {
1550 const options = sb.pushValueOptions(optionsIn); // [thisVal, objectVal, ?argsarr]
1551
1552 sb.emitHelper(node, options, sb.helpers.createObject);
1553
1554 if (this.noArgs) {
1555 // [thisVal, objectVal, thisVal]
1556 sb.emitOp(node, 'TUCK');
1557 } else {
1558 // [3, thisVal, objectVal, argsarr]
1559 sb.emitPushInt(node, 3); // [thisVal, objectVal, argsarr, thisVal]
1560
1561 sb.emitOp(node, 'XTUCK');
1562 } // [thisVal, objectVal, thisVal, ?argsarr, thisVal]
1563
1564
1565 sb.emitOp(node, 'TUCK'); // [objectVal, thisVal, objectVal, thisVal, ?argsarr, thisVal]
1566
1567 sb.emitOp(node, 'OVER'); // ['prototype', objectVal, thisVal, objectVal, thisVal, ?argsarr, thisVal]
1568
1569 sb.emitPushString(node, 'prototype'); // [objectVal, 'prototype', thisVal, objectVal, thisVal, ?argsarr, thisVal]
1570
1571 sb.emitOp(node, 'SWAP'); // ['prototype', objectVal, 'prototype', thisVal, objectVal, thisVal, ?argsarr, thisVal]
1572
1573 sb.emitPushString(node, 'prototype'); // [prototype, 'prototype', thisVal, objectVal, thisVal, ?argsarr, thisVal]
1574
1575 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [objectVal, thisVal, ?argsarr, thisVal]
1576
1577 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [thisVal]
1578
1579 sb.emitHelper(node, options, sb.helpers.invokeConstruct({
1580 noArgs: this.noArgs
1581 }));
1582
1583 if (!optionsIn.pushValue) {
1584 // []
1585 sb.emitOp(node, 'DROP');
1586 }
1587 }
1588
1589}
1590
1591// Input: [argsArray]
1592// Output: []
1593class ParametersHelper extends Helper {
1594 emit(sb, node, optionsIn) {
1595 const options = sb.pushValueOptions(optionsIn); // [argsarr]
1596
1597 node.getParameters().forEach((param, idx) => {
1598 const name = sb.scope.add(param.getNameOrThrow());
1599 const initializer = param.getInitializer();
1600
1601 if (param.isRestParameter()) {
1602 sb.reportUnsupported(param);
1603 } else if (initializer != null) {
1604 sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
1605 condition: () => {
1606 // [argsarr, argsarr]
1607 sb.emitOp(param, 'DUP'); // [size, argsarr]
1608
1609 sb.emitOp(param, 'ARRAYSIZE'); // [idx, size, argsarr]
1610
1611 sb.emitPushInt(param, idx); // [lt, argsarr]
1612
1613 sb.emitOp(param, 'LTE');
1614 },
1615 whenTrue: () => {
1616 // [default, argsarr]
1617 sb.visit(initializer, sb.pushValueOptions(options));
1618 },
1619 whenFalse: () => {
1620 // [argsarr, argsarr]
1621 sb.emitOp(param, 'DUP'); // [idx, argsarr, argsarr]
1622
1623 sb.emitPushInt(param, idx); // [arg, argsarr]
1624
1625 sb.emitOp(param, 'PICKITEM'); // [arg, arg, argsarr]
1626
1627 sb.emitOp(param, 'DUP');
1628 sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
1629 condition: () => {
1630 // [isUndefined, arg, argsarr]
1631 sb.emitHelper(param, sb.pushValueOptions(options), sb.helpers.isUndefined);
1632 },
1633 whenTrue: () => {
1634 // [argsarr]
1635 sb.emitOp(param, 'DROP'); // [default, argsarr]
1636
1637 sb.visit(initializer, sb.pushValueOptions(options));
1638 }
1639 }));
1640 }
1641 }));
1642 } else if (param.isOptional()) {
1643 sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
1644 condition: () => {
1645 // [argsarr, argsarr]
1646 sb.emitOp(param, 'DUP'); // [size, argsarr]
1647
1648 sb.emitOp(param, 'ARRAYSIZE'); // [idx, size, argsarr]
1649
1650 sb.emitPushInt(param, idx); // [lt, argsarr]
1651
1652 sb.emitOp(param, 'LT');
1653 },
1654 whenTrue: () => {
1655 // [undefinedVal, argsarr]
1656 sb.emitHelper(param, sb.pushValueOptions(options), sb.helpers.createUndefined);
1657 },
1658 whenFalse: () => {
1659 // [argsarr, argsarr]
1660 sb.emitOp(param, 'DUP'); // [idx, argsarr, argsarr]
1661
1662 sb.emitPushInt(param, idx); // [arg, argsarr]
1663
1664 sb.emitOp(param, 'PICKITEM');
1665 }
1666 }));
1667 } else {
1668 // [argsarr, argsarr]
1669 sb.emitOp(param, 'DUP'); // [idx, argsarr, argsarr]
1670
1671 sb.emitPushInt(param, idx); // [arg, argsarr]
1672
1673 sb.emitOp(param, 'PICKITEM');
1674 }
1675
1676 const decorators = param.getDecorators();
1677
1678 if (decorators.length > 0) {
1679 sb.reportUnsupported(param);
1680 } // [argsarr]
1681
1682
1683 sb.scope.set(sb, param, sb.plainOptions(options), name);
1684 }); // []
1685
1686 sb.emitOp(node, 'DROP');
1687 }
1688
1689}
1690
1691// Output: []
1692
1693class GenericDeserializeHelper extends Helper {
1694 emitGlobal(sb, node, optionsIn) {
1695 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal]
1696
1697 sb.scope.getGlobal(sb, node, options); // [name, globalObjectVal]
1698
1699 sb.emitPushString(node, DESERIALIZE_NAME); // [farr, name, globalObjectVal]
1700
1701 sb.emitHelper(node, options, sb.helpers.createFunctionArray({
1702 body: () => {
1703 // [0, argsarr]
1704 sb.emitPushInt(node, 0); // [val]
1705
1706 sb.emitOp(node, 'PICKITEM');
1707 sb.emitHelper(node, options, sb.helpers.case(getTypes(sb, node, options).map(forType => ({
1708 condition: () => {
1709 sb.emitOp(node, 'DUP');
1710 forType.isSerializedType();
1711 },
1712 whenTrue: () => {
1713 forType.deserialize();
1714 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createNormalCompletion);
1715 sb.emitOp(node, 'RET');
1716 }
1717 })), () => {
1718 sb.emitOp(node, 'DROP');
1719 sb.emitHelper(node, options, sb.helpers.throwTypeError);
1720 }));
1721 }
1722 })); // [objectVal, name, globalObjectVal]
1723
1724 sb.emitHelper(node, options, sb.helpers.createFunctionObject({
1725 property: InternalFunctionProperties.CALL
1726 })); // []
1727
1728 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
1729 }
1730
1731 emit(sb, node, options) {
1732 if (!options.pushValue) {
1733 sb.emitOp(node, 'DROP');
1734 return;
1735 }
1736
1737 invokeDeserialize(sb, node, options);
1738 }
1739
1740}
1741
1742// Output: []
1743
1744class GenericSerializeHelper extends Helper {
1745 emitGlobal(sb, node, optionsIn) {
1746 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal]
1747
1748 sb.scope.getGlobal(sb, node, options); // [name, globalObjectVal]
1749
1750 sb.emitPushString(node, SERIALIZE_NAME); // [farr, name, globalObjectVal]
1751
1752 sb.emitHelper(node, options, sb.helpers.createFunctionArray({
1753 body: () => {
1754 // [0, argsarr]
1755 sb.emitPushInt(node, 0); // [val]
1756
1757 sb.emitOp(node, 'PICKITEM');
1758 sb.emitHelper(node, options, sb.helpers.case(getTypes(sb, node, options).map(forType => ({
1759 condition: () => {
1760 sb.emitOp(node, 'DUP');
1761 forType.isRuntimeType();
1762 },
1763 whenTrue: () => {
1764 forType.serialize();
1765 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createNormalCompletion);
1766 sb.emitOp(node, 'RET');
1767 }
1768 })), () => {
1769 sb.emitOp(node, 'DROP');
1770 sb.emitHelper(node, options, sb.helpers.throwTypeError);
1771 }));
1772 }
1773 })); // [objectVal, name, globalObjectVal]
1774
1775 sb.emitHelper(node, options, sb.helpers.createFunctionObject({
1776 property: InternalFunctionProperties.CALL
1777 })); // []
1778
1779 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
1780 }
1781
1782 emit(sb, node, options) {
1783 if (!options.pushValue) {
1784 sb.emitOp(node, 'DROP');
1785 return;
1786 }
1787
1788 invokeSerialize(sb, node, options);
1789 }
1790
1791}
1792
1793class TypedHelper extends Helper {
1794 constructor({
1795 knownType,
1796 type
1797 }) {
1798 super();
1799 Object.defineProperty(this, "type", {
1800 configurable: true,
1801 enumerable: true,
1802 writable: true,
1803 value: void 0
1804 });
1805 Object.defineProperty(this, "knownType", {
1806 configurable: true,
1807 enumerable: true,
1808 writable: true,
1809 value: void 0
1810 });
1811 this.type = type;
1812 this.knownType = knownType;
1813 }
1814
1815}
1816
1817// Input: [val, errorVal]
1818// Output: [completion]
1819class CreateCompletionHelper extends Helper {
1820 emit(sb, node, options) {
1821 if (!options.pushValue) {
1822 sb.emitOp(node, 'DROP');
1823 sb.emitOp(node, 'DROP');
1824 return;
1825 } // [2, val, errorVal]
1826
1827
1828 sb.emitPushInt(node, 2); // [completion]
1829
1830 sb.emitOp(node, 'PACK');
1831 }
1832
1833}
1834
1835// Input: [val]
1836// Output: [completion]
1837class CreateNormalCompletionHelper extends Helper {
1838 emit(sb, node, options) {
1839 if (!options.pushValue) {
1840 sb.emitOp(node, 'DROP');
1841 return;
1842 } // [undefinedVal, val]
1843
1844
1845 sb.emitHelper(node, options, sb.helpers.createUndefined); // [val, undefinedVal]
1846
1847 sb.emitOp(node, 'SWAP'); // [completion]
1848
1849 sb.emitHelper(node, options, sb.helpers.createCompletion);
1850 }
1851
1852}
1853
1854// Input: [errorVal]
1855// Output: [completion]
1856class CreateThrowCompletionHelper extends Helper {
1857 emit(sb, node, options) {
1858 if (!options.pushValue) {
1859 sb.emitOp(node, 'DROP');
1860 return;
1861 } // [undefinedVal, errorVal]
1862
1863
1864 sb.emitHelper(node, options, sb.helpers.createUndefined); // [completion]
1865
1866 sb.emitHelper(node, options, sb.helpers.createCompletion);
1867 }
1868
1869}
1870
1871// Input: [completion]
1872// Output: [val]
1873class GetCompletionBaseHelper extends Helper {
1874 constructor(...args) {
1875 var _temp;
1876
1877 return _temp = super(...args), Object.defineProperty(this, "index", {
1878 configurable: true,
1879 enumerable: true,
1880 writable: true,
1881 value: void 0
1882 }), _temp;
1883 }
1884
1885 emit(sb, node, options) {
1886 if (!options.pushValue) {
1887 sb.emitOp(node, 'DROP');
1888 return;
1889 } // [index, completion]
1890
1891
1892 sb.emitPushInt(node, this.index); // [val]
1893
1894 sb.emitOp(node, 'PICKITEM');
1895 }
1896
1897}
1898
1899// Output: [errorVal]
1900
1901class GetCompletionErrorHelper extends GetCompletionBaseHelper {
1902 constructor(...args) {
1903 var _temp;
1904
1905 return _temp = super(...args), Object.defineProperty(this, "index", {
1906 configurable: true,
1907 enumerable: true,
1908 writable: true,
1909 value: 1
1910 }), _temp;
1911 }
1912
1913}
1914
1915// Output: [errorVal]
1916
1917class GetCompletionValHelper extends GetCompletionBaseHelper {
1918 constructor(...args) {
1919 var _temp;
1920
1921 return _temp = super(...args), Object.defineProperty(this, "index", {
1922 configurable: true,
1923 enumerable: true,
1924 writable: true,
1925 value: 0
1926 }), _temp;
1927 }
1928
1929}
1930
1931let DiagnosticCode;
1932
1933(function (DiagnosticCode) {
1934 DiagnosticCode[DiagnosticCode["UNSUPPORTED_SYNTAX"] = 0] = "UNSUPPORTED_SYNTAX";
1935 DiagnosticCode[DiagnosticCode["UNKNOWN_TYPE"] = 1] = "UNKNOWN_TYPE";
1936 DiagnosticCode[DiagnosticCode["EXPECTED_NUMBER"] = 2] = "EXPECTED_NUMBER";
1937 DiagnosticCode[DiagnosticCode["EXPECTED_STRING"] = 3] = "EXPECTED_STRING";
1938 DiagnosticCode[DiagnosticCode["REFERENCE_ERROR"] = 4] = "REFERENCE_ERROR";
1939 DiagnosticCode[DiagnosticCode["SOMETHING_WENT_WRONG"] = 5] = "SOMETHING_WENT_WRONG";
1940 DiagnosticCode[DiagnosticCode["EXPECTED_PROPERTY"] = 6] = "EXPECTED_PROPERTY";
1941 DiagnosticCode[DiagnosticCode["EXPECTED_CAST"] = 7] = "EXPECTED_CAST";
1942 DiagnosticCode[DiagnosticCode["TRANSPILATION_ERROR"] = 8] = "TRANSPILATION_ERROR";
1943 DiagnosticCode[DiagnosticCode["INVALID_CONTRACT_PARAMETER"] = 9] = "INVALID_CONTRACT_PARAMETER";
1944 DiagnosticCode[DiagnosticCode["INVALID_CONTRACT_TYPE"] = 10] = "INVALID_CONTRACT_TYPE";
1945 DiagnosticCode[DiagnosticCode["INVALID_CONTRACT_METHOD"] = 11] = "INVALID_CONTRACT_METHOD";
1946 DiagnosticCode[DiagnosticCode["INVALID_VALUE_TYPE"] = 12] = "INVALID_VALUE_TYPE";
1947 DiagnosticCode[DiagnosticCode["INVALID_SYS_CALL"] = 13] = "INVALID_SYS_CALL";
1948 DiagnosticCode[DiagnosticCode["UNKNOWN_SYMBOL"] = 14] = "UNKNOWN_SYMBOL";
1949})(DiagnosticCode || (DiagnosticCode = {}));
1950
1951const NORMAL_COMPLETION = 0;
1952const BREAK_COMPLETION = 1;
1953const CONTINUE_COMPLETION = 2;
1954const CATCH_COMPLETION = 3;
1955const ASSIGNMENT_OPERATORS = new Set([Ast.SyntaxKind.EqualsToken, Ast.SyntaxKind.PlusEqualsToken, Ast.SyntaxKind.MinusEqualsToken, Ast.SyntaxKind.AsteriskAsteriskEqualsToken, Ast.SyntaxKind.AsteriskEqualsToken, Ast.SyntaxKind.SlashEqualsToken, Ast.SyntaxKind.PercentEqualsToken, Ast.SyntaxKind.AmpersandEqualsToken, Ast.SyntaxKind.BarEqualsToken, Ast.SyntaxKind.CaretEqualsToken, Ast.SyntaxKind.LessThanLessThanEqualsToken, Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken, Ast.SyntaxKind.GreaterThanGreaterThanEqualsToken]);
1956
1957const isValidParent = node => node != null && (Ast.TypeGuards.isTryStatement(node) || Ast.TypeGuards.isFunctionLikeDeclaration(node) || Ast.TypeGuards.isArrowFunction(node) || Ast.TypeGuards.isSourceFile(node)); // Input: [completion]
1958// Output: []
1959
1960
1961class HandleCompletionHelper extends Helper {
1962 emit(sb, node, optionsIn) {
1963 const options = sb.pushValueOptions(optionsIn);
1964 sb.emitHelper(node, options, sb.helpers.if({
1965 condition: () => {
1966 // [completion, completion]
1967 sb.emitOp(node, 'DUP'); // [errorVal, completion]
1968
1969 sb.emitHelper(node, options, sb.helpers.getCompletionError); // [isUndefined, completion]
1970
1971 sb.emitHelper(node, options, sb.helpers.isUndefined);
1972 },
1973 whenTrue: () => {
1974 sb.emitOp(node, 'DROP');
1975 },
1976 whenFalse: () => {
1977 let parent = node.getParent();
1978
1979 if (!isValidParent(parent)) {
1980 parent = node.getParentWhile(parentNode => !isValidParent(parentNode));
1981
1982 if (parent != null) {
1983 parent = parent.getParent();
1984 }
1985 }
1986
1987 if (Ast.TypeGuards.isSourceFile(node) || parent != null && Ast.TypeGuards.isSourceFile(parent)) {
1988 // TODO: Add Error notification
1989 sb.emitOp(node, 'THROW');
1990 } else if (parent == null) {
1991 sb.reportError(node, 'Something went wrong, could not find a valid parent node.', DiagnosticCode.SOMETHING_WENT_WRONG);
1992 } else if (Ast.TypeGuards.isTryStatement(parent)) {
1993 if (options.catchPC == null) {
1994 sb.reportError(node, 'Something went wrong. Expected a catch jump location.', DiagnosticCode.SOMETHING_WENT_WRONG);
1995 } else {
1996 sb.emitPushInt(node, CATCH_COMPLETION);
1997 sb.emitJmp(node, 'JMP', options.catchPC);
1998 }
1999 } else {
2000 sb.emitOp(node, 'RET');
2001 }
2002 }
2003 }));
2004 }
2005
2006}
2007
2008// Input: [completion]
2009// Output: [val]
2010class PickCompletionValHelper extends Helper {
2011 emit(sb, node, options) {
2012 if (options.pushValue) {
2013 // [completion, completion]
2014 sb.emitOp(node, 'DUP');
2015 }
2016
2017 sb.emitHelper(node, options, sb.helpers.handleCompletion);
2018
2019 if (options.pushValue) {
2020 sb.emitHelper(node, options, sb.helpers.getCompletionVal);
2021 }
2022 }
2023
2024}
2025
2026// Input: [errorVal]
2027// Output: []
2028class ThrowHelper extends Helper {
2029 emit(sb, node, options) {
2030 // [throwCompletion]
2031 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createThrowCompletion); // []
2032
2033 sb.emitHelper(node, options, sb.helpers.handleCompletion);
2034 }
2035
2036}
2037
2038// Input: []
2039// Output: []
2040class ThrowTypeErrorHelper extends Helper {
2041 emit(sb, node, options) {
2042 // TODO: Implement with global TypeError prototype
2043 // ['TypeError']
2044 sb.emitPushString(node, 'TypeError'); // [value]
2045
2046 sb.emitHelper(node, options, sb.helpers.createString); // []
2047
2048 sb.emitHelper(node, options, sb.helpers.throw);
2049 }
2050
2051}
2052
2053// Input: []
2054// Output: []
2055class CaseHelper extends Helper {
2056 constructor(cases, defaultCase) {
2057 super();
2058 Object.defineProperty(this, "cases", {
2059 configurable: true,
2060 enumerable: true,
2061 writable: true,
2062 value: void 0
2063 });
2064 Object.defineProperty(this, "defaultCase", {
2065 configurable: true,
2066 enumerable: true,
2067 writable: true,
2068 value: void 0
2069 });
2070 this.cases = cases;
2071 this.defaultCase = defaultCase;
2072 }
2073
2074 emit(sb, node, options) {
2075 this.addCase(sb, node, options);
2076 }
2077
2078 addCase(sb, node, options, idx = 0) {
2079 if (idx >= this.cases.length) {
2080 this.defaultCase();
2081 } else {
2082 sb.emitHelper(node, options, sb.helpers.if({
2083 condition: this.cases[idx].condition,
2084 whenTrue: this.cases[idx].whenTrue,
2085 whenFalse: () => this.addCase(sb, node, options, idx + 1)
2086 }));
2087 }
2088 }
2089
2090}
2091
2092class ForLoopHelper extends Helper {
2093 constructor({
2094 each,
2095 initializer,
2096 condition,
2097 incrementor,
2098 withScope
2099 }) {
2100 super();
2101 Object.defineProperty(this, "each", {
2102 configurable: true,
2103 enumerable: true,
2104 writable: true,
2105 value: void 0
2106 });
2107 Object.defineProperty(this, "initializer", {
2108 configurable: true,
2109 enumerable: true,
2110 writable: true,
2111 value: void 0
2112 });
2113 Object.defineProperty(this, "condition", {
2114 configurable: true,
2115 enumerable: true,
2116 writable: true,
2117 value: void 0
2118 });
2119 Object.defineProperty(this, "incrementor", {
2120 configurable: true,
2121 enumerable: true,
2122 writable: true,
2123 value: void 0
2124 });
2125 Object.defineProperty(this, "withScope", {
2126 configurable: true,
2127 enumerable: true,
2128 writable: true,
2129 value: void 0
2130 });
2131 this.each = each;
2132 this.initializer = initializer;
2133 this.condition = condition;
2134 this.incrementor = incrementor;
2135 this.withScope = withScope == null ? true : withScope;
2136 }
2137
2138 emit(sb, node, options) {
2139 if (this.withScope) {
2140 sb.withScope(node, options, innerOptions => {
2141 this.emitLoop(sb, node, innerOptions);
2142 });
2143 } else {
2144 this.emitLoop(sb, node, options);
2145 }
2146 } // TODO: Optimize to check for continue/break that refers to this loop in child.
2147
2148
2149 emitLoop(sb, node, options) {
2150 if (this.initializer != null) {
2151 this.initializer();
2152 }
2153
2154 sb.withProgramCounter(loopPC => {
2155 if (this.condition != null) {
2156 this.condition();
2157 }
2158
2159 if (!loopPC.getFirst().equals(loopPC.getCurrent())) {
2160 sb.emitJmp(node, 'JMPIFNOT', loopPC.getLast());
2161 }
2162
2163 sb.withProgramCounter(breakPC => {
2164 sb.withProgramCounter(innerPC => {
2165 sb.withProgramCounter(continuePC => {
2166 this.each(sb.breakPCOptions(sb.continuePCOptions(options, continuePC.getLast()), breakPC.getLast()));
2167 sb.emitJmp(node, 'JMP', innerPC.getLast());
2168 }); // Drop continue completion
2169
2170 sb.emitOp(node, 'DROP');
2171 });
2172
2173 if (this.incrementor != null) {
2174 this.incrementor();
2175 }
2176
2177 sb.emitJmp(node, 'JMP', loopPC.getFirst());
2178 }); // Drop break completion
2179
2180 sb.emitOp(node, 'DROP');
2181 });
2182 }
2183
2184}
2185
2186class IfHelper extends Helper {
2187 constructor({
2188 condition,
2189 whenTrue,
2190 whenFalse
2191 }) {
2192 super();
2193 Object.defineProperty(this, "condition", {
2194 configurable: true,
2195 enumerable: true,
2196 writable: true,
2197 value: void 0
2198 });
2199 Object.defineProperty(this, "whenTrue", {
2200 configurable: true,
2201 enumerable: true,
2202 writable: true,
2203 value: void 0
2204 });
2205 Object.defineProperty(this, "whenFalse", {
2206 configurable: true,
2207 enumerable: true,
2208 writable: true,
2209 value: void 0
2210 });
2211 this.condition = condition;
2212 this.whenTrue = whenTrue;
2213 this.whenFalse = whenFalse;
2214 }
2215
2216 emit(sb, node, options) {
2217 this.condition();
2218 const {
2219 whenTrue,
2220 whenFalse
2221 } = this;
2222
2223 if (whenTrue == null) {
2224 if (whenFalse == null) {
2225 throw new Error('If statement must have a true or false value');
2226 }
2227
2228 sb.withProgramCounter(endPC => {
2229 sb.emitJmp(node, 'JMPIF', endPC.getLast());
2230 whenFalse();
2231 });
2232 } else {
2233 sb.withProgramCounter(whenFalsePC => {
2234 sb.withProgramCounter(whenTruePC => {
2235 sb.emitJmp(node, 'JMPIFNOT', whenTruePC.getLast());
2236 whenTrue();
2237
2238 if (this.whenFalse != null) {
2239 sb.emitJmp(node, 'JMP', whenFalsePC.getLast());
2240 }
2241 });
2242
2243 if (this.whenFalse != null) {
2244 this.whenFalse();
2245 }
2246 });
2247 }
2248 }
2249
2250}
2251
2252class ProcessStatementsHelper extends Helper {
2253 constructor({
2254 createScope
2255 }) {
2256 super();
2257 Object.defineProperty(this, "createScope", {
2258 configurable: true,
2259 enumerable: true,
2260 writable: true,
2261 value: void 0
2262 });
2263 this.createScope = createScope;
2264 }
2265
2266 emit(sb, node, options) {
2267 if (this.createScope) {
2268 sb.withScope(node, options, innerOptions => {
2269 this.emitStatements(sb, node, innerOptions);
2270 });
2271 } else {
2272 this.emitStatements(sb, node, options);
2273 }
2274 }
2275
2276 emitStatements(sb, node, options) {
2277 node.getFunctions().forEach(func => {
2278 sb.scope.add(func.getName());
2279 });
2280 node.getVariableDeclarations().forEach(decl => {
2281 sb.scope.add(decl.getName());
2282 });
2283 const compilerStatements = node.compilerNode.statements;
2284 let statements;
2285
2286 if (compilerStatements == null) {
2287 statements = node.getStatements();
2288 } else {
2289 statements = compilerStatements.map(statement => node.getNodeFromCompilerNode(statement));
2290 }
2291
2292 statements.forEach(statement => {
2293 // TODO: Should functions be hoisted?
2294 sb.visit(statement, sb.noValueOptions(options));
2295 });
2296 }
2297
2298}
2299
2300// Input: [value]
2301// Output: [val]
2302class CreatePrimitiveHelper extends Helper {
2303 constructor(...args) {
2304 var _temp;
2305
2306 return _temp = super(...args), Object.defineProperty(this, "length", {
2307 configurable: true,
2308 enumerable: true,
2309 writable: true,
2310 value: 2
2311 }), Object.defineProperty(this, "type", {
2312 configurable: true,
2313 enumerable: true,
2314 writable: true,
2315 value: void 0
2316 }), _temp;
2317 }
2318
2319 emit(sb, node, options) {
2320 if (!options.pushValue) {
2321 sb.emitOp(node, 'DROP');
2322 return;
2323 } // [type, value]
2324
2325
2326 sb.emitPushInt(node, this.type); // [2, type, value]
2327
2328 sb.emitPushInt(node, this.length); // [[type, value]]
2329
2330 sb.emitOp(node, 'PACK');
2331 }
2332
2333}
2334
2335let Types;
2336
2337(function (Types) {
2338 Types[Types["Undefined"] = 0] = "Undefined";
2339 Types[Types["Null"] = 1] = "Null";
2340 Types[Types["Boolean"] = 2] = "Boolean";
2341 Types[Types["String"] = 3] = "String";
2342 Types[Types["Symbol"] = 4] = "Symbol";
2343 Types[Types["Number"] = 5] = "Number";
2344 Types[Types["Object"] = 6] = "Object";
2345})(Types || (Types = {}));
2346
2347// Output: [booleanVal]
2348
2349class CreateBooleanHelper extends CreatePrimitiveHelper {
2350 constructor(...args) {
2351 var _temp;
2352
2353 return _temp = super(...args), Object.defineProperty(this, "type", {
2354 configurable: true,
2355 enumerable: true,
2356 writable: true,
2357 value: Types.Boolean
2358 }), _temp;
2359 }
2360
2361}
2362
2363// Input: [val]
2364// Output: [value]
2365class GetPrimitiveHelper extends Helper {
2366 emit(sb, node, options) {
2367 if (!options.pushValue) {
2368 sb.emitOp(node, 'DROP');
2369 return;
2370 } // [1, val]
2371
2372
2373 sb.emitPushInt(node, 1); // [value]
2374
2375 sb.emitOp(node, 'PICKITEM');
2376 }
2377
2378}
2379
2380// Output: [boolean]
2381
2382class GetBooleanHelper extends GetPrimitiveHelper {}
2383
2384// Input: [val]
2385// Output: [boolean]
2386class IsHelper extends Helper {
2387 constructor(...args) {
2388 var _temp;
2389
2390 return _temp = super(...args), Object.defineProperty(this, "type", {
2391 configurable: true,
2392 enumerable: true,
2393 writable: true,
2394 value: void 0
2395 }), _temp;
2396 }
2397
2398 emit(sb, node, options) {
2399 if (!options.pushValue) {
2400 sb.emitOp(node, 'DROP');
2401 return;
2402 } // [0, value]
2403
2404
2405 sb.emitPushInt(node, 0); // [type]
2406
2407 sb.emitOp(node, 'PICKITEM'); // [type, type]
2408
2409 sb.emitPushInt(node, this.type); // [isType]
2410
2411 sb.emitOp(node, 'EQUAL');
2412 }
2413
2414}
2415
2416// Output: [boolean]
2417
2418class IsBooleanHelper extends IsHelper {
2419 constructor(...args) {
2420 var _temp;
2421
2422 return _temp = super(...args), Object.defineProperty(this, "type", {
2423 configurable: true,
2424 enumerable: true,
2425 writable: true,
2426 value: Types.Boolean
2427 }), _temp;
2428 }
2429
2430}
2431
2432function getType(type) {
2433 if (type == null) {
2434 return undefined;
2435 }
2436
2437 const constraint = type.getConstraint();
2438 return constraint == null ? type : constraint;
2439}
2440
2441const hasUnionType = (type, isType) => getType(type).isUnionType() && getType(type).getUnionTypes().some(isType);
2442const hasIntersectionType = (type, isType) => getType(type).isIntersectionType() && getType(type).getIntersectionTypes().some(isType);
2443const hasType = (type, isType) => isType(type) || hasUnionType(type, isType) || hasIntersectionType(type, isType);
2444const isOnly = (type, isType) => type != null && !getType(type).isNullable() && (isType(type) || getType(type).isUnionType() && getType(type).getUnionTypes().every(unionType => isOnly(unionType, isType)) || getType(type).isIntersectionType() && getType(type).getIntersectionTypes().every(intersectionType => isOnly(intersectionType, isType)));
2445const isUndefined = type => type != null && getType(type).isUndefinedType();
2446const isOnlyUndefined = type => isOnly(type, isUndefined);
2447const hasUndefined = type => hasType(type, isUndefined);
2448const isNull = type => type != null && (getType(type).isNullType() || getType(type).isNullable());
2449const isOnlyNull = type => isOnly(type, isNull);
2450const hasNull = type => hasType(type, isNull) || getType(type).isNullable();
2451const isOnlyNumberLiteral = type => type != null && isOnly(type, tpe => tpe != null && tpe.isNumberLiteralType());
2452const isNumber = type => type != null && (getType(type).isNumberType() || getType(type).isNumberLiteralType());
2453const isOnlyNumber = type => isOnly(type, isNumber);
2454const hasNumber = type => hasType(type, isNumber);
2455const isString = type => type != null && (getType(type).isStringType() || getType(type).isStringLiteralType());
2456const isOnlyString = type => isOnly(type, isString);
2457const hasString = type => hasType(type, isString);
2458const isBoolean = type => type != null && (getType(type).isBooleanType() || getType(type).isBooleanLiteralType());
2459const isOnlyBoolean = type => isOnly(type, isBoolean);
2460const hasBoolean = type => hasType(type, isBoolean);
2461
2462const hasTypeFlag = (type, flag // tslint:disable-next-line
2463) => (getType(type).compilerType.flags & flag) === flag;
2464
2465const isSymbol = type => type != null && (hasTypeFlag(type, Ast.TypeFlags.ESSymbol) || hasTypeFlag(type, Ast.TypeFlags.ESSymbolLike));
2466const isOnlySymbol = type => isOnly(type, isSymbol);
2467const isPrimitive = type => isUndefined(type) || isNull(type) || isString(type) || isNumber(type) || isBoolean(type) || isSymbol(type);
2468const isOnlyPrimitive = type => isOnly(type, isPrimitive);
2469const isOnlyObject = type => isOnly(type, tpe => !isPrimitive(tpe));
2470const isArray = type => type != null && getType(type).isArrayType();
2471const isOnlyArray = type => isOnly(type, isArray);
2472const isTuple = type => type != null && getType(type).isTupleType();
2473const isOnlyTuple = type => isOnly(type, isTuple);
2474const isSame = (type0, type1) => type0 != null && type1 != null && (type0 === type1 || isOnlyBoolean(type0) && isOnlyBoolean(type1) || isOnlyNumber(type0) && isOnlyNumber(type1) || isOnlyString(type0) && isOnlyString(type1));
2475const isUnion = type => type != null && getType(type).isUnionType();
2476const isIntersection = type => type != null && getType(type).isIntersectionType();
2477const isLiteral = type => type != null && getType(type).isLiteralType();
2478const isAnyType = type => type != null && hasTypeFlag(type, Ast.TypeFlags.Any);
2479const isVoid = type => type != null && hasTypeFlag(type, Ast.TypeFlags.Void);
2480
2481// Output: [boolean]
2482
2483class ToBooleanHelper extends TypedHelper {
2484 emit(sb, node, options) {
2485 if (!options.pushValue) {
2486 sb.emitOp(node, 'DROP');
2487 return;
2488 }
2489
2490 if (this.type != null) {
2491 this.convertType(sb, node, options, this.type);
2492 } else {
2493 this.convertUnknownType(sb, node, options);
2494 }
2495 }
2496
2497 convertType(sb, node, options, type) {
2498 if (isOnlyUndefined(type) || isOnlyNull(type)) {
2499 sb.emitPushBoolean(node, false);
2500 } else if (isOnlyBoolean(type)) {
2501 this.convertBoolean(sb, node, options);
2502 } else if (isOnlyNumber(type)) {
2503 this.convertNumber(sb, node, options);
2504 } else if (isOnlyString(type)) {
2505 this.convertString(sb, node, options);
2506 } else if ( // It's a symbol or an object
2507 !hasUndefined(type) && !hasNull(type) && !hasBoolean(type) && !hasNumber(type) && !hasString(type)) {
2508 sb.emitPushBoolean(node, true);
2509 } else {
2510 this.convertUnknownType(sb, node, options);
2511 }
2512 }
2513
2514 convertBoolean(sb, node, options) {
2515 sb.emitHelper(node, options, sb.helpers.getBoolean);
2516 }
2517
2518 convertNumber(sb, node, options) {
2519 sb.emitHelper(node, options, sb.helpers.getNumber);
2520 sb.emitPushInt(node, 0);
2521 sb.emitOp(node, 'NUMNOTEQUAL');
2522 }
2523
2524 convertString(sb, node, options) {
2525 sb.emitHelper(node, options, sb.helpers.getString);
2526 sb.emitPushString(node, '');
2527 sb.emitOp(node, 'EQUAL');
2528 sb.emitOp(node, 'NOT');
2529 }
2530
2531 convertUnknownType(sb, node, options) {
2532 sb.emitHelper(node, options, sb.helpers.case([{
2533 condition: () => {
2534 // [value, value]
2535 sb.emitOp(node, 'DUP'); // [isBoolean, value]
2536
2537 sb.emitHelper(node, options, sb.helpers.isBoolean);
2538 },
2539 whenTrue: () => {
2540 // [value]
2541 sb.emitHelper(node, options, sb.helpers.getBoolean);
2542 }
2543 }, {
2544 condition: () => {
2545 // [value, value]
2546 sb.emitOp(node, 'DUP'); // [isNull, value]
2547
2548 sb.emitHelper(node, options, sb.helpers.isNull); // [value, isNull, value]
2549
2550 sb.emitOp(node, 'OVER'); // [isUndefined, isNull, value]
2551
2552 sb.emitHelper(node, options, sb.helpers.isUndefined); // [isUndefinedOrNull, value]
2553
2554 sb.emitOp(node, 'OR');
2555 },
2556 whenTrue: () => {
2557 sb.emitPushBoolean(node, false);
2558 }
2559 }, {
2560 condition: () => {
2561 // [value, value]
2562 sb.emitOp(node, 'DUP'); // [isObject, value]
2563
2564 sb.emitHelper(node, options, sb.helpers.isObject); // [value, isObject, value]
2565
2566 sb.emitOp(node, 'OVER'); // [isSymbol, isObject, value]
2567
2568 sb.emitHelper(node, options, sb.helpers.isSymbol); // [isSymbolOrObject, value]
2569
2570 sb.emitOp(node, 'OR');
2571 },
2572 whenTrue: () => {
2573 sb.emitPushBoolean(node, true);
2574 }
2575 }, {
2576 condition: () => {
2577 // [value, value]
2578 sb.emitOp(node, 'DUP'); // [isNumber, value]
2579
2580 sb.emitHelper(node, options, sb.helpers.isNumber);
2581 },
2582 whenTrue: () => {
2583 this.convertNumber(sb, node, options);
2584 }
2585 }], () => {
2586 this.convertString(sb, node, options);
2587 }));
2588 }
2589
2590}
2591
2592// Output: [nullVal]
2593
2594class CreateNullHelper extends CreatePrimitiveHelper {
2595 constructor(...args) {
2596 var _temp;
2597
2598 return _temp = super(...args), Object.defineProperty(this, "length", {
2599 configurable: true,
2600 enumerable: true,
2601 writable: true,
2602 value: 1
2603 }), Object.defineProperty(this, "type", {
2604 configurable: true,
2605 enumerable: true,
2606 writable: true,
2607 value: Types.Null
2608 }), _temp;
2609 }
2610
2611}
2612
2613// Output: [boolean]
2614
2615class IsNullHelper extends IsHelper {
2616 constructor(...args) {
2617 var _temp;
2618
2619 return _temp = super(...args), Object.defineProperty(this, "type", {
2620 configurable: true,
2621 enumerable: true,
2622 writable: true,
2623 value: Types.Null
2624 }), _temp;
2625 }
2626
2627}
2628
2629// Output: [numberVal]
2630
2631class CreateNumberHelper extends CreatePrimitiveHelper {
2632 constructor(...args) {
2633 var _temp;
2634
2635 return _temp = super(...args), Object.defineProperty(this, "type", {
2636 configurable: true,
2637 enumerable: true,
2638 writable: true,
2639 value: Types.Number
2640 }), _temp;
2641 }
2642
2643}
2644
2645// Output: [number]
2646
2647class GetNumberHelper extends GetPrimitiveHelper {}
2648
2649// Output: [boolean]
2650
2651class IsNumberHelper extends IsHelper {
2652 constructor(...args) {
2653 var _temp;
2654
2655 return _temp = super(...args), Object.defineProperty(this, "type", {
2656 configurable: true,
2657 enumerable: true,
2658 writable: true,
2659 value: Types.Number
2660 }), _temp;
2661 }
2662
2663}
2664
2665// be the result.
2666// Input: [val]
2667// Output: [number]
2668
2669class ToNumberHelper extends TypedHelper {
2670 emit(sb, node, options) {
2671 if (!options.pushValue) {
2672 sb.emitOp(node, 'DROP');
2673 return;
2674 }
2675
2676 if (this.type != null) {
2677 this.convertType(sb, node, options, this.type);
2678 } else {
2679 this.convertUnknown(sb, node, options);
2680 }
2681 }
2682
2683 convertType(sb, node, options, type) {
2684 if (isOnlyUndefined(type)) {
2685 this.convertUndefined(sb, node, options);
2686 } else if (isOnlyNull(type)) {
2687 this.convertNull(sb, node, options);
2688 } else if (isOnlyBoolean(type)) {
2689 this.convertBoolean(sb, node, options);
2690 } else if (isOnlyNumber(type)) {
2691 this.convertNumber(sb, node, options);
2692 } else if (isOnlyString(type)) {
2693 this.convertString(sb, node, options);
2694 } else if (isOnlySymbol(type)) {
2695 this.convertSymbol(sb, node, options);
2696 } else if (isOnlyObject(type)) {
2697 this.convertObject(sb, node, options);
2698 } else {
2699 this.convertUnknown(sb, node, options);
2700 }
2701 }
2702
2703 convertUndefined(sb, node, options) {
2704 // TODO: Should we support this?
2705 sb.emitHelper(node, options, sb.helpers.throwTypeError);
2706 }
2707
2708 convertNull(sb, node, options) {
2709 // []
2710 sb.emitOp(node, 'DROP'); // [0]
2711
2712 sb.emitPushInt(node, 0);
2713 }
2714
2715 convertBoolean(sb, node, options) {
2716 sb.emitHelper(node, options, sb.helpers.if({
2717 condition: () => {
2718 sb.emitHelper(node, options, sb.helpers.getBoolean);
2719 },
2720 whenTrue: () => {
2721 // [1]
2722 sb.emitPushInt(node, 1);
2723 },
2724 whenFalse: () => {
2725 // [0]
2726 sb.emitPushInt(node, 0);
2727 }
2728 }));
2729 }
2730
2731 convertNumber(sb, node, options) {
2732 // [value]
2733 sb.emitHelper(node, options, sb.helpers.getNumber);
2734 }
2735
2736 convertString(sb, node, options) {
2737 // TODO: Should we support this?
2738 sb.emitHelper(node, options, sb.helpers.throwTypeError);
2739 }
2740
2741 convertSymbol(sb, node, options) {
2742 sb.emitHelper(node, options, sb.helpers.throwTypeError);
2743 }
2744
2745 convertObject(sb, node, options) {
2746 // [primitive]
2747 sb.emitHelper(node, options, sb.helpers.toPrimitive({
2748 type: this.type,
2749 knownType: Types.Object,
2750 preferredType: 'number'
2751 })); // [value]
2752
2753 this.convertUnknown(sb, node, options, true);
2754 }
2755
2756 convertUnknown(sb, node, options, shouldThrowOnObject = false) {
2757 const emitIf = (check, whenTrue, whenFalse) => sb.emitHelper(node, options, sb.helpers.if({
2758 condition: () => {
2759 // [value, value]
2760 sb.emitOp(node, 'DUP'); // [isValue, value]
2761
2762 sb.emitHelper(node, options, check);
2763 },
2764 whenTrue,
2765 whenFalse
2766 }));
2767
2768 emitIf(sb.helpers.isNumber, () => this.convertNumber(sb, node, options), () => emitIf(sb.helpers.isUndefined, () => this.convertUndefined(sb, node, options), () => emitIf(sb.helpers.isNull, () => this.convertNull(sb, node, options), () => emitIf(sb.helpers.isBoolean, () => this.convertBoolean(sb, node, options), () => emitIf(sb.helpers.isString, () => this.convertString(sb, node, options), () => emitIf(sb.helpers.isSymbol, () => this.convertSymbol(sb, node, options), () => shouldThrowOnObject ? sb.emitHelper(node, options, sb.helpers.throwTypeError) : this.convertObject(sb, node, options)))))));
2769 }
2770
2771}
2772
2773// Output: [objectVal]
2774
2775class CreateObjectHelper extends Helper {
2776 emit(sb, node, options) {
2777 if (options.pushValue) {
2778 /* create internal object */
2779 // [iobj]
2780 sb.emitOp(node, 'NEWMAP');
2781 /* create symbol obj */
2782 // [sobj, iobj]
2783
2784 sb.emitOp(node, 'NEWMAP');
2785 /* create obj */
2786 // [pobj, sobj, iobj]
2787
2788 sb.emitOp(node, 'NEWMAP'); // TODO: Consolidate with ShallowCloneObjectHelper
2789
2790 /* create object array */
2791 // [3, pobj, sobj, iobj]
2792
2793 sb.emitPushInt(node, 3); // [object]
2794
2795 sb.emitOp(node, 'PACK'); // [objectType, object]
2796
2797 sb.emitPushInt(node, Types.Object);
2798 /* create object */
2799 // [2, objectType, object]
2800
2801 sb.emitPushInt(node, 2); // [objectVal]
2802
2803 sb.emitOp(node, 'PACK');
2804 }
2805 }
2806
2807}
2808
2809// Input: [pobj]
2810// Output: [objectVal]
2811class CreatePropertyObjectHelper extends Helper {
2812 emit(sb, node, options) {
2813 if (options.pushValue) {
2814 // TODO: This could use some optimization.
2815 const obj = sb.scope.addUnique();
2816 const pobj = sb.scope.addUnique(); // [pobj, pobj]
2817
2818 sb.emitOp(node, 'DUP'); // [pobj]
2819
2820 sb.scope.set(sb, node, options, pobj); // [objectVal, pobj]
2821
2822 sb.emitHelper(node, options, sb.helpers.createObject); // [objectVal, pobj, objectVal]
2823
2824 sb.emitOp(node, 'TUCK'); // [pobj, objectVal]
2825
2826 sb.scope.set(sb, node, options, obj); // [keysArr, objectVal]
2827
2828 sb.emitOp(node, 'KEYS'); // [objectVal]
2829
2830 sb.emitHelper(node, options, sb.helpers.arrForEach({
2831 each: () => {
2832 // [objectVal, key]
2833 sb.scope.get(sb, node, options, obj); // [pobj, objectVal, key]
2834
2835 sb.scope.get(sb, node, options, pobj); // [key, pobj, objectVal]
2836
2837 sb.emitOp(node, 'ROT'); // [key, pobj, key, objectVal]
2838
2839 sb.emitOp(node, 'TUCK'); // [val, key, objectVal]
2840
2841 sb.emitOp(node, 'PICKITEM'); // []
2842
2843 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
2844 }
2845 }));
2846 }
2847 }
2848
2849}
2850
2851// Output: [val]
2852
2853class ElementAccessHelper extends Helper {
2854 emit(sb, expr, optionsIn) {
2855 const options = sb.pushValueOptions(sb.noSetValueOptions(optionsIn));
2856 const value = expr.getExpression();
2857 const valueType = sb.getType(value);
2858 const prop = expr.getArgumentExpressionOrThrow();
2859 const propType = sb.getType(prop); // [objectVal]
2860
2861 sb.emitHelper(value, options, sb.helpers.toObject({
2862 type: sb.getType(value)
2863 })); // [propVal, objectVal]
2864
2865 sb.visit(prop, options);
2866
2867 if (optionsIn.setValue) {
2868 let valueIndex = 2;
2869
2870 if (optionsIn.pushValue) {
2871 // [objectVal, propVal]
2872 sb.emitOp(expr, 'SWAP'); // [objectVal, propVal, objectVal]
2873
2874 sb.emitOp(expr, 'TUCK'); // [propVal, objectVal, propVal, objectVal]
2875
2876 sb.emitOp(expr, 'OVER');
2877 valueIndex = 4;
2878 }
2879
2880 if (isOnlyString(propType)) {
2881 // [propString, objectVal]
2882 sb.emitHelper(prop, options, sb.helpers.getString); // []
2883
2884 this.setProperty(sb, prop, options, valueIndex);
2885 } else if (isOnlyNumber(propType)) {
2886 // []
2887 this.setNumberProperty(sb, prop, options, propType, valueType, valueIndex);
2888 } else if (isOnlySymbol(propType)) {
2889 // [propString, objectVal]
2890 sb.emitHelper(prop, options, sb.helpers.getSymbol); // []
2891
2892 this.setSymbol(sb, prop, options, valueIndex);
2893 } else {
2894 // []
2895 sb.emitHelper(prop, options, sb.helpers.case([{
2896 condition: () => {
2897 // [propVal, propVal, objectVal]
2898 sb.emitOp(prop, 'DUP'); // [isString, propVal, objectVal]
2899
2900 sb.emitHelper(prop, options, sb.helpers.isString);
2901 },
2902 whenTrue: () => {
2903 // [propString, objectVal]
2904 sb.emitHelper(prop, options, sb.helpers.getString); // []
2905
2906 this.setProperty(sb, prop, options, valueIndex);
2907 }
2908 }, {
2909 condition: () => {
2910 // [propVal, propVal, objectVal]
2911 sb.emitOp(prop, 'DUP'); // [isNumber, propVal, objectVal]
2912
2913 sb.emitHelper(prop, options, sb.helpers.isNumber);
2914 },
2915 whenTrue: () => {
2916 // []
2917 this.setNumberProperty(sb, prop, options, propType, valueType, valueIndex);
2918 }
2919 }], () => {
2920 // [propString, objectVal]
2921 sb.emitHelper(prop, options, sb.helpers.getSymbol); // []
2922
2923 this.setSymbol(sb, prop, options, valueIndex);
2924 }));
2925 }
2926 }
2927
2928 if (optionsIn.pushValue || !optionsIn.setValue) {
2929 if (isOnlyString(propType)) {
2930 // [propString, objectVal]
2931 sb.emitHelper(prop, options, sb.helpers.getString); // [val]
2932
2933 sb.emitHelper(expr, options, sb.helpers.getPropertyObjectProperty);
2934 } else if (isOnlyNumber(propType)) {
2935 // [val]
2936 this.getNumberProperty(sb, prop, options, propType, valueType);
2937 } else if (isOnlySymbol(propType)) {
2938 // [propString, objectVal]
2939 sb.emitHelper(prop, options, sb.helpers.getSymbol); // [val]
2940
2941 sb.emitHelper(expr, options, sb.helpers.getSymbolObjectProperty);
2942 } else {
2943 // [val]
2944 sb.emitHelper(prop, options, sb.helpers.case([{
2945 condition: () => {
2946 // [propVal, propVal, objectVal]
2947 sb.emitOp(prop, 'DUP'); // [propVal, objectVal]
2948
2949 sb.emitHelper(prop, options, sb.helpers.isString);
2950 },
2951 whenTrue: () => {
2952 // [propString, objectVal]
2953 sb.emitHelper(prop, options, sb.helpers.getString); // [val]
2954
2955 sb.emitHelper(expr, options, sb.helpers.getPropertyObjectProperty);
2956 }
2957 }, {
2958 condition: () => {
2959 // [propVal, propVal, objectVal]
2960 sb.emitOp(prop, 'DUP'); // [propVal, objectVal]
2961
2962 sb.emitHelper(prop, options, sb.helpers.isNumber);
2963 },
2964 whenTrue: () => {
2965 // [val]
2966 this.getNumberProperty(sb, prop, options, propType, valueType);
2967 }
2968 }], () => {
2969 // [propString, objectVal]
2970 sb.emitHelper(prop, options, sb.helpers.getSymbol); // [val]
2971
2972 sb.emitHelper(expr, options, sb.helpers.getSymbolObjectProperty);
2973 }));
2974 }
2975 }
2976
2977 if (!optionsIn.pushValue && !optionsIn.setValue) {
2978 sb.emitOp(expr, 'DROP');
2979 }
2980 }
2981
2982 getNumberProperty(sb, node, options, propType, valueType) {
2983 if (isOnlyArray(valueType) || isOnlyTuple(valueType)) {
2984 sb.emitHelper(node, options, sb.helpers.getNumber);
2985 sb.emitHelper(node, options, sb.helpers.getArrayIndex);
2986 } else {
2987 sb.emitHelper(node, options, sb.helpers.if({
2988 condition: () => {
2989 // [isArray, propVal, objectVal]
2990 this.isArrayInstance(sb, node, options);
2991 },
2992 whenTrue: () => {
2993 // [propNumber, objectVal]
2994 sb.emitHelper(node, options, sb.helpers.getNumber); // [val]
2995
2996 sb.emitHelper(node, options, sb.helpers.getArrayIndex);
2997 },
2998 whenFalse: () => {
2999 // [propString, objectVal]
3000 sb.emitHelper(node, options, sb.helpers.toString({
3001 type: propType
3002 })); // [val]
3003
3004 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty);
3005 }
3006 }));
3007 }
3008 }
3009
3010 setProperty(sb, node, options, index) {
3011 // [val, propString, objectVal]
3012 this.pickValue(sb, node, options, index); // []
3013
3014 sb.emitHelper(node, options, sb.helpers.setPropertyObjectProperty);
3015 }
3016
3017 setNumberProperty(sb, node, options, propType, valueType, index) {
3018 if (isOnlyArray(valueType) || isOnlyTuple(valueType)) {
3019 sb.emitHelper(node, options, sb.helpers.getNumber);
3020 this.setArrayIndex(sb, node, options, index);
3021 } else {
3022 sb.emitHelper(node, options, sb.helpers.if({
3023 condition: () => {
3024 // [isArray, propVal, objectVal]
3025 this.isArrayInstance(sb, node, options);
3026 },
3027 whenTrue: () => {
3028 sb.emitHelper(node, options, sb.helpers.getNumber);
3029 this.setArrayIndex(sb, node, options, index);
3030 },
3031 whenFalse: () => {
3032 // [propString, objectVal]
3033 sb.emitHelper(node, options, sb.helpers.toString({
3034 type: propType
3035 })); // []
3036
3037 this.setProperty(sb, node, options, index);
3038 }
3039 }));
3040 }
3041 }
3042
3043 setArrayIndex(sb, node, options, index) {
3044 // [val, propNumber, objectVal]
3045 this.pickValue(sb, node, options, index); // []
3046
3047 sb.emitHelper(node, options, sb.helpers.setArrayIndex);
3048 }
3049
3050 setSymbol(sb, node, options, index) {
3051 // [val, propString, objectVal]
3052 this.pickValue(sb, node, options, index); // []
3053
3054 sb.emitHelper(node, options, sb.helpers.setSymbolObjectProperty);
3055 }
3056
3057 isArrayInstance(sb, node, options) {
3058 // [objectVal, propVal, objectVal]
3059 sb.emitOp(node, 'OVER'); // [Array, objectVal, propVal, objectVal]
3060
3061 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
3062 property: 'Array'
3063 })); // [isArray, propVal, objectVal]
3064
3065 sb.emitHelper(node, options, sb.helpers.instanceof);
3066 }
3067
3068 pickValue(sb, node, options, index) {
3069 if (index === 2) {
3070 sb.emitOp(node, 'ROT');
3071 } else {
3072 // [index, ...]
3073 sb.emitPushInt(node, index); // [val, ...]
3074
3075 sb.emitOp(node, 'ROLL');
3076 }
3077 }
3078
3079}
3080
3081// Input: [stringProp, objectVal]
3082// Output: [val]
3083class FindObjectPropertyHelper extends Helper {
3084 constructor({
3085 accessor,
3086 dataExists,
3087 data,
3088 getObject
3089 }) {
3090 super();
3091 Object.defineProperty(this, "accessor", {
3092 configurable: true,
3093 enumerable: true,
3094 writable: true,
3095 value: void 0
3096 });
3097 Object.defineProperty(this, "dataExists", {
3098 configurable: true,
3099 enumerable: true,
3100 writable: true,
3101 value: void 0
3102 });
3103 Object.defineProperty(this, "data", {
3104 configurable: true,
3105 enumerable: true,
3106 writable: true,
3107 value: void 0
3108 });
3109 Object.defineProperty(this, "getObject", {
3110 configurable: true,
3111 enumerable: true,
3112 writable: true,
3113 value: void 0
3114 });
3115 this.accessor = accessor;
3116 this.dataExists = dataExists;
3117 this.data = data;
3118 this.getObject = getObject;
3119 }
3120
3121 emit(sb, node, options) {
3122 if (!options.pushValue) {
3123 sb.emitOp(node, 'DROP');
3124 sb.emitOp(node, 'DROP');
3125 return;
3126 } // [objectVal, prop]
3127
3128
3129 sb.emitOp(node, 'SWAP');
3130
3131 const prepareLoop = () => {
3132 // [objectVal, objectVal, prop]
3133 sb.emitOp(node, 'DUP'); // [pobj, objectVal, prop]
3134
3135 sb.emitHelper(node, options, sb.helpers.getPropertyObject); // [pobj, pobj, objectVal, prop]
3136
3137 sb.emitOp(node, 'DUP'); // [objectVal, pobj, pobj, prop]
3138
3139 sb.emitOp(node, 'ROT'); // [obj, pobj, pobj, prop]
3140
3141 sb.emitHelper(node, options, this.getObject(sb)); // [obj, obj, pobj, pobj, prop]
3142
3143 sb.emitOp(node, 'DUP'); // [4, obj, obj, pobj, pobj, prop]
3144
3145 sb.emitPushInt(node, 4); // [prop, obj, obj, pobj, pobj, prop]
3146
3147 sb.emitOp(node, 'PICK');
3148 }; // [prop, obj, obj, pobj, pobj, prop]
3149
3150
3151 prepareLoop();
3152 sb.emitHelper(node, options, sb.helpers.forLoop({
3153 condition: () => {
3154 // [hasKey, obj, pobj, pobj, prop]
3155 sb.emitOp(node, 'HASKEY'); // [notHasKey, obj, pobj, pobj, prop]
3156
3157 sb.emitOp(node, 'NOT'); // [pobj, notHasKey, obj, pobj, prop]
3158
3159 sb.emitOp(node, 'ROT'); // ['prototype', pobj, notHasKey, obj, pobj, prop]
3160
3161 sb.emitPushString(node, 'prototype'); // [hasPrototypeKey, notHasKey, obj, pobj, prop]
3162
3163 sb.emitOp(node, 'HASKEY'); // [condition, obj, pobj, prop]
3164
3165 sb.emitOp(node, 'AND');
3166 },
3167 each: () => {
3168 // [pobj, prop]
3169 sb.emitOp(node, 'DROP'); // ['prototype', pobj, prop]
3170
3171 sb.emitPushString(node, 'prototype'); // [propVal, prop]
3172
3173 sb.emitOp(node, 'PICKITEM'); // [0, propVal, prop]
3174
3175 sb.emitPushInt(node, 0); // [objectVal, prop]
3176
3177 sb.emitOp(node, 'PICKITEM'); // [prop, obj, obj, pobj, pobj, prop]
3178
3179 prepareLoop();
3180 },
3181 withScope: false
3182 })); // [obj, prop]
3183
3184 sb.emitOp(node, 'NIP'); // [obj, prop, obj]
3185
3186 sb.emitOp(node, 'TUCK'); // [prop, obj, prop, obj]
3187
3188 sb.emitOp(node, 'OVER'); // [val]
3189
3190 sb.emitHelper(node, options, sb.helpers.if({
3191 condition: () => {
3192 // [hasKey, prop, obj]
3193 sb.emitOp(node, 'HASKEY');
3194 },
3195 whenTrue: () => {
3196 // [propVal]
3197 sb.emitOp(node, 'PICKITEM'); // [propVal, propVal]
3198
3199 sb.emitOp(node, 'DUP');
3200 sb.emitHelper(node, options, sb.helpers.if({
3201 condition: () => {
3202 // [size, propVal]
3203 sb.emitOp(node, 'ARRAYSIZE'); // [2, size, propVal]
3204
3205 sb.emitPushInt(node, 2); // [size === 2, propVal]
3206
3207 sb.emitOp(node, 'EQUAL');
3208 },
3209 whenTrue: () => {
3210 this.accessor();
3211 },
3212 whenFalse: () => {
3213 this.dataExists();
3214 }
3215 }));
3216 },
3217 whenFalse: () => {
3218 // [obj]
3219 sb.emitOp(node, 'DROP'); // []
3220
3221 sb.emitOp(node, 'DROP');
3222 this.data();
3223 }
3224 }));
3225 }
3226
3227}
3228
3229// Input: [objectVal]
3230// Output: [obj]
3231class GetObjectHelperBase extends Helper {
3232 constructor(...args) {
3233 var _temp;
3234
3235 return _temp = super(...args), Object.defineProperty(this, "index", {
3236 configurable: true,
3237 enumerable: true,
3238 writable: true,
3239 value: void 0
3240 }), _temp;
3241 }
3242
3243 emit(sb, node, options) {
3244 if (!options.pushValue) {
3245 sb.emitOp(node, 'DROP');
3246 return;
3247 } // [object]
3248
3249
3250 sb.emitHelper(node, options, sb.helpers.getObject); // [2, object]
3251
3252 sb.emitPushInt(node, this.index); // [obj]
3253
3254 sb.emitOp(node, 'PICKITEM');
3255 }
3256
3257}
3258
3259// Output: [iobj]
3260
3261class GetInternalObjectHelper extends GetObjectHelperBase {
3262 constructor(...args) {
3263 var _temp;
3264
3265 return _temp = super(...args), Object.defineProperty(this, "index", {
3266 configurable: true,
3267 enumerable: true,
3268 writable: true,
3269 value: 2
3270 }), _temp;
3271 }
3272
3273}
3274
3275// Input: [stringProp, objectVal]
3276// Output: [val]
3277class GetInternalObjectPropertyHelper extends Helper {
3278 emit(sb, node, options) {
3279 if (!options.pushValue) {
3280 sb.emitOp(node, 'DROP');
3281 sb.emitOp(node, 'DROP');
3282 return;
3283 } // [objectVal, stringProp]
3284
3285
3286 sb.emitOp(node, 'SWAP'); // [iobj, stringProp]
3287
3288 sb.emitHelper(node, options, sb.helpers.getInternalObject); // [stringProp, iobj]
3289
3290 sb.emitOp(node, 'SWAP'); // [val]
3291
3292 sb.emitOp(node, 'PICKITEM');
3293 }
3294
3295}
3296
3297// Output: [object]
3298
3299class GetObjectHelper extends GetPrimitiveHelper {}
3300
3301// Output: [pobj]
3302
3303class GetPropertyObjectHelper extends GetObjectHelperBase {
3304 constructor(...args) {
3305 var _temp;
3306
3307 return _temp = super(...args), Object.defineProperty(this, "index", {
3308 configurable: true,
3309 enumerable: true,
3310 writable: true,
3311 value: 0
3312 }), _temp;
3313 }
3314
3315}
3316
3317// Input: [stringProp, objectVal]
3318// Output: [val]
3319class GetObjectPropertyHelperBase extends Helper {
3320 emit(sb, node, options) {
3321 // [objectVal, stringProp, objectVal]
3322 sb.emitOp(node, 'OVER'); // [stringProp, objectVal, objectVal]
3323
3324 sb.emitOp(node, 'SWAP');
3325 sb.emitHelper(node, options, sb.helpers.findObjectProperty({
3326 accessor: () => {
3327 // [0, propVal, objectVal]
3328 sb.emitPushInt(node, 0); // [getObjectVal, objectVal]
3329
3330 sb.emitOp(node, 'PICKITEM'); // [val]
3331
3332 sb.emitHelper(node, options, sb.helpers.invokeCall({
3333 bindThis: true,
3334 noArgs: true
3335 }));
3336 },
3337 dataExists: () => {
3338 // [propVal]
3339 sb.emitOp(node, 'NIP');
3340
3341 if (options.pushValue) {
3342 // [0, propVal]
3343 sb.emitPushInt(node, 0); // [val]
3344
3345 sb.emitOp(node, 'PICKITEM');
3346 } else {
3347 // []
3348 sb.emitOp(node, 'DROP');
3349 }
3350 },
3351 data: () => {
3352 // []
3353 sb.emitOp(node, 'DROP');
3354
3355 if (options.pushValue) {
3356 // [val]
3357 sb.emitHelper(node, options, sb.helpers.createUndefined);
3358 }
3359 },
3360 getObject: this.getObject.bind(this)
3361 }));
3362 }
3363
3364}
3365
3366// Output: [val]
3367
3368class GetPropertyObjectPropertyHelper extends GetObjectPropertyHelperBase {
3369 getObject(sb) {
3370 return sb.helpers.getPropertyObject;
3371 }
3372
3373}
3374
3375// Output: [sobj]
3376
3377class GetSymbolObjectHelper extends GetObjectHelperBase {
3378 constructor(...args) {
3379 var _temp;
3380
3381 return _temp = super(...args), Object.defineProperty(this, "index", {
3382 configurable: true,
3383 enumerable: true,
3384 writable: true,
3385 value: 1
3386 }), _temp;
3387 }
3388
3389}
3390
3391// Output: [val]
3392
3393class GetSymbolObjectPropertyHelper extends GetObjectPropertyHelperBase {
3394 getObject(sb) {
3395 return sb.helpers.getSymbolObject;
3396 }
3397
3398}
3399
3400// Input: [constructorObjectVal, objectVal]
3401// Output: [boolean]
3402class InstanceofHelper extends Helper {
3403 emit(sb, node, options) {
3404 if (!options.pushValue) {
3405 sb.emitOp(node, 'DROP');
3406 sb.emitOp(node, 'DROP');
3407 return;
3408 } // ['prototype', constructorObjectVal, objectVal]
3409
3410
3411 sb.emitPushString(node, 'prototype'); // [prototypeVal, objectVal]
3412
3413 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [objectVal, prototypeVal]
3414
3415 sb.emitOp(node, 'SWAP');
3416
3417 const prepareLoop = () => {
3418 // [objectVal, objectVal, prototypeVal]
3419 sb.emitOp(node, 'DUP'); // ['prototype', objectVal, objectVal, prototypeVal]
3420
3421 sb.emitPushString(node, 'prototype'); // [nextPrototypeVal, objectVal, prototypeVal]
3422
3423 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [nextPrototypeVal, nextPrototypeVal, objectVal, prototypeVal]
3424
3425 sb.emitOp(node, 'DUP'); // [objectVal, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3426
3427 sb.emitOp(node, 'ROT'); // [3, objectVal, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3428
3429 sb.emitPushInt(node, 3); // [prototypeVal, objectVal, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3430
3431 sb.emitOp(node, 'PICK');
3432 }; // [prototypeVal, objectVal, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3433
3434
3435 prepareLoop();
3436 sb.emitHelper(node, options, sb.helpers.forLoop({
3437 condition: () => {
3438 // [samePrototype, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3439 sb.emitOp(node, 'EQUAL'); // [samePrototype, samePrototype, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3440
3441 sb.emitOp(node, 'DUP'); // [notSamePrototype, samePrototype, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3442
3443 sb.emitOp(node, 'NOT'); // [nextPrototypeVal, notSamePrototype, samePrototype, nextPrototypeVal, prototypeVal]
3444
3445 sb.emitOp(node, 'ROT'); // [isUndefined, notSamePrototype, samePrototype, nextPrototypeVal, prototypeVal]
3446
3447 sb.emitHelper(node, options, sb.helpers.isUndefined); // [hasPrototype, notSamePrototype, samePrototype, nextPrototypeVal, prototypeVal]
3448
3449 sb.emitOp(node, 'NOT'); // [hasPrototypeAndNotSame, samePrototype, nextPrototypeVal, prototypeVal]
3450
3451 sb.emitOp(node, 'AND');
3452 },
3453 each: () => {
3454 // [nextPrototypeVal, prototypeVal]
3455 sb.emitOp(node, 'DROP'); // [prototypeVal, objectVal, nextPrototypeVal, nextPrototypeVal, prototypeVal]
3456
3457 prepareLoop();
3458 }
3459 })); // [samePrototype, prototypeVal]
3460
3461 sb.emitOp(node, 'NIP'); // [samePrototype]
3462
3463 sb.emitOp(node, 'NIP');
3464 }
3465
3466}
3467
3468// Output: [boolean]
3469
3470class IsObjectHelper extends IsHelper {
3471 constructor(...args) {
3472 var _temp;
3473
3474 return _temp = super(...args), Object.defineProperty(this, "type", {
3475 configurable: true,
3476 enumerable: true,
3477 writable: true,
3478 value: Types.Object
3479 }), _temp;
3480 }
3481
3482}
3483
3484// Input: [?getObjectVal, ?setObjectVal, stringProp, objectVal]
3485// Output: []
3486class SetObjectAccessorPropertyHelperBase extends Helper {
3487 constructor({
3488 hasSet,
3489 hasGet
3490 }) {
3491 super();
3492 Object.defineProperty(this, "hasSet", {
3493 configurable: true,
3494 enumerable: true,
3495 writable: true,
3496 value: void 0
3497 });
3498 Object.defineProperty(this, "hasGet", {
3499 configurable: true,
3500 enumerable: true,
3501 writable: true,
3502 value: void 0
3503 });
3504 this.hasSet = hasSet == null ? false : hasSet;
3505 this.hasGet = hasGet == null ? false : hasGet;
3506
3507 if (!(this.hasSet || this.hasGet)) {
3508 throw new Error('Something went wrong. Must have either a getter or setter');
3509 }
3510 }
3511
3512 emit(sb, node, optionsIn) {
3513 const options = sb.pushValueOptions(optionsIn);
3514
3515 if (!(this.hasSet && this.hasGet)) {
3516 // [val, ?getObjectVal, ?setObjectVal, stringProp, objectVal]
3517 sb.emitHelper(node, options, sb.helpers.createUndefined);
3518
3519 if (this.hasGet) {
3520 // [getObjectVal, setObjectVal, stringProp, objectVal]
3521 sb.emitOp(node, 'SWAP');
3522 }
3523 } // [2, getObjectVal, setObjectVal, stringProp, objectVal]
3524
3525
3526 sb.emitPushInt(node, 2); // [val, stringProp, objectVal]
3527
3528 sb.emitOp(node, 'PACK'); // [objectVal, val, stringProp]
3529
3530 sb.emitOp(node, 'ROT'); // [obj, val, stringProp]
3531
3532 sb.emitHelper(node, options, this.getObject(sb)); // [stringProp, obj, val]
3533
3534 sb.emitOp(node, 'ROT'); // [val, stringProp, obj]
3535
3536 sb.emitOp(node, 'ROT'); // []
3537
3538 sb.emitOp(node, 'SETITEM');
3539 }
3540
3541}
3542
3543// Output: []
3544
3545class SetAccessorPropertyObjectPropertyHelper extends SetObjectAccessorPropertyHelperBase {
3546 getObject(sb) {
3547 return sb.helpers.getPropertyObject;
3548 }
3549
3550}
3551
3552// Output: []
3553
3554class SetAccessorSymbolObjectPropertyHelper extends SetObjectAccessorPropertyHelperBase {
3555 getObject(sb) {
3556 return sb.helpers.getSymbolObject;
3557 }
3558
3559}
3560
3561// Input: [val, stringProp, objectVal]
3562// Output: []
3563class SetObjectDataPropertyHelperBase extends Helper {
3564 emit(sb, node, options) {
3565 // [objectVal, val, stringProp]
3566 sb.emitOp(node, 'ROT'); // [obj, val, stringProp]
3567
3568 sb.emitHelper(node, sb.pushValueOptions(options), this.getObject(sb)); // [stringProp, obj, val]
3569
3570 sb.emitOp(node, 'ROT'); // [val, stringProp, obj]
3571
3572 sb.emitOp(node, 'ROT'); // [1, val, stringProp, obj]
3573
3574 sb.emitPushInt(node, 1); // [propVal, stringProp, obj]
3575
3576 sb.emitOp(node, 'PACK'); // []
3577
3578 sb.emitOp(node, 'SETITEM');
3579 }
3580
3581}
3582
3583// Output: []
3584
3585class SetDataPropertyObjectPropertyHelper extends SetObjectDataPropertyHelperBase {
3586 getObject(sb) {
3587 return sb.helpers.getPropertyObject;
3588 }
3589
3590}
3591
3592// Output: []
3593
3594class SetDataSymbolObjectPropertyHelper extends SetObjectDataPropertyHelperBase {
3595 getObject(sb) {
3596 return sb.helpers.getSymbolObject;
3597 }
3598
3599}
3600
3601// Input: [val, stringProp, objectVal]
3602// Output: []
3603class SetInternalObjectPropertyHelper extends Helper {
3604 emit(sb, node, options) {
3605 // [objectVal, val, stringProp]
3606 sb.emitOp(node, 'ROT'); // [obj, val, stringProp]
3607
3608 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.getInternalObject); // [stringProp, obj, val]
3609
3610 sb.emitOp(node, 'ROT'); // [val, stringProp, obj]
3611
3612 sb.emitOp(node, 'ROT'); // []
3613
3614 sb.emitOp(node, 'SETITEM');
3615 }
3616
3617}
3618
3619// Input: [val, stringProp, objectVal]
3620// Output: [val]
3621class SetObjectPropertyHelperBase extends Helper {
3622 emit(sb, node, options) {
3623 // [objectVal, val, stringProp]
3624 sb.emitOp(node, 'ROT'); // [stringProp, objectVal, val]
3625
3626 sb.emitOp(node, 'ROT'); // [stringProp, objectVal, stringProp, val]
3627
3628 sb.emitOp(node, 'TUCK'); // [objectVal, stringProp, objectVal, stringProp, val]
3629
3630 sb.emitOp(node, 'OVER'); // [stringProp, objectVal, objectVal, stringProp, val]
3631
3632 sb.emitOp(node, 'SWAP');
3633 sb.emitHelper(node, options, sb.helpers.findObjectProperty({
3634 accessor: () => {
3635 // [1, propVal, objectVal, stringProp, val]
3636 sb.emitPushInt(node, 1); // [setObjectVal, objectVal, stringProp, val]
3637
3638 sb.emitOp(node, 'PICKITEM'); // [stringProp, setObjectVal, objectVal, val]
3639
3640 sb.emitOp(node, 'ROT'); // [setObjectVal, objectVal, val]
3641
3642 sb.emitOp(node, 'DROP'); // [val, setObjectVal, objectVal]
3643
3644 sb.emitOp(node, 'ROT'); // [1, val, setObjectVal, objectVal]
3645
3646 sb.emitPushInt(node, 1); // [argsarr, setObjectVal, objectVal]
3647
3648 sb.emitOp(node, 'PACK'); // [objectVal, argsarr, setObjectVal]
3649
3650 sb.emitOp(node, 'ROT'); // [setObjectVal, objectVal, argsarr]
3651
3652 sb.emitOp(node, 'ROT'); // [val]
3653
3654 sb.emitHelper(node, options, sb.helpers.invokeCall({
3655 bindThis: true,
3656 noArgs: false
3657 }));
3658 },
3659 dataExists: () => {
3660 // [propVal, stringProp, val]
3661 sb.emitOp(node, 'NIP'); // [propVal, val]
3662
3663 sb.emitOp(node, 'NIP'); // [0, propVal, val]
3664
3665 sb.emitPushInt(node, 0); // [val, 0, propVal]
3666
3667 sb.emitOp(node, 'ROT'); // []
3668
3669 sb.emitOp(node, 'SETITEM');
3670 },
3671 data: () => {
3672 // [stringProp, objectVal, val]
3673 sb.emitOp(node, 'SWAP'); // [val, stringProp, objectVal]
3674
3675 sb.emitOp(node, 'ROT'); // []
3676
3677 sb.emitHelper(node, options, this.setDataProperty(sb));
3678 },
3679 getObject: this.getObject.bind(this)
3680 }));
3681 }
3682
3683}
3684
3685// Output: []
3686
3687class SetPropertyObjectPropertyHelper extends SetObjectPropertyHelperBase {
3688 getObject(sb) {
3689 return sb.helpers.getPropertyObject;
3690 }
3691
3692 setDataProperty(sb) {
3693 return sb.helpers.setDataPropertyObjectProperty;
3694 }
3695
3696}
3697
3698// Output: []
3699
3700class SetSymbolObjectPropertyHelper extends SetObjectPropertyHelperBase {
3701 getObject(sb) {
3702 return sb.helpers.getSymbolObject;
3703 }
3704
3705 setDataProperty(sb) {
3706 return sb.helpers.setDataSymbolObjectProperty;
3707 }
3708
3709}
3710
3711// Output: [objectVal]
3712
3713class ShallowCloneObjectHelper extends Helper {
3714 emit(sb, node, options) {
3715 if (!options.pushValue) {
3716 sb.emitOp(node, 'DROP');
3717 return;
3718 } // [object]
3719
3720
3721 sb.emitHelper(node, options, sb.helpers.getObject); // [length, pobj, sobj, iobj, ...]
3722
3723 sb.emitOp(node, 'UNPACK');
3724
3725 const roll = () => {
3726 // [3, length, pobj, sobj, iobj, ...]
3727 sb.emitPushInt(node, 3); // [iobj, length, pobj, sobj, ...]
3728
3729 sb.emitOp(node, 'ROLL');
3730 };
3731
3732 const clone = () => {
3733 roll(); // [iobj, length, pobj, sobj, ...]
3734
3735 sb.emitHelper(node, options, sb.helpers.shallowCloneObj);
3736 }; // [iobj, length, pobj, sobj, ...]
3737
3738
3739 clone(); // [sobj, iobj, length, pobj, ...]
3740
3741 clone(); // [pobj, sobj, iobj, length, ...]
3742
3743 clone(); // [length, pobj, sobj, iobj, ...]
3744
3745 roll(); // [object]
3746
3747 sb.emitOp(node, 'PACK'); // [objectType, object]
3748
3749 sb.emitPushInt(node, Types.Object); // TODO: Consolidate with CreateObjectHelper
3750
3751 /* create object */
3752 // [2, objectType, object]
3753
3754 sb.emitPushInt(node, 2); // [objectVal]
3755
3756 sb.emitOp(node, 'PACK');
3757 }
3758
3759}
3760
3761// Input: [obj]
3762// Output: [obj]
3763class ShallowCloneObjHelper extends Helper {
3764 emit(sb, node, options) {
3765 if (!options.pushValue) {
3766 sb.emitOp(node, 'DROP');
3767 return;
3768 }
3769 /* create new obj */
3770 // [newObj, oldObj]
3771
3772
3773 sb.emitOp(node, 'NEWMAP'); // [oldObj, newObj]
3774
3775 sb.emitOp(node, 'SWAP');
3776 /* get keys and values */
3777 // [oldObj, oldObj, newObj]
3778
3779 sb.emitOp(node, 'DUP'); // [valuesArray, oldObj, newObj]
3780
3781 sb.emitOp(node, 'VALUES'); // [oldObj, valuesArray, newObj]
3782
3783 sb.emitOp(node, 'SWAP'); // [keysArray, valuesArray, newObj]
3784
3785 sb.emitOp(node, 'KEYS');
3786 /* set keys/values on new obj */
3787
3788 sb.withScope(node, options, scopeOptions => {
3789 const counter = sb.scope.addUnique();
3790 const length = sb.scope.addUnique();
3791 sb.emitHelper(node, scopeOptions, sb.helpers.forLoop({
3792 initializer: () => {
3793 // [keysArray, keysArray, valuesArray, newObj]
3794 sb.emitOp(node, 'DUP'); // [length, keysArray, valuesArray, newObj]
3795
3796 sb.emitOp(node, 'ARRAYSIZE'); // [keysArray, valuesArray, newObj]
3797
3798 sb.scope.set(sb, node, scopeOptions, length); // [counter, keysArray, valuesArray, newObj]
3799
3800 sb.emitPushInt(node, 0); // [keysArray, valuesArray, newObj]
3801
3802 sb.scope.set(sb, node, scopeOptions, counter);
3803 },
3804 condition: () => {
3805 // [counter]
3806 sb.scope.get(sb, node, scopeOptions, counter); // [length, counter]
3807
3808 sb.scope.get(sb, node, scopeOptions, length); // [lt]
3809
3810 sb.emitOp(node, 'LT');
3811 },
3812 incrementor: () => {
3813 // [counter]
3814 sb.scope.get(sb, node, scopeOptions, counter); // [counter]
3815
3816 sb.emitOp(node, 'INC'); // []
3817
3818 sb.scope.set(sb, node, scopeOptions, counter);
3819 },
3820 each: innerOptions => {
3821 // [keysArray, valuesArray, keysArray, newObj]
3822 sb.emitOp(node, 'TUCK'); // [valuesArray, keysArray, valuesArray, keysArray, newObj]
3823
3824 sb.emitOp(node, 'OVER'); // [counter, valuesArray, keysArray, valuesArray, keysArray, newObj]
3825
3826 sb.scope.get(sb, node, innerOptions, counter); // [counter, valuesArray, counter, keysArray, valuesArray, keysArray, newObj]
3827
3828 sb.emitOp(node, 'TUCK'); // [value, counter, keysArray, valuesArray, keysArray, newObj]
3829
3830 sb.emitOp(node, 'PICKITEM'); // [keysArray, value, counter, valuesArray, keysArray, newObj]
3831
3832 sb.emitOp(node, 'ROT'); // [counter, keysArray, value, valuesArray, keysArray, newObj]
3833
3834 sb.emitOp(node, 'ROT'); // [key, value, valuesArray, keysArray, newObj]
3835
3836 sb.emitOp(node, 'PICKITEM'); // [4, key, value, valuesArray, keysArray, newObj]
3837
3838 sb.emitPushInt(node, 4); // [newObj, key, value, valuesArray, keysArray, newObj]
3839
3840 sb.emitOp(node, 'PICK'); // [key, newObj, value, valuesArray, keysArray, newObj]
3841
3842 sb.emitOp(node, 'SWAP'); // [value, key, newObj, valuesArray, keysArray, newObj]
3843
3844 sb.emitOp(node, 'ROT'); // [valuesArray, keysArray, newObj]
3845
3846 sb.emitOp(node, 'SETITEM');
3847 }
3848 }));
3849 }); // [keysArray, newObj]
3850
3851 sb.emitOp(node, 'DROP'); // [newObj]
3852
3853 sb.emitOp(node, 'DROP');
3854 }
3855
3856}
3857
3858// Output: [objectVal]
3859
3860class ToObjectHelper extends TypedHelper {
3861 emit(sb, node, options) {
3862 if (!options.pushValue) {
3863 sb.emitOp(node, 'DROP');
3864 return;
3865 }
3866
3867 const type = this.type;
3868
3869 if (isOnlyBoolean(type)) {
3870 this.convertPrimitive(sb, node, options, 'Boolean');
3871 } else if (isOnlyNumber(type)) {
3872 this.convertPrimitive(sb, node, options, 'Number');
3873 } else if (isOnlyString(type)) {
3874 this.convertPrimitive(sb, node, options, 'String');
3875 } else if (isOnlySymbol(type)) {
3876 this.convertPrimitive(sb, node, options, 'Symbol');
3877 } else if (isOnlyObject(type)) {
3878 return;
3879 } else {
3880 sb.emitHelper(node, options, sb.helpers.case([{
3881 condition: () => {
3882 // [val, val]
3883 sb.emitOp(node, 'DUP'); // [isObject, val]
3884
3885 sb.emitHelper(node, options, sb.helpers.isObject);
3886 },
3887 whenTrue: () => {// do nothing
3888 }
3889 }].concat([{
3890 helper: sb.helpers.isBoolean,
3891 primitive: 'Boolean'
3892 }, {
3893 helper: sb.helpers.isNumber,
3894 primitive: 'Number'
3895 }, {
3896 helper: sb.helpers.isString,
3897 primitive: 'String'
3898 }, {
3899 helper: sb.helpers.isSymbol,
3900 primitive: 'Symbol'
3901 }].map(({
3902 helper,
3903 primitive
3904 }) => ({
3905 condition: () => {
3906 // [val, val]
3907 sb.emitOp(node, 'DUP'); // [isObject, val]
3908
3909 sb.emitHelper(node, options, sb.helpers.isObject);
3910 },
3911 whenTrue: () => {
3912 this.convertPrimitive(sb, node, options, primitive);
3913 }
3914 }))), () => {
3915 sb.emitHelper(node, options, sb.helpers.throwTypeError);
3916 }));
3917 }
3918 }
3919
3920 convertPrimitive(sb, node, options, primitive) {
3921 // [1, val]
3922 sb.emitPushInt(node, 1); // [valArgsArray]
3923
3924 sb.emitOp(node, 'PACK'); // [globalObjectVal, valArgsArray]
3925
3926 sb.scope.getGlobal(sb, node, options); // [primitiveString, globalObjectVal, valArgsArray]
3927
3928 sb.emitPushString(node, primitive); // [primitiveObjectVal, valArgsArray]
3929
3930 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [val]
3931
3932 sb.emitHelper(node, options, sb.helpers.invokeCall());
3933 }
3934
3935}
3936
3937// Output: [stringVal]
3938
3939class CreateStringHelper extends CreatePrimitiveHelper {
3940 constructor(...args) {
3941 var _temp;
3942
3943 return _temp = super(...args), Object.defineProperty(this, "type", {
3944 configurable: true,
3945 enumerable: true,
3946 writable: true,
3947 value: Types.String
3948 }), _temp;
3949 }
3950
3951}
3952
3953// Output: [string]
3954
3955class GetStringHelper extends GetPrimitiveHelper {}
3956
3957// Output: [boolean]
3958
3959class IsStringHelper extends IsHelper {
3960 constructor(...args) {
3961 var _temp;
3962
3963 return _temp = super(...args), Object.defineProperty(this, "type", {
3964 configurable: true,
3965 enumerable: true,
3966 writable: true,
3967 value: Types.String
3968 }), _temp;
3969 }
3970
3971}
3972
3973// Output: [string]
3974
3975class ToStringHelper extends TypedHelper {
3976 emit(sb, node, options) {
3977 if (!options.pushValue) {
3978 sb.emitOp(node, 'DROP');
3979 return;
3980 }
3981
3982 if (this.type != null) {
3983 this.convertType(sb, node, options, this.type);
3984 } else {
3985 this.convertUnknown(sb, node, options);
3986 }
3987 }
3988
3989 convertType(sb, node, options, type) {
3990 if (isOnlyUndefined(type)) {
3991 this.convertUndefined(sb, node, options);
3992 } else if (isOnlyNull(type)) {
3993 this.convertNull(sb, node, options);
3994 } else if (isOnlyBoolean(type)) {
3995 this.convertBoolean(sb, node, options);
3996 } else if (isOnlyNumber(type)) {
3997 this.convertNumber(sb, node, options);
3998 } else if (isOnlyString(type)) {
3999 this.convertString(sb, node, options);
4000 } else if (isOnlySymbol(type)) {
4001 this.convertSymbol(sb, node, options);
4002 } else if (isOnlyObject(type)) {
4003 this.convertObject(sb, node, options);
4004 } else {
4005 this.convertUnknown(sb, node, options);
4006 }
4007 }
4008
4009 convertUndefined(sb, node, options) {
4010 sb.emitPushString(node, 'undefined');
4011 }
4012
4013 convertNull(sb, node, options) {
4014 sb.emitPushString(node, 'null');
4015 }
4016
4017 convertBoolean(sb, node, options) {
4018 sb.emitHelper(node, options, sb.helpers.if({
4019 condition: () => {
4020 sb.emitHelper(node, options, sb.helpers.getBoolean);
4021 },
4022 whenTrue: () => {
4023 sb.emitPushString(node, 'true');
4024 },
4025 whenFalse: () => {
4026 sb.emitPushString(node, 'false');
4027 }
4028 }));
4029 }
4030
4031 convertNumber(sb, node, options) {
4032 // TODO: Try to support this
4033 sb.emitHelper(node, options, sb.helpers.throwTypeError);
4034 }
4035
4036 convertString(sb, node, options) {
4037 sb.emitHelper(node, options, sb.helpers.getString);
4038 }
4039
4040 convertSymbol(sb, node, options) {
4041 sb.emitHelper(node, options, sb.helpers.throwTypeError);
4042 }
4043
4044 convertObject(sb, node, options) {
4045 // [primitive]
4046 sb.emitHelper(node, options, sb.helpers.toPrimitive({
4047 type: this.type,
4048 preferredType: 'string'
4049 })); // [value]
4050
4051 this.convertUnknown(sb, node, options, true);
4052 }
4053
4054 convertUnknown(sb, node, options, shouldThrowOnObject = false) {
4055 const emitIf = (check, whenTrue, whenFalse) => sb.emitHelper(node, options, sb.helpers.if({
4056 condition: () => {
4057 // [value, value]
4058 sb.emitOp(node, 'DUP'); // [isValue, value]
4059
4060 sb.emitHelper(node, options, check);
4061 },
4062 whenTrue,
4063 whenFalse
4064 }));
4065
4066 emitIf(sb.helpers.isString, () => this.convertString(sb, node, options), () => emitIf(sb.helpers.isUndefined, () => this.convertUndefined(sb, node, options), () => emitIf(sb.helpers.isNull, () => this.convertNull(sb, node, options), () => emitIf(sb.helpers.isBoolean, () => this.convertBoolean(sb, node, options), () => emitIf(sb.helpers.isNumber, () => this.convertNumber(sb, node, options), () => emitIf(sb.helpers.isSymbol, () => this.convertSymbol(sb, node, options), () => shouldThrowOnObject ? sb.emitHelper(node, options, sb.helpers.throwTypeError) : this.convertObject(sb, node, options)))))));
4067 }
4068
4069}
4070
4071// Output: [symbolVal]
4072
4073class CreateSymbolHelper extends CreatePrimitiveHelper {
4074 constructor(...args) {
4075 var _temp;
4076
4077 return _temp = super(...args), Object.defineProperty(this, "type", {
4078 configurable: true,
4079 enumerable: true,
4080 writable: true,
4081 value: Types.Symbol
4082 }), _temp;
4083 }
4084
4085}
4086
4087// Output: [string]
4088
4089class GetSymbolHelper extends GetPrimitiveHelper {}
4090
4091// Output: [boolean]
4092
4093class IsSymbolHelper extends IsHelper {
4094 constructor(...args) {
4095 var _temp;
4096
4097 return _temp = super(...args), Object.defineProperty(this, "type", {
4098 configurable: true,
4099 enumerable: true,
4100 writable: true,
4101 value: Types.Symbol
4102 }), _temp;
4103 }
4104
4105}
4106
4107// Output: [undefinedVal]
4108
4109class CreateUndefinedHelper extends CreatePrimitiveHelper {
4110 constructor(...args) {
4111 var _temp;
4112
4113 return _temp = super(...args), Object.defineProperty(this, "length", {
4114 configurable: true,
4115 enumerable: true,
4116 writable: true,
4117 value: 1
4118 }), Object.defineProperty(this, "type", {
4119 configurable: true,
4120 enumerable: true,
4121 writable: true,
4122 value: Types.Undefined
4123 }), _temp;
4124 }
4125
4126}
4127
4128// Output: [boolean]
4129
4130class IsUndefinedHelper extends IsHelper {
4131 constructor(...args) {
4132 var _temp;
4133
4134 return _temp = super(...args), Object.defineProperty(this, "type", {
4135 configurable: true,
4136 enumerable: true,
4137 writable: true,
4138 value: Types.Undefined
4139 }), _temp;
4140 }
4141
4142}
4143
4144// Input: [val]
4145// Output: [boolean]
4146class IsNullOrUndefinedHelper extends Helper {
4147 emit(sb, node, options) {
4148 if (!options.pushValue) {
4149 sb.emitOp(node, 'DROP');
4150 return;
4151 } // [val, val]
4152
4153
4154 sb.emitOp(node, 'DUP'); // [isNullBoolean, val]
4155
4156 sb.emitHelper(node, options, sb.helpers.isNull); // [val, isNullBoolean]
4157
4158 sb.emitOp(node, 'SWAP'); // [isUndefinedBoolean, isNullBoolean]
4159
4160 sb.emitHelper(node, options, sb.helpers.isUndefined); // [boolean]
4161
4162 sb.emitOp(node, 'BOOLOR');
4163 }
4164
4165}
4166
4167// Input: [val0, val1]
4168// Output: [boolean]
4169class IsSameTypeHelper extends Helper {
4170 emit(sb, node, options) {
4171 if (!options.pushValue) {
4172 sb.emitOp(node, 'DROP');
4173 sb.emitOp(node, 'DROP');
4174 return;
4175 } // [type0, val1]
4176
4177
4178 sb.emitHelper(node, options, sb.helpers.unwrapType); // [val1, type0]
4179
4180 sb.emitOp(node, 'SWAP'); // [type1, type0]
4181
4182 sb.emitHelper(node, options, sb.helpers.unwrapType); // [boolean]
4183
4184 sb.emitOp(node, 'EQUAL');
4185 }
4186
4187}
4188
4189// NOTE: Unlike the other To* methods, this returns a wrapped value.
4190// Input: [val]
4191// Output: [val]
4192class ToPrimitiveHelper extends Helper {
4193 constructor({
4194 type,
4195 knownType,
4196 preferredType
4197 }) {
4198 super();
4199 Object.defineProperty(this, "type", {
4200 configurable: true,
4201 enumerable: true,
4202 writable: true,
4203 value: void 0
4204 });
4205 Object.defineProperty(this, "knownType", {
4206 configurable: true,
4207 enumerable: true,
4208 writable: true,
4209 value: void 0
4210 });
4211 Object.defineProperty(this, "preferredType", {
4212 configurable: true,
4213 enumerable: true,
4214 writable: true,
4215 value: void 0
4216 });
4217 this.type = type;
4218 this.knownType = knownType;
4219 this.preferredType = preferredType || 'default';
4220 }
4221
4222 emit(sb, node, options) {
4223 if (!options.pushValue) {
4224 sb.emitOp(node, 'DROP');
4225 return;
4226 }
4227
4228 if (!isOnlyPrimitive(this.type)) {
4229 if (this.type == null && this.knownType !== Types.Object) {
4230 this.toPrimitive(sb, node, options);
4231 } else {
4232 this.toPrimitiveObject(sb, node, options);
4233 }
4234 }
4235 }
4236
4237 toPrimitive(sb, node, options) {
4238 sb.emitHelper(node, options, sb.helpers.if({
4239 condition: () => {
4240 // [value, value]
4241 sb.emitOp(node, 'DUP'); // [isObject, value]
4242
4243 sb.emitHelper(node, options, sb.helpers.isObject);
4244 },
4245 whenTrue: () => {
4246 this.toPrimitiveObject(sb, node, options);
4247 }
4248 }));
4249 }
4250
4251 toPrimitiveObject(sb, node, options) {
4252 // [value, value]
4253 sb.emitOp(node, 'DUP'); // [symbol, value, value]
4254
4255 sb.emitPushString(node, '@@toPrimitive'); // [toPrimitive, value]
4256
4257 sb.emitHelper(node, options, sb.helpers.getSymbolObjectProperty);
4258 sb.emitHelper(node, options, sb.helpers.if({
4259 condition: () => {
4260 // [toPrimitive, toPrimitive, value]
4261 sb.emitOp(node, 'DUP'); // [isUndefined, toPrimitive, value]
4262
4263 sb.emitHelper(node, options, sb.helpers.isUndefined);
4264 },
4265 whenTrue: () => {
4266 // [value]
4267 sb.emitOp(node, 'DROP'); // [value]
4268
4269 this.tryConvert(sb, node, options, this.preferredType);
4270 },
4271 whenFalse: () => {
4272 // [preferredType, toPrimitiveVal, val]
4273 sb.emitPushString(node, this.preferredType); // [1, preferredType, toPrimitiveVal, val]
4274
4275 sb.emitPushInt(node, 1); // [args, toPrimitiveVal, val]
4276
4277 sb.emitOp(node, 'PACK'); // [val, args, toPrimitiveVal]
4278
4279 sb.emitOp(node, 'ROT'); // [toPrimitiveVal, val, args]
4280
4281 sb.emitOp(node, 'ROT'); // [val]
4282
4283 sb.emitHelper(node, options, sb.helpers.invokeCall({
4284 bindThis: true
4285 }));
4286 }
4287 }));
4288 }
4289
4290 tryConvert(sb, node, options, preferredType) {
4291 const methods = preferredType === 'string' ? ['toString', 'valueOf'] : ['valueOf', 'toString']; // [value, value]
4292
4293 sb.emitOp(node, 'DUP'); // [method, value]
4294
4295 sb.emitPushString(node, methods[0]); // [func, value]
4296
4297 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty);
4298 sb.emitHelper(node, options, sb.helpers.if({
4299 condition: () => {
4300 // [func, func, value]
4301 sb.emitOp(node, 'DUP'); // [isUndefined, func, value]
4302
4303 sb.emitHelper(node, options, sb.helpers.isUndefined);
4304 },
4305 whenTrue: () => {
4306 // [value]
4307 sb.emitOp(node, 'DROP'); // [value, value]
4308
4309 sb.emitOp(node, 'DUP'); // [method, value]
4310
4311 sb.emitPushString(node, methods[1]); // [func, value]
4312
4313 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty);
4314 sb.emitHelper(node, options, sb.helpers.if({
4315 condition: () => {
4316 // [func, func, value]
4317 sb.emitOp(node, 'DUP'); // [isUndefined, func, value]
4318
4319 sb.emitHelper(node, options, sb.helpers.isUndefined);
4320 },
4321 whenTrue: () => {
4322 // [value]
4323 sb.emitOp(node, 'DROP'); // []
4324
4325 sb.emitOp(node, 'DROP'); // []
4326
4327 sb.emitHelper(node, options, sb.helpers.throwTypeError);
4328 },
4329 whenFalse: () => {
4330 sb.emitHelper(node, options, sb.helpers.invokeCall({
4331 bindThis: true,
4332 noArgs: true
4333 }));
4334 }
4335 }));
4336 },
4337 whenFalse: () => {
4338 sb.emitHelper(node, options, sb.helpers.invokeCall({
4339 bindThis: true,
4340 noArgs: true
4341 }));
4342 }
4343 }));
4344 }
4345
4346}
4347
4348// Input: [val]
4349// Output: [type]
4350class UnwrapTypeHelper extends Helper {
4351 emit(sb, node, options) {
4352 if (!options.pushValue) {
4353 sb.emitOp(node, 'DROP');
4354 return;
4355 } // [0, val]
4356
4357
4358 sb.emitPushInt(node, 0); // [value]
4359
4360 sb.emitOp(node, 'PICKITEM');
4361 }
4362
4363}
4364
4365// Input: [val]
4366// Output: [value]
4367// Must not be undefined or null
4368class UnwrapValHelper extends Helper {
4369 emit(sb, node, options) {
4370 if (!options.pushValue) {
4371 sb.emitOp(node, 'DROP');
4372 return;
4373 } // [1, val]
4374
4375
4376 sb.emitPushInt(node, 1); // [value]
4377
4378 sb.emitOp(node, 'PICKITEM');
4379 }
4380
4381}
4382
4383// Input: []
4384// Output: [boolean]
4385class EqualsEqualsEqualsHelper extends Helper {
4386 constructor(options) {
4387 super();
4388 Object.defineProperty(this, "left", {
4389 configurable: true,
4390 enumerable: true,
4391 writable: true,
4392 value: void 0
4393 });
4394 Object.defineProperty(this, "right", {
4395 configurable: true,
4396 enumerable: true,
4397 writable: true,
4398 value: void 0
4399 });
4400 this.left = options.left;
4401 this.right = options.right;
4402 }
4403
4404 emit(sb, node, options) {
4405 sb.visit(this.left, options);
4406 sb.visit(this.right, options);
4407
4408 if (!options.pushValue) {
4409 sb.emitOp(node, 'DROP');
4410 sb.emitOp(node, 'DROP');
4411 return;
4412 }
4413
4414 if (isSame(sb.getType(this.left), sb.getType(this.right))) {
4415 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsSameType);
4416 } else {
4417 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsUnknown);
4418 }
4419 }
4420
4421}
4422
4423// Input: [numberVal, numberVal]
4424// Output: [boolean]
4425class EqualsEqualsEqualsNumberHelper extends Helper {
4426 emit(sb, node, options) {
4427 if (!options.pushValue) {
4428 sb.emitOp(node, 'DROP');
4429 sb.emitOp(node, 'DROP');
4430 return;
4431 } // [number, numberVal]
4432
4433
4434 sb.emitHelper(node, options, sb.helpers.getNumber); // [numberVal, number]
4435
4436 sb.emitOp(node, 'SWAP'); // [number, number]
4437
4438 sb.emitHelper(node, options, sb.helpers.getNumber); // [boolean]
4439
4440 sb.emitOp(node, 'NUMEQUAL');
4441 }
4442
4443}
4444
4445// Input: [val0, val1]
4446// Output: [boolean]
4447class EqualsEqualsEqualsSameTypeHelper extends Helper {
4448 emit(sb, node, options) {
4449 if (!options.pushValue) {
4450 sb.emitOp(node, 'DROP');
4451 sb.emitOp(node, 'DROP');
4452 return;
4453 }
4454
4455 sb.emitHelper(node, options, sb.helpers.if({
4456 condition: () => {
4457 // [val0, val0, val1]
4458 sb.emitOp(node, 'DUP'); // [isNullOrUndefined]
4459
4460 sb.emitHelper(node, options, sb.helpers.isNullOrUndefined);
4461 },
4462 whenTrue: () => {
4463 // [val1]
4464 sb.emitOp(node, 'DROP'); // []
4465
4466 sb.emitOp(node, 'DROP'); // [boolean]
4467
4468 sb.emitPushBoolean(node, true);
4469 },
4470 whenFalse: () => {
4471 // [value0, val1]
4472 sb.emitHelper(node, options, sb.helpers.unwrapVal); // [val1, value0]
4473
4474 sb.emitOp(node, 'SWAP'); // [value1, value0]
4475
4476 sb.emitHelper(node, options, sb.helpers.unwrapVal); // [boolean]
4477
4478 sb.emitOp(node, 'EQUAL');
4479 }
4480 }));
4481 }
4482
4483}
4484
4485// Input: [val0, val1]
4486// Output: [boolean]
4487class EqualsEqualsEqualsUnknownHelper extends Helper {
4488 emit(sb, node, options) {
4489 if (!options.pushValue) {
4490 sb.emitOp(node, 'DROP');
4491 sb.emitOp(node, 'DROP');
4492 return;
4493 }
4494
4495 sb.emitHelper(node, options, sb.helpers.if({
4496 condition: () => {
4497 // [val1, val0, val1]
4498 sb.emitOp(node, 'TUCK'); // [val0, val1, val0, val1]
4499
4500 sb.emitOp(node, 'OVER');
4501 sb.emitHelper(node, options, sb.helpers.isSameType);
4502 },
4503 whenTrue: () => {
4504 // [boolean]
4505 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsSameType);
4506 },
4507 whenFalse: () => {
4508 // [val1]
4509 sb.emitOp(node, 'DROP'); // []
4510
4511 sb.emitOp(node, 'DROP'); // [boolean]
4512
4513 sb.emitPushBoolean(node, false);
4514 }
4515 }));
4516 }
4517
4518}
4519
4520// Input: []
4521// Output: [boolean]
4522class EqualsEqualsHelper extends Helper {
4523 constructor(options) {
4524 super();
4525 Object.defineProperty(this, "left", {
4526 configurable: true,
4527 enumerable: true,
4528 writable: true,
4529 value: void 0
4530 });
4531 Object.defineProperty(this, "right", {
4532 configurable: true,
4533 enumerable: true,
4534 writable: true,
4535 value: void 0
4536 });
4537 this.left = options.left;
4538 this.right = options.right;
4539 }
4540
4541 emit(sb, node, options) {
4542 if (!options.pushValue) {
4543 sb.visit(this.left, options);
4544 sb.visit(this.right, options);
4545 return;
4546 }
4547
4548 const leftType = sb.getType(this.left);
4549 const rightType = sb.getType(this.right);
4550
4551 if (leftType != null && rightType != null) {
4552 this.equalsEqualsType(sb, node, options, leftType, rightType);
4553 } else {
4554 this.equalsEqualsUnknown(sb, node, options);
4555 }
4556 }
4557
4558 equalsEqualsType(sb, node, options, leftType, rightType) {
4559 if (isSame(leftType, rightType)) {
4560 sb.emitHelper(node, options, sb.helpers.equalsEqualsEquals({
4561 left: this.left,
4562 right: this.right
4563 }));
4564 } else if ((hasNull(leftType) || hasUndefined(leftType)) && (isOnlyUndefined(rightType) || isOnlyNull(rightType))) {
4565 // [left]
4566 sb.visit(this.left, options); // [right, left]
4567
4568 sb.visit(this.right, options); // [left]
4569
4570 sb.emitOp(this.right, 'DROP'); // [equals]
4571
4572 sb.emitHelper(node, options, sb.helpers.isNullOrUndefined);
4573 } else if (isOnlyNumber(leftType) && (isOnlyString(rightType) || isOnlyBoolean(rightType))) {
4574 // [left]
4575 sb.visit(this.left, options); // [right, left]
4576
4577 sb.visit(this.right, options); // [equals]
4578
4579 this.equalsEqualsLeftNumberRightBooleanOrString(sb, node, options);
4580 } else if (isOnlyBoolean(leftType) && (isOnlyString(rightType) || isOnlyBoolean(rightType))) {
4581 // [left]
4582 sb.visit(this.left, options); // [leftNumber]
4583
4584 sb.emitHelper(this.left, options, sb.helpers.toNumber({
4585 type: sb.getType(this.left)
4586 })); // [leftNumberVal]
4587
4588 sb.emitHelper(this.left, options, sb.helpers.createNumber); // [right, leftNumberVal]
4589
4590 sb.visit(this.right, options); // [equals]
4591
4592 this.equalsEqualsLeftNumberRightBooleanOrString(sb, node, options);
4593 } else if ((isOnlyString(leftType) || isOnlyBoolean(leftType)) && isOnlyNumber(rightType)) {
4594 // [left]
4595 sb.visit(this.left, options); // [right, left]
4596
4597 sb.visit(this.right, options); // [equals]
4598
4599 this.equalsEqualsRightNumberLeftBooleanOrString(sb, node, options);
4600 } else if ((isOnlyString(leftType) || isOnlyBoolean(leftType)) && isOnlyBoolean(rightType)) {
4601 // [left]
4602 sb.visit(this.left, options); // [right, left]
4603
4604 sb.visit(this.right, options); // [rightNumber, left]
4605
4606 sb.emitHelper(this.right, options, sb.helpers.toNumber({
4607 type: sb.getType(this.right)
4608 })); // [rightNumberVal, left]
4609
4610 sb.emitHelper(this.right, options, sb.helpers.createNumber); // [equals]
4611
4612 this.equalsEqualsRightNumberLeftBooleanOrString(sb, node, options);
4613 } else {
4614 this.equalsEqualsUnknown(sb, node, options);
4615 }
4616 }
4617
4618 equalsEqualsLeftNumberRightBooleanOrString(sb, node, options) {
4619 // [rightNumber, left]
4620 sb.emitHelper(this.right, options, sb.helpers.toNumber({
4621 type: sb.getType(this.right)
4622 })); // [rightNumber, left]
4623
4624 sb.emitHelper(this.right, options, sb.helpers.createNumber); // [equals]
4625
4626 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsNumber);
4627 }
4628
4629 equalsEqualsRightNumberLeftBooleanOrString(sb, node, options) {
4630 // [left, right]
4631 sb.emitOp(node, 'SWAP'); // [leftNumber, right]
4632
4633 sb.emitHelper(this.left, options, sb.helpers.toNumber({
4634 type: sb.getType(this.left)
4635 })); // [leftNumber, right]
4636
4637 sb.emitHelper(this.left, options, sb.helpers.createNumber); // [right, leftNumber]
4638
4639 sb.emitOp(node, 'SWAP'); // [equals]
4640
4641 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsNumber);
4642 }
4643
4644 equalsEqualsUnknown(sb, node, options) {
4645 const copy = () => {
4646 // [right, left, right]
4647 sb.emitOp(this.right, 'TUCK'); // [left, right, left, right]
4648
4649 sb.emitOp(this.right, 'OVER');
4650 }; // [left]
4651
4652
4653 sb.visit(this.left, options); // [right, left]
4654
4655 sb.visit(this.right, options);
4656 const cases = [{
4657 condition: () => {
4658 copy(); // [right, left]
4659
4660 sb.emitHelper(node, options, sb.helpers.isSameType);
4661 },
4662 whenTrue: () => {
4663 sb.emitHelper(node, options, sb.helpers.equalsEqualsEqualsSameType);
4664 }
4665 }, {
4666 condition: () => {
4667 copy(); // [rightIsNullOrUndefined, left, right, left]
4668
4669 sb.emitHelper(node, options, sb.helpers.isNullOrUndefined); // [left, rightIsNullOrUndefined, right, left]
4670
4671 sb.emitOp(node, 'SWAP'); // [leftIsNullOrUndefined, rightIsNullOrUndefined, right, left]
4672
4673 sb.emitHelper(node, options, sb.helpers.isNullOrUndefined); // [equals, right, left]
4674
4675 sb.emitOp(node, 'BOOLOR');
4676 },
4677 whenTrue: () => {
4678 // [left]
4679 sb.emitOp(node, 'DROP'); // []
4680
4681 sb.emitOp(node, 'DROP'); // [equals]
4682
4683 sb.emitPushBoolean(node, true);
4684 }
4685 }, {
4686 condition: () => {
4687 copy(); // [right, right, left, right, left]
4688
4689 sb.emitOp(node, 'DUP'); // [isString, right, left, right, left]
4690
4691 sb.emitHelper(this.right, options, sb.helpers.isString); // [right, isString, left, right, left]
4692
4693 sb.emitOp(node, 'SWAP'); // [isBoolean, isString, left, right, left]
4694
4695 sb.emitHelper(this.right, options, sb.helpers.isBoolean); // [isBooleanOrString, left, right, left]
4696
4697 sb.emitOp(node, 'BOOLOR'); // [left, isBooleanOrString, right, left]
4698
4699 sb.emitOp(node, 'SWAP'); // [left, left, isBooleanOrString, right, left]
4700
4701 sb.emitOp(node, 'DUP'); // [isNumber, left, isBooleanOrString, right, left]
4702
4703 sb.emitHelper(this.right, options, sb.helpers.isNumber); // [left, isNumber, isBooleanOrString, right, left]
4704
4705 sb.emitOp(node, 'SWAP'); // [isBoolean, isNumber, isBooleanOrString, right, left]
4706
4707 sb.emitHelper(this.right, options, sb.helpers.isBoolean); // [isBooleanOrNumber, isBooleanOrString, right, left]
4708
4709 sb.emitOp(node, 'BOOLOR'); // [is(BooleanOrNumber)And(BooleanOrString), right, left]
4710
4711 sb.emitOp(node, 'BOOLAND');
4712 },
4713 whenTrue: () => {
4714 // [left, right]
4715 sb.emitOp(node, 'SWAP'); // [leftNumber, right]
4716
4717 sb.emitHelper(node, options, sb.helpers.toNumber({
4718 type: sb.getType(this.left)
4719 })); // [leftNumber, right]
4720
4721 sb.emitHelper(node, options, sb.helpers.createNumber); // [right, leftNumber]
4722
4723 sb.emitOp(node, 'SWAP');
4724 this.equalsEqualsLeftNumberRightBooleanOrString(sb, node, options);
4725 }
4726 }, {
4727 condition: () => {
4728 copy(); // [left, right, right, left]
4729
4730 sb.emitOp(node, 'SWAP'); // [left, left, right, right, left]
4731
4732 sb.emitOp(node, 'DUP'); // [isString, left, right, right, left]
4733
4734 sb.emitHelper(this.right, options, sb.helpers.isString); // [left, isString, right, right, left]
4735
4736 sb.emitOp(node, 'SWAP'); // [isBoolean, isString, right, right, left]
4737
4738 sb.emitHelper(this.right, options, sb.helpers.isBoolean); // [isBooleanOrString, right, right, left]
4739
4740 sb.emitOp(node, 'BOOLOR'); // [right, isBooleanOrString, right, left]
4741
4742 sb.emitOp(node, 'SWAP'); // [right, right, isBooleanOrString, right, left]
4743
4744 sb.emitOp(node, 'DUP'); // [isNumber, right, isBooleanOrString, right, left]
4745
4746 sb.emitHelper(this.right, options, sb.helpers.isNumber); // [right, isNumber, isBooleanOrString, right, left]
4747
4748 sb.emitOp(node, 'SWAP'); // [isBoolean, isNumber, isBooleanOrString, right, left]
4749
4750 sb.emitHelper(this.right, options, sb.helpers.isBoolean); // [isBooleanOrNumber, isBooleanOrString, right, left]
4751
4752 sb.emitOp(node, 'BOOLOR'); // [is(BooleanOrNumber)And(BooleanOrString), right, left]
4753
4754 sb.emitOp(node, 'BOOLAND');
4755 },
4756 whenTrue: () => {
4757 // [rightNumber, left]
4758 sb.emitHelper(node, options, sb.helpers.toNumber({
4759 type: sb.getType(this.right)
4760 })); // [rightNumber, left]
4761
4762 sb.emitHelper(node, options, sb.helpers.createNumber);
4763 this.equalsEqualsRightNumberLeftBooleanOrString(sb, node, options);
4764 }
4765 }];
4766 sb.emitHelper(node, options, sb.helpers.case(cases, () => {
4767 // [rightPrim, left]
4768 sb.emitHelper(node, options, sb.helpers.toPrimitive({
4769 type: sb.getType(this.right)
4770 })); // [left, rightPrim]
4771
4772 sb.emitOp(node, 'SWAP'); // [leftPrim, rightPrim]
4773
4774 sb.emitHelper(node, options, sb.helpers.toPrimitive({
4775 type: sb.getType(this.left)
4776 })); // [rightPrim, leftPrim]
4777
4778 sb.emitOp(node, 'SWAP');
4779 sb.emitHelper(node, options, sb.helpers.case(cases, () => {
4780 // [leftPrim]
4781 sb.emitOp(node, 'DROP'); // []
4782
4783 sb.emitOp(node, 'DROP'); // [equals]
4784
4785 sb.emitPushBoolean(node, false);
4786 }));
4787 }));
4788 }
4789
4790}
4791
4792// Input: []
4793// Output: [boolean]
4794// TODO: Currently only supports numbers. Invalid to pass in a string.
4795class LessThanHelper extends Helper {
4796 constructor(options) {
4797 super();
4798 Object.defineProperty(this, "leftFirst", {
4799 configurable: true,
4800 enumerable: true,
4801 writable: true,
4802 value: void 0
4803 });
4804 Object.defineProperty(this, "left", {
4805 configurable: true,
4806 enumerable: true,
4807 writable: true,
4808 value: void 0
4809 });
4810 Object.defineProperty(this, "right", {
4811 configurable: true,
4812 enumerable: true,
4813 writable: true,
4814 value: void 0
4815 });
4816 this.leftFirst = options.leftFirst;
4817 this.left = options.left;
4818 this.right = options.right;
4819 }
4820
4821 emit(sb, node, options) {
4822 if (!options.pushValue) {
4823 if (this.leftFirst) {
4824 sb.visit(this.left, options);
4825 sb.visit(this.right, options);
4826 } else {
4827 sb.visit(this.right, options);
4828 sb.visit(this.left, options);
4829 }
4830
4831 return;
4832 }
4833
4834 if (this.leftFirst) {
4835 // [left]
4836 sb.visit(this.left, options); // [leftPrim]
4837
4838 sb.emitHelper(this.left, options, sb.helpers.toPrimitive({
4839 type: sb.getType(this.left),
4840 preferredType: 'number'
4841 })); // [right, leftPrim]
4842
4843 sb.visit(this.right, options); // [rightPrim, leftPrim]
4844
4845 sb.emitHelper(this.right, options, sb.helpers.toPrimitive({
4846 type: sb.getType(this.right),
4847 preferredType: 'number'
4848 }));
4849 } else {
4850 // [right]
4851 sb.visit(this.right, options); // [rightPrim]
4852
4853 sb.emitHelper(this.right, options, sb.helpers.toPrimitive({
4854 type: sb.getType(this.right),
4855 preferredType: 'number'
4856 })); // [left, rightPrim]
4857
4858 sb.visit(this.left, options); // [leftPrim, rightPrim]
4859
4860 sb.emitHelper(this.left, options, sb.helpers.toPrimitive({
4861 type: sb.getType(this.left),
4862 preferredType: 'number'
4863 })); // [rightPrim, leftPrim]
4864
4865 sb.emitOp(node, 'SWAP');
4866 }
4867
4868 if (isOnlyString(sb.getType(this.left)) && isOnlyString(sb.getType(this.right))) {
4869 sb.reportUnsupported(node);
4870 } else {
4871 // [rightNumber, leftPrim]
4872 sb.emitHelper(this.right, options, sb.helpers.toNumber({
4873 type: sb.getType(this.right)
4874 })); // [leftPrim, rightNumber]
4875
4876 sb.emitOp(node, 'SWAP'); // [leftNumber, rightNumber]
4877
4878 sb.emitHelper(this.left, options, sb.helpers.toNumber({
4879 type: sb.getType(this.left)
4880 })); // [rightNumber, leftNumber]
4881
4882 sb.emitOp(node, 'SWAP'); // [lt]
4883
4884 sb.emitOp(node, 'LT');
4885
4886 if (!options.pushValue) {
4887 sb.emitOp(node, 'DROP');
4888 }
4889 }
4890 }
4891
4892}
4893
4894const GLOBAL_PROPERTIES = new Set(['Array', 'Boolean', 'Buffer', 'Error', 'Number', 'Object', 'String', 'Symbol', 'process']);
4895
4896let InternalGlobalProperties;
4897
4898(function (InternalGlobalProperties) {
4899 InternalGlobalProperties["MODULES"] = "modules";
4900 InternalGlobalProperties["ARGUMENTS"] = "arguments";
4901})(InternalGlobalProperties || (InternalGlobalProperties = {}));
4902
4903// Output: []
4904
4905class AddArgumentsHelper extends Helper {
4906 emit(sb, node, optionsIn) {
4907 const options = sb.pushValueOptions(optionsIn); // ['arguments', argv, globalObjectVal]
4908
4909 sb.emitPushString(node, InternalGlobalProperties.ARGUMENTS); // [argv, 'arguments', globalObjectVal]
4910
4911 sb.emitOp(node, 'SWAP'); // []
4912
4913 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
4914 }
4915
4916}
4917
4918// Output: [objectPrototypeVal, globalObjectVal]
4919
4920class AddConstructorObjectHelper extends Helper {
4921 constructor(...args) {
4922 var _temp;
4923
4924 return _temp = super(...args), Object.defineProperty(this, "name", {
4925 configurable: true,
4926 enumerable: true,
4927 writable: true,
4928 value: void 0
4929 }), _temp;
4930 }
4931
4932 emit(sb, node, optionsIn) {
4933 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal, objectPrototypeVal]
4934
4935 sb.emitOp(node, 'SWAP'); // [globalObjectVal, objectPrototypeVal, globalObjectVal]
4936
4937 sb.emitOp(node, 'TUCK'); // [objectPrototypeVal, globalObjectVal, objectPrototypeVal, globalObjectVal]
4938
4939 sb.emitOp(node, 'OVER');
4940 /* create constructor prototype */
4941 // [prototypeVal, objectPrototypeVal, globalObjectVal]
4942
4943 sb.emitHelper(node, options, sb.helpers.createObject); // [prototypeVal, objectPrototypeVal, prototypeVal, globalObjectVal]
4944
4945 sb.emitOp(node, 'TUCK'); // ['prototype', prototypeVal, objectPrototypeVal, prototypeVal, globalObjectVal]
4946
4947 sb.emitPushString(node, 'prototype'); // [objectPrototypeVal, 'prototype', prototypeVal, prototypeVal, globalObjectVal]
4948
4949 sb.emitOp(node, 'ROT'); // [prototypeVal, globalObjectVal]
4950
4951 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [prototypeVal, globalObjectVal]
4952
4953 this.addPrototypeProperties(sb, node, options);
4954 /* create object */
4955 // [objectVal, prototypeVal, globalObjectVal]
4956
4957 sb.emitHelper(node, options, sb.helpers.createObject); // [objectVal, prototypeVal, objectVal, globalObjectVal]
4958
4959 sb.emitOp(node, 'TUCK'); // [prototypeVal, objectVal, prototypeVal, objectVal, globalObjectVal]
4960
4961 sb.emitOp(node, 'OVER'); // ['prototype', prototypeVal, objectVal, prototypeVal, objectVal, globalObjectVal]
4962
4963 sb.emitPushString(node, 'prototype'); // [prototypeVal, 'prototype', objectVal, prototypeVal, objectVal, globalObjectVal]
4964
4965 sb.emitOp(node, 'SWAP'); // [prototypeVal, objectVal, globalObjectVal]
4966
4967 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [objectVal, prototypeVal, objectVal, globalObjectVal]
4968
4969 sb.emitOp(node, 'OVER'); // ['constructor', objectVal, prototypeVal, objectVal, globalObjectVal]
4970
4971 sb.emitPushString(node, 'constructor'); // [objectVal, 'constructor', prototypeVal, objectVal, globalObjectVal]
4972
4973 sb.emitOp(node, 'SWAP'); // [objectVal, globalObjectVal]
4974
4975 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [objectVal, globalObjectVal]
4976
4977 this.addConstructorProperties(sb, node, options); // [name, objectVal, globalObjectVal]
4978
4979 sb.emitPushString(node, this.name); // [objectVal, name, globalObjectVal]
4980
4981 sb.emitOp(node, 'SWAP'); // [objectPrototypeVal, globalObjectVal]
4982
4983 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
4984 }
4985
4986 addPrototypeProperties(sb, node, options) {// do nothing
4987 }
4988
4989 addConstructorProperties(sb, node, options) {// do nothing
4990 }
4991
4992 addMethod(sb, node, options, name, body) {
4993 // [prototypeVal, prototypeVal, globalObjectVal]
4994 sb.emitOp(node, 'DUP'); // [name, prototypeVal, prototypeVal, globalObjectVal]
4995
4996 sb.emitPushString(node, name); // [farr, name, prototypeVal, prototypeVal, globalObjectVal]
4997
4998 sb.emitHelper(node, options, sb.helpers.createFunctionArray({
4999 body: () => {
5000 sb.withScope(node, options, body);
5001 sb.emitHelper(node, options, sb.helpers.createNormalCompletion);
5002 sb.emitOp(node, 'RET');
5003 }
5004 })); // [fobjectVal, name, prototypeVal, prototypeVal, globalObjectVal]
5005
5006 sb.emitHelper(node, options, sb.helpers.createFunctionObject({
5007 property: InternalFunctionProperties.CALL
5008 })); // [prototypeVal, globalObjectVal]
5009
5010 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
5011 }
5012
5013}
5014
5015// Input: [objectPrototypeVal, globalObjectVal]
5016// Output: [objectPrototypeVal, globalObjectVal]
5017class AddArrayObjectHelper extends AddConstructorObjectHelper {
5018 constructor(...args) {
5019 var _temp;
5020
5021 return _temp = super(...args), Object.defineProperty(this, "name", {
5022 configurable: true,
5023 enumerable: true,
5024 writable: true,
5025 value: 'Array'
5026 }), _temp;
5027 }
5028
5029 addPrototypeProperties(sb, node, options) {
5030 this.addMap(sb, node, options);
5031 this.addFilter(sb, node, options);
5032 this.addReduce(sb, node, options);
5033 }
5034
5035 addConstructorProperties(sb, node, options) {
5036 // [objectVal, objectVal, globalObjectVal]
5037 sb.emitOp(node, 'DUP'); // ['construct', objectVal, objectVal, globalObjectVal]
5038
5039 sb.emitPushString(node, InternalFunctionProperties.CONSTRUCT); // [func, 'construct', objectVal, objectVal, globalObjectVal]
5040
5041 sb.emitHelper(node, options, sb.helpers.createConstructArray({
5042 withoutScope: true,
5043 body: () => {
5044 // [argsarray, argsarray]
5045 sb.emitOp(node, 'DUP'); // [size, argsarray]
5046
5047 sb.emitOp(node, 'ARRAYSIZE');
5048 sb.emitHelper(node, options, sb.helpers.case([{
5049 condition: () => {
5050 // [size, size, argsarray]
5051 sb.emitOp(node, 'DUP'); // [0, size, size, argsarray]
5052
5053 sb.emitPushInt(node, 0); // [size === 0, size, argsarray]
5054
5055 sb.emitOp(node, 'EQUAL');
5056 },
5057 whenTrue: () => {
5058 // [argsarray]
5059 sb.emitOp(node, 'DROP'); // []
5060
5061 sb.emitOp(node, 'DROP'); // [length]
5062
5063 sb.emitPushInt(node, 0); // [0, length]
5064
5065 sb.emitPushInt(node, 0); // [array, length]
5066
5067 sb.emitOp(node, 'NEWARRAY');
5068 }
5069 }, {
5070 condition: () => {
5071 // [size, size, argsarray]
5072 sb.emitOp(node, 'DUP'); // [1, size, size, argsarray]
5073
5074 sb.emitPushInt(node, 1); // [size === 1, size, argsarray]
5075
5076 sb.emitOp(node, 'EQUAL');
5077 },
5078 whenTrue: () => {
5079 // [argsarray]
5080 sb.emitOp(node, 'DROP'); // [0, argsarray]
5081
5082 sb.emitPushInt(node, 0); // [lengthVal]
5083
5084 sb.emitOp(node, 'PICKITEM'); // [length]
5085
5086 sb.emitHelper(node, options, sb.helpers.getNumber); // [length, length]
5087
5088 sb.emitOp(node, 'DUP'); // [0, length, length]
5089
5090 sb.emitPushInt(node, 0); // [arr, length, length]
5091
5092 sb.emitOp(node, 'NEWARRAY'); // [arr, length, arr, length]
5093
5094 sb.emitOp(node, 'TUCK'); // [length, arr, arr, length]
5095
5096 sb.emitOp(node, 'SWAP'); // [array, length]
5097
5098 sb.emitHelper(node, options, sb.helpers.extendArray);
5099 }
5100 }], () => {
5101 // [array, length]
5102 sb.emitOp(node, 'SWAP');
5103 })); // [objectVal, arr, length]
5104
5105 sb.scope.getThis(sb, node, options); // [objectVal, objectVal, arr, length]
5106
5107 sb.emitOp(node, 'DUP'); // [arr, objectVal, objectVal, length]
5108
5109 sb.emitOp(node, 'ROT'); // [objectVal, length]
5110
5111 sb.emitHelper(node, options, sb.helpers.setArrayValue); // ['length', objectVal, length]
5112
5113 sb.emitPushString(node, 'length'); // [length, 'length', objectVal]
5114
5115 sb.emitOp(node, 'ROT'); // [lengthVal, 'length', objectVal]
5116
5117 sb.emitHelper(node, options, sb.helpers.createNumber); // []
5118
5119 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
5120 }
5121 })); // [objectVal, globalObjectVal]
5122
5123 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
5124 }
5125
5126 addMap(sb, node, options) {
5127 this.addMapLike(sb, node, options, 'map', sb.helpers.arrMap);
5128 }
5129
5130 addFilter(sb, node, options) {
5131 this.addMapLike(sb, node, options, 'filter', sb.helpers.arrFilter);
5132 }
5133
5134 addReduce(sb, node, outerOptions) {
5135 this.addMethod(sb, node, outerOptions, 'reduce', options => {
5136 const func = sb.scope.addUnique();
5137 const accum = sb.scope.addUnique(); // [argsarr, argsarr]
5138
5139 sb.emitOp(node, 'DUP'); // [0, argsarr, argsarr]
5140
5141 sb.emitPushInt(node, 0); // [fObjectVal, argsarr]
5142
5143 sb.emitOp(node, 'PICKITEM'); // [argsarr]
5144
5145 sb.scope.set(sb, node, options, func); // [argsarr, argsarr]
5146
5147 sb.emitOp(node, 'DUP'); // [size, argsarr]
5148
5149 sb.emitOp(node, 'ARRAYSIZE'); // [val]
5150
5151 sb.emitHelper(node, options, sb.helpers.if({
5152 condition: () => {
5153 // [2, size, argsarr]
5154 sb.emitPushInt(node, 2); // [size === 2, argsarr]
5155
5156 sb.emitOp(node, 'NUMEQUAL');
5157 },
5158 whenTrue: () => {
5159 // [1, argsarr]
5160 sb.emitPushInt(node, 1); // [val]
5161
5162 sb.emitOp(node, 'PICKITEM');
5163 },
5164 whenFalse: () => {
5165 // []
5166 sb.emitOp(node, 'DROP'); // [val]
5167
5168 sb.emitHelper(node, options, sb.helpers.createUndefined);
5169 }
5170 })); // []
5171
5172 sb.scope.set(sb, node, options, accum); // [arrayObjectVal]
5173
5174 sb.scope.getThis(sb, node, options); // [arr]
5175
5176 sb.emitHelper(node, options, sb.helpers.unwrapArray); // [arr]
5177
5178 sb.emitHelper(node, options, sb.helpers.arrForEach({
5179 each: () => {
5180 // [accum, val, index]
5181 sb.scope.get(sb, node, options, accum); // [index, accum, val]
5182
5183 sb.emitOp(node, 'ROT'); // [indexVal, accum, val]
5184
5185 sb.emitHelper(node, options, sb.helpers.createNumber); // [accum, indexVal, val]
5186
5187 sb.emitOp(node, 'SWAP'); // [val, accum, indexVal]
5188
5189 sb.emitOp(node, 'ROT'); // [3, val, accum, indexVal]
5190
5191 sb.emitPushInt(node, 3); // [argsarr]
5192
5193 sb.emitOp(node, 'PACK'); // [fObjectVal, argsarr]
5194
5195 sb.scope.get(sb, node, options, func); // [val]
5196
5197 sb.emitHelper(node, options, sb.helpers.invokeCall()); // []
5198
5199 sb.scope.set(sb, node, options, accum);
5200 },
5201 withIndex: true
5202 })); // [val]
5203
5204 sb.scope.get(sb, node, options, accum);
5205 });
5206 }
5207
5208 addMapLike(sb, node, outerOptions, name, helper) {
5209 this.addMethod(sb, node, outerOptions, name, options => {
5210 const func = sb.scope.addUnique(); // [0, argsarr]
5211
5212 sb.emitPushInt(node, 0); // [fObjectVal]
5213
5214 sb.emitOp(node, 'PICKITEM'); // []
5215
5216 sb.scope.set(sb, node, options, func); // [arrayObjectVal]
5217
5218 sb.scope.getThis(sb, node, options); // [arr]
5219
5220 sb.emitHelper(node, options, sb.helpers.unwrapArray); // [arr]
5221
5222 sb.emitHelper(node, options, helper({
5223 map: () => {
5224 // [index, val]
5225 sb.emitOp(node, 'SWAP'); // [indexVal, val]
5226
5227 sb.emitHelper(node, options, sb.helpers.createNumber); // [val, indexVal]
5228
5229 sb.emitOp(node, 'SWAP'); // [2, val, indexVal]
5230
5231 sb.emitPushInt(node, 2); // [argsarr]
5232
5233 sb.emitOp(node, 'PACK'); // [fObjectVal, argsarr]
5234
5235 sb.scope.get(sb, node, options, func); // [val]
5236
5237 sb.emitHelper(node, options, sb.helpers.invokeCall());
5238 },
5239 withIndex: true
5240 })); // [arrayObjectVal]
5241
5242 sb.emitHelper(node, options, sb.helpers.wrapArray);
5243 });
5244 }
5245
5246}
5247
5248// Output: [objectPrototypeVal, globalObjectVal]
5249
5250class AddBufferObjectHelper extends AddConstructorObjectHelper {
5251 constructor(...args) {
5252 var _temp;
5253
5254 return _temp = super(...args), Object.defineProperty(this, "name", {
5255 configurable: true,
5256 enumerable: true,
5257 writable: true,
5258 value: 'Buffer'
5259 }), _temp;
5260 }
5261
5262 addConstructorProperties(sb, node, options) {
5263 this.addConstructor(sb, node, options);
5264 this.addConcat(sb, node, options);
5265 }
5266
5267 addConstructor(sb, node, options) {
5268 // [objectVal, objectVal, globalObjectVal]
5269 sb.emitOp(node, 'DUP'); // ['construct', objectVal, objectVal, globalObjectVal]
5270
5271 sb.emitPushString(node, InternalFunctionProperties.CONSTRUCT); // [func, 'construct', objectVal, objectVal, globalObjectVal]
5272
5273 sb.emitHelper(node, options, sb.helpers.createConstructArray({
5274 withoutScope: true,
5275 body: () => {
5276 // Drop the args array
5277 // []
5278 sb.emitOp(node, 'DROP');
5279 }
5280 })); // [objectVal, globalObjectVal]
5281
5282 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
5283 }
5284
5285 addConcat(sb, node, outerOptions) {
5286 this.addMethod(sb, node, outerOptions, 'concat', options => {
5287 // [0, argsarr]
5288 sb.emitPushInt(node, 0); // [arrayObjectVal]
5289
5290 sb.emitOp(node, 'PICKITEM'); // [array]
5291
5292 sb.emitHelper(node, options, sb.helpers.unwrapArray); // [buffer, array]
5293
5294 sb.emitOp(node, 'PUSH0');
5295 sb.emitHelper(node, options, sb.helpers.forLoop({
5296 condition: () => {
5297 // [array, buffer, array]
5298 sb.emitOp(node, 'OVER'); // [size, buffer, array]
5299
5300 sb.emitOp(node, 'ARRAYSIZE'); // [0, size, buffer, array]
5301
5302 sb.emitPushInt(node, 0); // [size > 0, buffer, array]
5303
5304 sb.emitOp(node, 'GT');
5305 },
5306 each: () => {
5307 // [array, buffer, array]
5308 sb.emitOp(node, 'OVER'); // [0, array, buffer, array]
5309
5310 sb.emitPushInt(node, 0); // [rightBufferVal, buffer, array]
5311
5312 sb.emitOp(node, 'PICKITEM'); // [rightBuffer, buffer, array]
5313
5314 sb.emitHelper(node, options, sb.helpers.unwrapBuffer); // [buffer + rightBuffer, array]
5315
5316 sb.emitOp(node, 'CAT'); // [array, buffer, array]
5317
5318 sb.emitOp(node, 'OVER'); // [0, array, buffer, array]
5319
5320 sb.emitPushInt(node, 0); // [buffer, array]
5321
5322 sb.emitOp(node, 'REMOVE');
5323 }
5324 })); // [buffer]
5325
5326 sb.emitOp(node, 'NIP'); // [bufferVal]
5327
5328 sb.emitHelper(node, options, sb.helpers.wrapBuffer);
5329 });
5330 }
5331
5332}
5333
5334// Output: [objectPrototypeVal, globalObjectVal]
5335
5336class AddBooleanObjectHelper extends AddConstructorObjectHelper {
5337 constructor(...args) {
5338 var _temp;
5339
5340 return _temp = super(...args), Object.defineProperty(this, "name", {
5341 configurable: true,
5342 enumerable: true,
5343 writable: true,
5344 value: 'Boolean'
5345 }), _temp;
5346 }
5347
5348}
5349
5350// Output: [objectPrototypeVal, globalObjectVal]
5351
5352class AddErrorObjectHelper extends AddConstructorObjectHelper {
5353 constructor(...args) {
5354 var _temp;
5355
5356 return _temp = super(...args), Object.defineProperty(this, "name", {
5357 configurable: true,
5358 enumerable: true,
5359 writable: true,
5360 value: 'Error'
5361 }), _temp;
5362 }
5363
5364 addConstructorProperties(sb, node, options) {
5365 // [objectVal, objectVal, globalObjectVal]
5366 sb.emitOp(node, 'DUP'); // ['construct', objectVal, objectVal, globalObjectVal]
5367
5368 sb.emitPushString(node, InternalFunctionProperties.CONSTRUCT); // [func, 'construct', objectVal, objectVal, globalObjectVal]
5369
5370 sb.emitHelper(node, options, sb.helpers.createConstructArray({
5371 withoutScope: true,
5372 body: () => {
5373 // Drop the args array
5374 // []
5375 sb.emitOp(node, 'DROP');
5376 }
5377 })); // [objectVal, globalObjectVal]
5378
5379 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
5380 }
5381
5382}
5383
5384// Output: [objectPrototypeVal, globalObjectVal]
5385
5386class AddModulesHelper extends Helper {
5387 emit(sb, node, optionsIn) {
5388 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal, objectPrototypeVal, globalObjectVal]
5389
5390 sb.emitOp(node, 'OVER'); // ['modules', globalObjectVal, objectPrototypeVal, globalObjectVal]
5391
5392 sb.emitPushString(node, InternalGlobalProperties.MODULES); // [0, 'modules', globalObjectVal, objectPrototypeVal, globalObjectVal]
5393
5394 sb.emitPushInt(node, 0); // [arr, 'modules', globalObjectVal, objectPrototypeVal, globalObjectVal]
5395
5396 sb.emitOp(node, 'NEWARRAY'); // [objectPrototypeVal, globalObjectVal]]
5397
5398 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
5399 }
5400
5401}
5402
5403// Output: [objectPrototypeVal, globalObjectVal]
5404
5405class AddNumberObjectHelper extends AddConstructorObjectHelper {
5406 constructor(...args) {
5407 var _temp;
5408
5409 return _temp = super(...args), Object.defineProperty(this, "name", {
5410 configurable: true,
5411 enumerable: true,
5412 writable: true,
5413 value: 'Number'
5414 }), _temp;
5415 }
5416
5417}
5418
5419// Input: [globalObjectVal]
5420// Output: [objectPrototypeVal, globalObjectVal]
5421class AddObjectObjectHelper extends Helper {
5422 emit(sb, node, optionsIn) {
5423 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal, globalObjectVal]
5424
5425 sb.emitOp(node, 'DUP');
5426 /* create object prototype */
5427 // TODO: Implement more of the prototype
5428 // [objectPrototypeVal, globalObjectVal, globalObjectVal]
5429
5430 sb.emitHelper(node, options, sb.helpers.createObject); // [objectPrototypeVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5431
5432 sb.emitOp(node, 'DUP');
5433 /* create object */
5434 // [objectVal, objectPrototypeVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5435
5436 sb.emitHelper(node, options, sb.helpers.createObject); // [objectVal, objectPrototypeVal, objectVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5437
5438 sb.emitOp(node, 'TUCK'); // ['prototype', objectVal, objectPrototypeVal, objectVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5439
5440 sb.emitPushString(node, 'prototype'); // [objectPrototypeVal, 'prototype', objectVal, objectVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5441
5442 sb.emitOp(node, 'ROT'); // [objectVal, objectPrototypeVal, globalObjectVal, globalObjectVal]
5443
5444 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [objectVal, objectPrototypeVal, objectVal, globalObjectVal, globalObjectVal]
5445
5446 sb.emitOp(node, 'TUCK'); // [objectPrototypeVal, objectVal, objectPrototypeVal, objectVal, globalObjectVal, globalObjectVal]
5447
5448 sb.emitOp(node, 'OVER'); // ['constructor', objectPrototypeVal, objectVal, objectPrototypeVal, objectVal, globalObjectVal, globalObjectVal]
5449
5450 sb.emitPushString(node, 'constructor'); // [objectVal, 'constructor', objectPrototypeVal, objectPrototypeVal, objectVal, globalObjectVal, globalObjectVal]
5451
5452 sb.emitOp(node, 'ROT'); // [objectPrototypeVal, objectVal, globalObjectVal, globalObjectVal]
5453
5454 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [globalObjectVal, objectPrototypeVal, objectVal, globalObjectVal]
5455
5456 sb.emitOp(node, 'ROT'); // ['Object', globalObjectVal, objectPrototypeVal, objectVal, globalObjectVal]
5457
5458 sb.emitPushString(node, 'Object'); // ['Object', globalObjectVal, objectPrototypeVal, objectVal, globalObjectVal]
5459
5460 sb.emitPushInt(node, 3); // [objectVal, 'Object', globalObjectVal, objectPrototypeVal, globalObjectVal]
5461
5462 sb.emitOp(node, 'ROLL'); // [objectPrototypeVal, globalObjectVal]
5463
5464 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty);
5465 }
5466
5467}
5468
5469// Output: [objectPrototypeVal, globalObjectVal]
5470
5471class AddStringObjectHelper extends AddConstructorObjectHelper {
5472 constructor(...args) {
5473 var _temp;
5474
5475 return _temp = super(...args), Object.defineProperty(this, "name", {
5476 configurable: true,
5477 enumerable: true,
5478 writable: true,
5479 value: 'String'
5480 }), _temp;
5481 }
5482
5483}
5484
5485// Output: [objectPrototypeVal, globalObjectVal]
5486
5487class AddSymbolObjectHelper extends AddConstructorObjectHelper {
5488 constructor(...args) {
5489 var _temp;
5490
5491 return _temp = super(...args), Object.defineProperty(this, "name", {
5492 configurable: true,
5493 enumerable: true,
5494 writable: true,
5495 value: 'Symbol'
5496 }), _temp;
5497 }
5498
5499}
5500
5501// Input: []
5502// Output: [globalObjectVal]
5503class SetGlobalObjectHelper extends Helper {
5504 emit(sb, node, optionsIn) {
5505 const options = sb.pushValueOptions(optionsIn); // [length, ...args]
5506
5507 sb.emitOp(node, 'DEPTH'); // [argv]
5508
5509 sb.emitOp(node, 'PACK'); // [globalObjectVal, argv]
5510
5511 sb.emitHelper(node, options, sb.helpers.createObject); // [globalObjectVal, globalObjectVal, argv]
5512
5513 sb.emitOp(node, 'DUP'); // [globalObjectVal, argv]
5514
5515 sb.scope.setGlobal(sb, node, options); // [globalObjectVal, argv, globalObjectVal]
5516
5517 sb.emitOp(node, 'TUCK'); // [argv, globalObjectVal, globalObjectVal]
5518
5519 sb.emitOp(node, 'SWAP'); // [globalObjectVal]
5520
5521 sb.emitHelper(node, options, sb.helpers.addArguments); // [objectPrototypeVal, globalObjectVal]
5522
5523 sb.emitHelper(node, options, sb.helpers.addObjectObject); // [objectPrototypeVal, globalObjectVal]
5524
5525 sb.emitHelper(node, options, sb.helpers.addBooleanObject); // [objectPrototypeVal, globalObjectVal]
5526
5527 sb.emitHelper(node, options, sb.helpers.addNumberObject); // [objectPrototypeVal, globalObjectVal]
5528
5529 sb.emitHelper(node, options, sb.helpers.addStringObject); // [objectPrototypeVal, globalObjectVal]
5530
5531 sb.emitHelper(node, options, sb.helpers.addSymbolObject); // [objectPrototypeVal, globalObjectVal]
5532
5533 sb.emitHelper(node, options, sb.helpers.addArrayObject); // [objectPrototypeVal, globalObjectVal]
5534
5535 sb.emitHelper(node, options, sb.helpers.addBufferObject); // [objectPrototypeVal, globalObjectVal]
5536
5537 sb.emitHelper(node, options, sb.helpers.addErrorObject); // [objectPrototypeVal, globalObjectVal]
5538
5539 sb.emitHelper(node, options, sb.helpers.addModules); // [globalObjectVal]
5540
5541 sb.emitOp(node, 'DROP');
5542
5543 if (!optionsIn.pushValue) {
5544 sb.emitOp(node, 'DROP');
5545 }
5546 }
5547
5548}
5549
5550// Output: [value]
5551
5552class GetArgumentHelper extends TypedHelper {
5553 emit(sb, node, options) {
5554 if (!options.pushValue) {
5555 sb.emitOp(node, 'DROP');
5556 return;
5557 } // [globalObjectVal, numberVal]
5558
5559
5560 sb.scope.getGlobal(sb, node, options); // [arguments, globalObjectVal, numberVal]
5561
5562 sb.emitPushString(node, InternalGlobalProperties.ARGUMENTS); // [argv, numberVal]
5563
5564 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty); // [numberVal, argv]
5565
5566 sb.emitOp(node, 'SWAP'); // TODO: This should really be toNumber
5567 // [number, argv]
5568
5569 sb.emitHelper(node, options, sb.helpers.toNumber({
5570 type: this.type
5571 })); // [value]
5572
5573 sb.emitOp(node, 'PICKITEM');
5574 }
5575
5576}
5577
5578// Input: []
5579// Output: [val]
5580class GetGlobalPropertyHelper extends Helper {
5581 constructor(options) {
5582 super();
5583 Object.defineProperty(this, "property", {
5584 configurable: true,
5585 enumerable: true,
5586 writable: true,
5587 value: void 0
5588 });
5589 this.property = options.property;
5590 }
5591
5592 emit(sb, node, optionsIn) {
5593 const options = sb.pushValueOptions(optionsIn); // [globalObjectVal]
5594
5595 sb.scope.getGlobal(sb, node, options); // [propertyString, globalObjectVal]
5596
5597 sb.emitPushString(node, this.property); // [val]
5598
5599 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty);
5600
5601 if (!optionsIn.pushValue) {
5602 sb.emitOp(node, 'DROP');
5603 }
5604 }
5605
5606}
5607
5608// Input: []
5609// Output: [objectVal]
5610class CreateArrayHelper extends Helper {
5611 emit(sb, node, options) {
5612 if (options.pushValue) {
5613 // [Array]
5614 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
5615 property: 'Array'
5616 })); // [objectVal]
5617
5618 sb.emitHelper(node, options, sb.helpers.new({
5619 noArgs: true
5620 }));
5621 }
5622 }
5623
5624}
5625
5626// Input: [indexNumber, objectVal]
5627// Output: [val]
5628class GetArrayIndexHelper extends Helper {
5629 emit(sb, node, optionsIn) {
5630 const options = sb.pushValueOptions(optionsIn);
5631 sb.emitHelper(node, options, sb.helpers.if({
5632 condition: () => {
5633 // [objectVal, indexNumber, objectVal]
5634 sb.emitOp(node, 'OVER'); // ['length', objectVal, indexNumber, objectVal]
5635
5636 sb.emitPushString(node, 'length'); // [lengthNumberVal, indexNumber, objectVal]
5637
5638 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [lengthNumber, indexNumber, objectVal]
5639
5640 sb.emitHelper(node, options, sb.helpers.getNumber); // [indexNumber, lengthNumber, indexNumber, objectVal]
5641
5642 sb.emitOp(node, 'OVER'); // [lessThanLength, indexNumber, objectVal]
5643
5644 sb.emitOp(node, 'GT');
5645 },
5646 whenTrue: () => {
5647 // [objectVal, indexNumber]
5648 sb.emitOp(node, 'SWAP'); // [arr, indexNumber]
5649
5650 sb.emitHelper(node, options, sb.helpers.getArrayValue); // [indexNumber, arr]
5651
5652 sb.emitOp(node, 'SWAP'); // []
5653
5654 sb.emitOp(node, 'PICKITEM');
5655 },
5656 whenFalse: () => {
5657 // [indexNumber]
5658 sb.emitOp(node, 'DROP'); // []
5659
5660 sb.emitOp(node, 'DROP'); // [val]
5661
5662 sb.emitHelper(node, options, sb.helpers.createUndefined);
5663 }
5664 }));
5665 }
5666
5667}
5668
5669let InternalArrayProperties;
5670
5671(function (InternalArrayProperties) {
5672 InternalArrayProperties["DATA_ARRAY"] = "DataArray";
5673})(InternalArrayProperties || (InternalArrayProperties = {}));
5674
5675// Output: [arr]
5676
5677class GetArrayValueHelper extends Helper {
5678 emit(sb, node, options) {
5679 if (!options.pushValue) {
5680 sb.emitOp(node, 'DROP');
5681 return;
5682 } // ['DataArray', objectVal]
5683
5684
5685 sb.emitPushString(node, InternalArrayProperties.DATA_ARRAY); // [arr]
5686
5687 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty);
5688 }
5689
5690}
5691
5692// Input: [val, indexNumber, objectVal]
5693// Output: []
5694class SetArrayIndexHelper extends Helper {
5695 emit(sb, node, optionsIn) {
5696 const options = sb.pushValueOptions(optionsIn);
5697 sb.emitHelper(node, options, sb.helpers.if({
5698 condition: () => {
5699 // [objectVal, val, indexNumber]
5700 sb.emitOp(node, 'ROT'); // [indexNumber, objectVal, val]
5701
5702 sb.emitOp(node, 'ROT'); // [objectVal, indexNumber, objectVal, val]
5703
5704 sb.emitOp(node, 'OVER'); // ['length', objectVal, indexNumber, objectVal, val]
5705
5706 sb.emitPushString(node, 'length'); // [lengthNumberVal, indexNumber, objectVal, val]
5707
5708 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [lengthNumber, indexNumber, objectVal, val]
5709
5710 sb.emitHelper(node, options, sb.helpers.getNumber); // [indexNumber, lengthNumber, indexNumber, objectVal, val]
5711
5712 sb.emitOp(node, 'OVER'); // [lessThanLength, indexNumber, objectVal, val]
5713
5714 sb.emitOp(node, 'GT');
5715 },
5716 whenTrue: () => {
5717 // [objectVal, indexNumber, val]
5718 sb.emitOp(node, 'SWAP'); // []
5719
5720 this.setIndex(sb, node, options);
5721 },
5722 whenFalse: () => {
5723 // [objectVal, indexNumber, objectVal, val]
5724 sb.emitOp(node, 'OVER'); // [arr, indexNumber, objectVal, val]
5725
5726 sb.emitHelper(node, options, sb.helpers.getArrayValue); // [indexNumber, arr, indexNumber, objectVal, val]
5727
5728 sb.emitOp(node, 'OVER'); // [indexNumber + 1, arr, indexNumber, objectVal, val]
5729
5730 sb.emitOp(node, 'INC'); // [length, arr, length, indexNumber, objectVal, val]
5731
5732 sb.emitOp(node, 'TUCK'); // [length, indexNumber, objectVal, val]
5733
5734 sb.emitHelper(node, options, sb.helpers.extendArray); // [objectVal, length, indexNumber, val]
5735
5736 sb.emitOp(node, 'ROT'); // [objectVal, length, objectVal, indexNumber, val]
5737
5738 sb.emitOp(node, 'TUCK'); // ['length', objectVal, length, objectVal, indexNumber, val]
5739
5740 sb.emitPushString(node, 'length'); // [length, 'length', objectVal, objectVal, indexNumber, val]
5741
5742 sb.emitOp(node, 'ROT'); // [lengthVal, 'length', objectVal, objectVal, indexNumber, val]
5743
5744 sb.emitHelper(node, options, sb.helpers.createNumber); // [objectVal, indexNumber, val]
5745
5746 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // []
5747
5748 this.setIndex(sb, node, options);
5749 }
5750 }));
5751 }
5752
5753 setIndex(sb, node, options) {
5754 // [arr, indexNumber, val]
5755 sb.emitHelper(node, options, sb.helpers.getArrayValue); // [indexNumber, arr, val]
5756
5757 sb.emitOp(node, 'SWAP'); // [val, indexNumber, arr]
5758
5759 sb.emitOp(node, 'ROT'); // []
5760
5761 sb.emitOp(node, 'SETITEM');
5762 }
5763
5764}
5765
5766// Output: []
5767
5768class SetArrayValueHelper extends Helper {
5769 emit(sb, node, optionsIn) {
5770 const options = sb.pushValueOptions(optionsIn); // ['DataArray', arr, objectVal]
5771
5772 sb.emitPushString(node, InternalArrayProperties.DATA_ARRAY); // [arr, 'DataArray', objectVal]
5773
5774 sb.emitOp(node, 'SWAP'); // []
5775
5776 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
5777 }
5778
5779}
5780
5781// Input: [objectVal]
5782// Output: [arr]
5783class UnwrapArrayHelper extends Helper {
5784 emit(sb, node, optionsIn) {
5785 if (!optionsIn.pushValue) {
5786 sb.emitOp(node, 'DROP');
5787 return;
5788 }
5789
5790 const options = sb.pushValueOptions(optionsIn); // [arr]
5791
5792 sb.emitHelper(node, options, sb.helpers.getArrayValue);
5793 }
5794
5795}
5796
5797// Input: [arr]
5798// Output: [objectVal]
5799class WrapArrayHelper extends Helper {
5800 emit(sb, node, options) {
5801 if (!options.pushValue) {
5802 sb.emitOp(node, 'DROP');
5803 return;
5804 }
5805
5806 const invokeArrayConstruct = () => {
5807 // [Array, argsarr]
5808 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
5809 property: 'Array'
5810 })); // [objectVal]
5811
5812 sb.emitHelper(node, options, sb.helpers.new());
5813 };
5814
5815 sb.emitHelper(node, options, sb.helpers.if({
5816 condition: () => {
5817 // [arr, arr]
5818 sb.emitOp(node, 'DUP'); // [size, arr]
5819
5820 sb.emitOp(node, 'ARRAYSIZE'); // [1, size, arr]
5821
5822 sb.emitPushInt(node, 1); // [size === 1, arr]
5823
5824 sb.emitOp(node, 'EQUAL');
5825 },
5826 whenTrue: () => {
5827 // [0, arr]
5828 sb.emitPushInt(node, 0); // [val]
5829
5830 sb.emitOp(node, 'PICKITEM'); // [1, val]
5831
5832 sb.emitPushInt(node, 1); // [lengthVal, val]
5833
5834 sb.emitHelper(node, options, sb.helpers.createNumber); // [1, lengthVal, val]
5835
5836 sb.emitPushInt(node, 1); // [argsarr, val]
5837
5838 sb.emitOp(node, 'PACK'); // [arrayObjectVal, val]
5839
5840 invokeArrayConstruct(); // [arrayObjectVal, val, arrayObjectVal]
5841
5842 sb.emitOp(node, 'TUCK'); // [0, arrayObjectVal, val, arrayObjectVal]
5843
5844 sb.emitPushInt(node, 0); // [val, 0, arrayObjectVal, arrayObjectVal]
5845
5846 sb.emitOp(node, 'ROT'); // [arrayObjectVal]
5847
5848 sb.emitHelper(node, options, sb.helpers.setArrayIndex);
5849 },
5850 whenFalse: () => {
5851 // [arrayObjectVal]
5852 invokeArrayConstruct();
5853 }
5854 }));
5855 }
5856
5857}
5858
5859// Input: [globalObjectVal]
5860// Output: []
5861class AddEmptyModuleHelper extends Helper {
5862 emit(sb, node, optionsIn) {
5863 const options = sb.pushValueOptions(optionsIn); // [modules]
5864
5865 sb.emitHelper(node, options, sb.helpers.getModules); // [exports, modules]
5866
5867 sb.emitOp(node, 'NEWMAP'); // []
5868
5869 sb.emitOp(node, 'APPEND');
5870 }
5871
5872}
5873
5874// Input: [val, exports]
5875// Output: []
5876class ExportHelper extends Helper {
5877 constructor({
5878 name,
5879 defaultExport
5880 }) {
5881 super();
5882 Object.defineProperty(this, "name", {
5883 configurable: true,
5884 enumerable: true,
5885 writable: true,
5886 value: void 0
5887 });
5888 Object.defineProperty(this, "defaultExport", {
5889 configurable: true,
5890 enumerable: true,
5891 writable: true,
5892 value: void 0
5893 });
5894 this.name = name;
5895 this.defaultExport = defaultExport || false;
5896 }
5897
5898 emit(sb, node, optionsIn) {
5899 if (this.name != null) {
5900 sb.addExport(this.name); // [name, val, exports]
5901
5902 sb.emitPushString(node, this.name);
5903 } else if (this.defaultExport) {
5904 // [name, val, exports]
5905 sb.emitPushString(node, 'default');
5906 } else {
5907 sb.reportUnsupported(node);
5908 } // [val, name, exports]
5909
5910
5911 sb.emitOp(node, 'SWAP'); // []
5912
5913 sb.emitOp(node, 'SETITEM');
5914 }
5915
5916}
5917
5918// Input: [val]
5919// Output: []
5920class ExportSingleHelper extends Helper {
5921 constructor(options) {
5922 super();
5923 Object.defineProperty(this, "options", {
5924 configurable: true,
5925 enumerable: true,
5926 writable: true,
5927 value: void 0
5928 });
5929 this.options = options;
5930 }
5931
5932 emit(sb, node, optionsIn) {
5933 const options = sb.pushValueOptions(optionsIn); // [exports, val]
5934
5935 sb.emitHelper(node, options, sb.helpers.getCurrentModule); // [val, exports]
5936
5937 sb.emitOp(node, 'SWAP'); // []
5938
5939 sb.emitHelper(node, options, sb.helpers.export(this.options));
5940 }
5941
5942}
5943
5944// Input: []
5945// Output: [exports]
5946class GetCurrentModuleHelper extends Helper {
5947 emit(sb, node, options) {
5948 if (options.pushValue) {
5949 // [globalObjectVal]
5950 sb.scope.getGlobal(sb, node, options); // [exports]
5951
5952 sb.emitHelper(node, options, sb.helpers.getModule({
5953 moduleIndex: sb.moduleIndex
5954 }));
5955 }
5956 }
5957
5958}
5959
5960// Input: [globalObjectVal]
5961// Output: [exports]
5962class GetModuleHelper extends Helper {
5963 constructor(options) {
5964 super();
5965 Object.defineProperty(this, "moduleIndex", {
5966 configurable: true,
5967 enumerable: true,
5968 writable: true,
5969 value: void 0
5970 });
5971 this.moduleIndex = options.moduleIndex;
5972 }
5973
5974 emit(sb, node, options) {
5975 if (options.pushValue) {
5976 // [modules, index]
5977 sb.emitHelper(node, options, sb.helpers.getModules); // [index, modules]
5978
5979 sb.emitPushInt(node, this.moduleIndex); // [exports]
5980
5981 sb.emitOp(node, 'PICKITEM');
5982 }
5983 }
5984
5985}
5986
5987// Output: [modules]
5988
5989class GetModulesHelper extends Helper {
5990 emit(sb, node, options) {
5991 if (options.pushValue) {
5992 // ['modules', globalObjectVal]
5993 sb.emitPushString(node, InternalGlobalProperties.MODULES); // [modules]
5994
5995 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty);
5996 }
5997 }
5998
5999}
6000
6001let InternalBlockchainInterfaceProperties;
6002
6003(function (InternalBlockchainInterfaceProperties) {
6004 InternalBlockchainInterfaceProperties["BLOCKCHAIN_INTERFACE"] = "BlockchainInterface";
6005})(InternalBlockchainInterfaceProperties || (InternalBlockchainInterfaceProperties = {}));
6006
6007// Input: [objectVal]
6008// Output: [boolean]
6009class IsBlockchainInterfaceHelper extends Helper {
6010 constructor(options) {
6011 super();
6012 Object.defineProperty(this, "name", {
6013 configurable: true,
6014 enumerable: true,
6015 writable: true,
6016 value: void 0
6017 });
6018 this.name = options.name;
6019 }
6020
6021 emit(sb, node, optionsIn) {
6022 if (!optionsIn.pushValue) {
6023 sb.emitOp(node, 'DROP');
6024 return;
6025 }
6026
6027 const options = sb.pushValueOptions(optionsIn); // ['__brand', objectVal]
6028
6029 sb.emitPushString(node, '__brand'); // [brandVal]
6030
6031 sb.emitHelper(node, options, sb.helpers.getPropertyObjectProperty); // [brand]
6032
6033 sb.emitHelper(node, options, sb.helpers.getString); // [name, brand]
6034
6035 sb.emitPushString(node, this.name); // [boolean]
6036
6037 sb.emitOp(node, 'EQUAL');
6038 }
6039
6040}
6041
6042// Output: [blockchainInterface]
6043
6044class UnwrapBlockchainInterfaceHelper extends Helper {
6045 emit(sb, node, optionsIn) {
6046 if (!optionsIn.pushValue) {
6047 sb.emitOp(node, 'DROP');
6048 return;
6049 }
6050
6051 const options = sb.pushValueOptions(optionsIn); // ['blockchain_interface', objectVal]
6052
6053 sb.emitPushString(node, InternalBlockchainInterfaceProperties.BLOCKCHAIN_INTERFACE); // [blockchainInterface]
6054
6055 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty);
6056 }
6057
6058}
6059
6060// Input: [blockchainInterface]
6061// Output: [objectVal]
6062class WrapBlockchainInterfaceHelper extends Helper {
6063 constructor(options) {
6064 super();
6065 Object.defineProperty(this, "name", {
6066 configurable: true,
6067 enumerable: true,
6068 writable: true,
6069 value: void 0
6070 });
6071 this.name = options.name;
6072 }
6073
6074 emit(sb, node, optionsIn) {
6075 if (!optionsIn.pushValue) {
6076 sb.emitOp(node, 'DROP');
6077 return;
6078 }
6079
6080 const options = sb.pushValueOptions(optionsIn); // [objectVal, blockchainInterface]
6081
6082 sb.emitHelper(node, options, sb.helpers.createObject); // [objectVal, blockchainInterface, objectVal]
6083
6084 sb.emitOp(node, 'TUCK'); // ['__brand', objectVal, blockchainInterface, objectVal]
6085
6086 sb.emitPushString(node, '__brand'); // [name, '__brand', objectVal, blockchainInterface, objectVal]
6087
6088 sb.emitPushString(node, this.name); // [nameVal, '__brand', objectVal, blockchainInterface, objectVal]
6089
6090 sb.emitHelper(node, options, sb.helpers.createString); // [blockchainInterface, objectVal]
6091
6092 sb.emitHelper(node, options, sb.helpers.setDataPropertyObjectProperty); // [objectVal, blockchainInterface, objectVal]
6093
6094 sb.emitOp(node, 'OVER'); // ['blockchain_interface', objectVal, blockchainInterface, objectVal]
6095
6096 sb.emitPushString(node, InternalBlockchainInterfaceProperties.BLOCKCHAIN_INTERFACE); // [blockchainInterface, 'blockchain_interface', objectVal, objectVal]
6097
6098 sb.emitOp(node, 'ROT'); // [objectVal]
6099
6100 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
6101 }
6102
6103}
6104
6105// Input: []
6106// Output: [objectVal]
6107class CreateBufferHelper extends Helper {
6108 emit(sb, node, options) {
6109 if (options.pushValue) {
6110 // [Buffer]
6111 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
6112 property: 'Buffer'
6113 })); // [objectVal]
6114
6115 sb.emitHelper(node, options, sb.helpers.new({
6116 noArgs: true
6117 }));
6118 }
6119 }
6120
6121}
6122
6123let InternalBufferProperties;
6124
6125(function (InternalBufferProperties) {
6126 InternalBufferProperties["DATA"] = "Data";
6127})(InternalBufferProperties || (InternalBufferProperties = {}));
6128
6129// Output: [byteArray]
6130
6131class GetBufferValueHelper extends Helper {
6132 emit(sb, node, optionsIn) {
6133 const options = sb.pushValueOptions(optionsIn); // ['data', objectVal]
6134
6135 sb.emitPushString(node, InternalBufferProperties.DATA); // [byteArray]
6136
6137 sb.emitHelper(node, options, sb.helpers.getInternalObjectProperty);
6138 }
6139
6140}
6141
6142// Output: []
6143
6144class SetBufferValueHelper extends Helper {
6145 emit(sb, node, optionsIn) {
6146 const options = sb.pushValueOptions(optionsIn); // ['data', byteArray, objectVal]
6147
6148 sb.emitPushString(node, InternalBufferProperties.DATA); // [byteArray, 'data', objectVal]
6149
6150 sb.emitOp(node, 'SWAP'); // []
6151
6152 sb.emitHelper(node, options, sb.helpers.setInternalObjectProperty);
6153 }
6154
6155}
6156
6157// Input: [objectVal]
6158// Output: [byteArray]
6159class UnwrapBufferHelper extends Helper {
6160 emit(sb, node, options) {
6161 if (!options.pushValue) {
6162 sb.emitOp(node, 'DROP');
6163 return;
6164 } // [byteArray]
6165
6166
6167 sb.emitHelper(node, options, sb.helpers.getBufferValue);
6168 }
6169
6170}
6171
6172// Input: [byteArray]
6173// Output: [objectVal]
6174class WrapBufferHelper extends Helper {
6175 emit(sb, node, options) {
6176 if (!options.pushValue) {
6177 sb.emitOp(node, 'DROP');
6178 return;
6179 } // [objectVal, byteArray]
6180
6181
6182 sb.emitHelper(node, options, sb.helpers.createBuffer); // [objectVal, byteArray, objectVal]
6183
6184 sb.emitOp(node, 'TUCK'); // [byteArray, objectVal, objectVal]
6185
6186 sb.emitOp(node, 'SWAP'); // [objectVal]
6187
6188 sb.emitHelper(node, options, sb.helpers.setBufferValue);
6189 }
6190
6191}
6192
6193const createHelpers = () => {
6194 const cache = {};
6195
6196 function memoized(HelperClass) {
6197 return options => {
6198 const key = HelperClass.getKey(options);
6199
6200 if (cache[key] == null) {
6201 cache[key] = new HelperClass(options);
6202 }
6203
6204 return cache[key];
6205 };
6206 }
6207
6208 return {
6209 arrFilter: options => new ArrFilterHelper(options),
6210 arrMap: options => new ArrMapHelper(options),
6211 arrForEach: options => new ArrForEachHelper(options),
6212 cloneArray: new CloneArrayHelper(),
6213 extendArray: new ExtendArrayHelper(),
6214 forType: options => new ForTypeHelper(options),
6215 genericDeserialize: new GenericDeserializeHelper(),
6216 genericSerialize: new GenericSerializeHelper(),
6217 equalsEqualsEquals: options => new EqualsEqualsEqualsHelper(options),
6218 equalsEqualsEqualsNumber: new EqualsEqualsEqualsNumberHelper(),
6219 equalsEqualsEqualsSameType: new EqualsEqualsEqualsSameTypeHelper(),
6220 equalsEqualsEqualsUnknown: new EqualsEqualsEqualsUnknownHelper(),
6221 equalsEquals: options => new EqualsEqualsHelper(options),
6222 lessThan: options => new LessThanHelper(options),
6223 processStatements: options => new ProcessStatementsHelper(options),
6224 args: new ArgumentsHelper(),
6225 bindFunctionObjectThis: options => new BindFunctionObjectThisHelper(options),
6226 bindFunctionThis: options => new BindFunctionThisHelper(options),
6227 call: new CallHelper(),
6228 cloneFunction: new CloneFunctionHelper(),
6229 cloneFunctionObject: options => new CloneFunctionObjectHelper(options),
6230 createCallArray: new CreateCallArrayHelper(),
6231 createConstructArray: options => new CreateConstructArrayHelper(options),
6232 createFunctionArray: options => new CreateFunctionArrayHelper(options),
6233 createFunctionObject: options => new CreateFunctionObjectHelper(options),
6234 function: options => new FunctionHelper(options),
6235 invokeCall: memoized(InvokeCallHelper),
6236 invokeConstruct: options => new InvokeConstructHelper(options),
6237 new: options => new NewHelper(options),
6238 parameters: new ParametersHelper(),
6239 forLoop: options => new ForLoopHelper(options),
6240 if: options => new IfHelper(options),
6241 case: (cases, defaultCase) => new CaseHelper(cases, defaultCase),
6242 createCompletion: new CreateCompletionHelper(),
6243 createNormalCompletion: new CreateNormalCompletionHelper(),
6244 createThrowCompletion: new CreateThrowCompletionHelper(),
6245 getCompletionError: new GetCompletionErrorHelper(),
6246 getCompletionVal: new GetCompletionValHelper(),
6247 handleCompletion: new HandleCompletionHelper(),
6248 pickCompletionVal: new PickCompletionValHelper(),
6249 throw: new ThrowHelper(),
6250 throwTypeError: new ThrowTypeErrorHelper(),
6251 createBoolean: new CreateBooleanHelper(),
6252 createNull: new CreateNullHelper(),
6253 createNumber: new CreateNumberHelper(),
6254 createObject: new CreateObjectHelper(),
6255 createString: new CreateStringHelper(),
6256 createSymbol: new CreateSymbolHelper(),
6257 createUndefined: new CreateUndefinedHelper(),
6258 isBoolean: new IsBooleanHelper(),
6259 isNull: new IsNullHelper(),
6260 isNumber: new IsNumberHelper(),
6261 isObject: new IsObjectHelper(),
6262 isString: new IsStringHelper(),
6263 isSymbol: new IsSymbolHelper(),
6264 isUndefined: new IsUndefinedHelper(),
6265 isNullOrUndefined: new IsNullOrUndefinedHelper(),
6266 isSameType: new IsSameTypeHelper(),
6267 getBoolean: new GetBooleanHelper(),
6268 getNumber: new GetNumberHelper(),
6269 getString: new GetStringHelper(),
6270 getSymbol: new GetSymbolHelper(),
6271 getObject: new GetObjectHelper(),
6272 toBoolean: options => new ToBooleanHelper(options),
6273 toString: options => new ToStringHelper(options),
6274 toNumber: options => new ToNumberHelper(options),
6275 toObject: options => new ToObjectHelper(options),
6276 toPrimitive: options => new ToPrimitiveHelper(options),
6277 getSymbolObject: new GetSymbolObjectHelper(),
6278 getSymbolObjectProperty: new GetSymbolObjectPropertyHelper(),
6279 setSymbolObjectProperty: new SetSymbolObjectPropertyHelper(),
6280 setDataSymbolObjectProperty: new SetDataSymbolObjectPropertyHelper(),
6281 setAccessorSymbolObjectProperty: options => new SetAccessorSymbolObjectPropertyHelper(options),
6282 getPropertyObject: new GetPropertyObjectHelper(),
6283 getPropertyObjectProperty: new GetPropertyObjectPropertyHelper(),
6284 setPropertyObjectProperty: new SetPropertyObjectPropertyHelper(),
6285 setDataPropertyObjectProperty: new SetDataPropertyObjectPropertyHelper(),
6286 setAccessorPropertyObjectProperty: options => new SetAccessorPropertyObjectPropertyHelper(options),
6287 getInternalObject: new GetInternalObjectHelper(),
6288 getInternalObjectProperty: new GetInternalObjectPropertyHelper(),
6289 setInternalObjectProperty: new SetInternalObjectPropertyHelper(),
6290 shallowCloneObject: new ShallowCloneObjectHelper(),
6291 shallowCloneObj: new ShallowCloneObjHelper(),
6292 elementAccess: new ElementAccessHelper(),
6293 unwrapType: new UnwrapTypeHelper(),
6294 unwrapVal: new UnwrapValHelper(),
6295 instanceof: new InstanceofHelper(),
6296 createPropertyObject: new CreatePropertyObjectHelper(),
6297 findObjectProperty: options => new FindObjectPropertyHelper(options),
6298 getArrayValue: new GetArrayValueHelper(),
6299 createArray: new CreateArrayHelper(),
6300 setArrayValue: new SetArrayValueHelper(),
6301 getArrayIndex: new GetArrayIndexHelper(),
6302 setArrayIndex: new SetArrayIndexHelper(),
6303 wrapArray: new WrapArrayHelper(),
6304 unwrapArray: new UnwrapArrayHelper(),
6305 createBuffer: new CreateBufferHelper(),
6306 getBufferValue: new GetBufferValueHelper(),
6307 setBufferValue: new SetBufferValueHelper(),
6308 unwrapBuffer: new UnwrapBufferHelper(),
6309 wrapBuffer: new WrapBufferHelper(),
6310 export: options => new ExportHelper(options),
6311 exportSingle: options => new ExportSingleHelper(options),
6312 getModule: options => new GetModuleHelper(options),
6313 getCurrentModule: new GetCurrentModuleHelper(),
6314 getModules: new GetModulesHelper(),
6315 addEmptyModule: new AddEmptyModuleHelper(),
6316 isBlockchainInterface: options => new IsBlockchainInterfaceHelper(options),
6317 wrapBlockchainInterface: options => new WrapBlockchainInterfaceHelper(options),
6318 unwrapBlockchainInterface: new UnwrapBlockchainInterfaceHelper(),
6319 addArguments: new AddArgumentsHelper(),
6320 addArrayObject: new AddArrayObjectHelper(),
6321 addBooleanObject: new AddBooleanObjectHelper(),
6322 addBufferObject: new AddBufferObjectHelper(),
6323 addErrorObject: new AddErrorObjectHelper(),
6324 addModules: new AddModulesHelper(),
6325 addNumberObject: new AddNumberObjectHelper(),
6326 addObjectObject: new AddObjectObjectHelper(),
6327 addStringObject: new AddStringObjectHelper(),
6328 addSymbolObject: new AddSymbolObjectHelper(),
6329 setGlobalObject: new SetGlobalObjectHelper(),
6330 getArgument: options => new GetArgumentHelper(options),
6331 getGlobalProperty: options => new GetGlobalPropertyHelper(options),
6332 globalProperties: GLOBAL_PROPERTIES
6333 };
6334};
6335
6336class ClassDeclarationCompiler extends NodeCompiler {
6337 constructor(...args) {
6338 var _temp;
6339
6340 return _temp = super(...args), Object.defineProperty(this, "kind", {
6341 configurable: true,
6342 enumerable: true,
6343 writable: true,
6344 value: Ast.SyntaxKind.ClassDeclaration
6345 }), _temp;
6346 }
6347
6348 visitNode(sb, decl, optionsIn) {
6349 let options = sb.pushValueOptions(sb.noSuperClassOptions(optionsIn));
6350 const name = sb.scope.add(decl.getNameOrThrow());
6351 const extendsExpr = decl.getExtends();
6352 let superClassIn;
6353
6354 if (extendsExpr != null) {
6355 superClassIn = sb.scope.addUnique();
6356 options = sb.superClassOptions(options, superClassIn); // [superClass]
6357
6358 sb.visit(extendsExpr.getExpression(), options); // []
6359
6360 sb.scope.set(sb, extendsExpr, options, superClassIn);
6361 }
6362
6363 const superClass = superClassIn;
6364 /* Create constructor function */
6365 // [farr]
6366
6367 sb.emitHelper(decl, options, sb.helpers.createConstructArray({
6368 body: () => {
6369 // [argsarr]
6370 const ctorImpl = decl.getConstructors().find(ctor => ctor.isImplementation()); // Default value assignments
6371
6372 if (ctorImpl != null) {
6373 // []
6374 sb.emitHelper(ctorImpl, options, sb.helpers.parameters); // Super call statement
6375 } else if (superClass != null && extendsExpr != null) {
6376 // [thisObjectVal, argsarr]
6377 sb.scope.getThis(sb, decl, options); // [ctor, thisObjectVal, argsarr]
6378
6379 sb.scope.get(sb, decl, options, superClass); // []
6380
6381 sb.emitHelper(decl, options, sb.helpers.invokeConstruct()); // Drop the argsarray, we must not use it
6382 } else {
6383 // []
6384 sb.emitOp(decl, 'DROP');
6385 } // Parameter property assignments
6386 // Member variable assignments
6387 // [thisObjectVal]
6388
6389
6390 sb.scope.getThis(sb, decl, options);
6391 decl.getInstanceProperties().filter(Ast.TypeGuards.isPropertyDeclaration).forEach(property => {
6392 const initializer = property.getInitializer();
6393
6394 if (initializer != null) {
6395 sb.emitOp(decl, 'DUP'); // [prop, thisObjectVal, thisObjectVal]
6396
6397 sb.emitPushString(initializer, property.getName()); // [init, prop, thisObjectVal, thisObjectVal]
6398
6399 sb.visit(initializer, options); // [thisObjectVal]
6400
6401 sb.emitHelper(initializer, options, sb.helpers.setDataPropertyObjectProperty);
6402 }
6403 }); // []
6404
6405 sb.emitOp(decl, 'DROP'); // Constructor statements
6406
6407 if (ctorImpl != null) {
6408 sb.visit(ctorImpl.getBodyOrThrow(), options);
6409 }
6410 }
6411 })); // [fobjectVal]
6412
6413 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6414 property: InternalFunctionProperties.CONSTRUCT
6415 }));
6416 /* Create prototype */
6417 // [fobjectVal, fobjectVal]
6418
6419 sb.emitOp(decl, 'DUP'); // ['prototype', fobjectVal, fobjectVal]
6420
6421 sb.emitPushString(decl, 'prototype'); // [fobjectVal, 'prototype', fobjectVal, fobjectVal]
6422
6423 sb.emitOp(decl, 'OVER'); // [objectVal, fobjectVal, 'prototype', fobjectVal, fobjectVal]
6424
6425 sb.emitHelper(decl, options, sb.helpers.createObject); // [objectVal, fobjectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6426
6427 sb.emitOp(decl, 'TUCK'); // ['constructor', objectVal, fobjectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6428
6429 sb.emitPushString(decl, 'constructor'); // [fobjectVal, 'constructor', objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6430
6431 sb.emitOp(decl, 'ROT'); // [objectVal, 'prototype', fobjectVal, fobjectVal]
6432
6433 sb.emitHelper(decl, options, sb.helpers.setDataPropertyObjectProperty);
6434 decl.getInstanceMethods().forEach(method => {
6435 if (method.isImplementation()) {
6436 // [objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6437 sb.emitOp(method, 'DUP'); // [name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6438
6439 sb.emitPushString(method, method.getName()); // [farr, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6440
6441 sb.emitHelper(method, options, sb.helpers.createCallArray); // [methodObjectVal, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6442
6443 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6444 property: InternalFunctionProperties.CALL
6445 })); // [objectVal, 'prototype', fobjectVal, fobjectVal]
6446
6447 sb.emitHelper(method, options, sb.helpers.setDataPropertyObjectProperty);
6448 }
6449 });
6450 decl.getSetAccessors().filter(accessor => !accessor.isStatic()).forEach(accessor => {
6451 // [objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6452 sb.emitOp(accessor, 'DUP'); // [name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6453
6454 sb.emitPushString(accessor, accessor.getName()); // [farr, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6455
6456 sb.emitHelper(accessor, options, sb.helpers.createCallArray); // [methodObjectVal, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6457
6458 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6459 property: InternalFunctionProperties.CALL
6460 }));
6461 const getAccessor = accessor.getGetAccessor();
6462 const hasGet = getAccessor != null;
6463
6464 if (getAccessor != null) {
6465 sb.emitHelper(getAccessor, options, sb.helpers.createCallArray);
6466 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6467 property: InternalFunctionProperties.CALL
6468 }));
6469 } // [objectVal, 'prototype', fobjectVal, fobjectVal]
6470
6471
6472 sb.emitHelper(accessor, options, sb.helpers.setAccessorPropertyObjectProperty({
6473 hasSet: true,
6474 hasGet
6475 }));
6476 });
6477 decl.getGetAccessors().filter(accessor => !accessor.isStatic() && accessor.getSetAccessor() == null).forEach(accessor => {
6478 // [objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6479 sb.emitOp(accessor, 'DUP'); // [name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6480
6481 sb.emitPushString(accessor, accessor.getName()); // [farr, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6482
6483 sb.emitHelper(accessor, options, sb.helpers.createCallArray); // [methodObjectVal, name, objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6484
6485 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6486 property: InternalFunctionProperties.CALL
6487 })); // [objectVal, 'prototype', fobjectVal, fobjectVal]
6488
6489 sb.emitHelper(accessor, options, sb.helpers.setAccessorPropertyObjectProperty({
6490 hasSet: false,
6491 hasGet: true
6492 }));
6493 });
6494 /* Set superclass prototype */
6495
6496 if (superClass != null && extendsExpr != null) {
6497 // [objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6498 sb.emitOp(extendsExpr, 'DUP'); // ['prototype', objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6499
6500 sb.emitPushString(extendsExpr, 'prototype'); // [superobjectVal, 'prototype', objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6501
6502 sb.scope.get(sb, extendsExpr, options, superClass); // ['prototype', superobjectVal, 'prototype', objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6503
6504 sb.emitPushString(extendsExpr, 'prototype'); // [superprototype, 'prototype', objectVal, objectVal, 'prototype', fobjectVal, fobjectVal]
6505
6506 sb.emitHelper(extendsExpr, options, sb.helpers.getPropertyObjectProperty); // [objectVal, 'prototype', fobjectVal, fobjectVal]
6507
6508 sb.emitHelper(extendsExpr, options, sb.helpers.setDataPropertyObjectProperty);
6509 } // [fobjectVal]
6510
6511
6512 sb.emitHelper(decl, options, sb.helpers.setDataPropertyObjectProperty);
6513
6514 if (decl.isNamedExport() || decl.isDefaultExport()) {
6515 // [fobjectVal, fobjectVal]
6516 sb.emitOp(decl, 'DUP'); // [fobjectVal]
6517
6518 sb.emitHelper(decl, options, sb.helpers.exportSingle({
6519 name: decl.isNamedExport() ? decl.getNameOrThrow() : undefined,
6520 defaultExport: decl.isDefaultExport()
6521 }));
6522 } // []
6523
6524
6525 sb.scope.set(sb, decl, options, name);
6526 }
6527
6528}
6529
6530class EnumDeclarationCompiler extends NodeCompiler {
6531 constructor(...args) {
6532 var _temp;
6533
6534 return _temp = super(...args), Object.defineProperty(this, "kind", {
6535 configurable: true,
6536 enumerable: true,
6537 writable: true,
6538 value: Ast.SyntaxKind.EnumDeclaration
6539 }), _temp;
6540 }
6541
6542 visitNode(sb, decl, options) {
6543 sb.reportUnsupported(decl);
6544 }
6545
6546}
6547
6548class EnumMemberCompiler extends NodeCompiler {
6549 constructor(...args) {
6550 var _temp;
6551
6552 return _temp = super(...args), Object.defineProperty(this, "kind", {
6553 configurable: true,
6554 enumerable: true,
6555 writable: true,
6556 value: Ast.SyntaxKind.EnumMember
6557 }), _temp;
6558 }
6559
6560 visitNode(sb, decl, options) {
6561 sb.reportUnsupported(decl);
6562 }
6563
6564}
6565
6566class ExportAssignmentCompiler extends NodeCompiler {
6567 constructor(...args) {
6568 var _temp;
6569
6570 return _temp = super(...args), Object.defineProperty(this, "kind", {
6571 configurable: true,
6572 enumerable: true,
6573 writable: true,
6574 value: Ast.SyntaxKind.ExportAssignment
6575 }), _temp;
6576 }
6577
6578 visitNode(sb, node, optionsIn) {
6579 if (node.isExportEquals()) {
6580 sb.reportUnsupported(node);
6581 } else {
6582 const options = sb.pushValueOptions(optionsIn); // [val]
6583
6584 sb.visit(node.getExpression(), options); // []
6585
6586 sb.emitHelper(node, options, sb.helpers.exportSingle({
6587 defaultExport: true
6588 }));
6589 }
6590 }
6591
6592}
6593
6594class ExportDeclarationCompiler extends NodeCompiler {
6595 constructor(...args) {
6596 var _temp;
6597
6598 return _temp = super(...args), Object.defineProperty(this, "kind", {
6599 configurable: true,
6600 enumerable: true,
6601 writable: true,
6602 value: Ast.SyntaxKind.ExportDeclaration
6603 }), _temp;
6604 }
6605
6606 visitNode(sb, node, optionsIn) {
6607 const options = sb.pushValueOptions(optionsIn);
6608
6609 const getName = namedExport => {
6610 let name = namedExport.getNameNode().getText();
6611 const alias = namedExport.getAliasIdentifier();
6612
6613 if (alias != null) {
6614 name = alias.getText();
6615 }
6616
6617 return name;
6618 };
6619
6620 const moduleSpecifier = node.getModuleSpecifierSourceFile(); // [exports]
6621
6622 sb.emitHelper(node, options, sb.helpers.getCurrentModule);
6623
6624 if (moduleSpecifier == null) {
6625 node.getNamedExports().filter(namedExport => namedExport.getLocalTargetDeclarations().some(decl => !Ast.TypeGuards.isTypeAliasDeclaration(decl))).forEach(namedExport => {
6626 // [exports, exports]
6627 sb.emitOp(node, 'DUP'); // [val, exports, exports]
6628
6629 sb.scope.get(sb, node, options, namedExport.getNameNode().getText()); // [exports]
6630
6631 sb.emitHelper(node, options, sb.helpers.export({
6632 name: getName(namedExport)
6633 }));
6634 });
6635 } else {
6636 // [moduleExports, exports]
6637 sb.loadModule(moduleSpecifier);
6638 node.getNamedExports().filter(namedExport => sb.hasExport(moduleSpecifier, namedExport.getNameNode().getText())).forEach(namedExport => {
6639 // [exports, moduleExports]
6640 sb.emitOp(node, 'SWAP'); // [exports, moduleExports, exports]
6641
6642 sb.emitOp(node, 'TUCK'); // [moduleExports, exports, moduleExports, exports]
6643
6644 sb.emitOp(node, 'OVER'); // [name, moduleExports, exports, moduleExports, exports]
6645
6646 sb.emitPushString(node, namedExport.getNameNode().getText()); // [val, exports, moduleExports, exports]
6647
6648 sb.emitOp(node, 'PICKITEM'); // [moduleExports, exports]
6649
6650 sb.emitHelper(node, options, sb.helpers.export({
6651 name: getName(namedExport)
6652 }));
6653 }); // [exports]
6654
6655 sb.emitOp(node, 'DROP');
6656 } // []
6657
6658
6659 sb.emitOp(node, 'DROP');
6660 }
6661
6662}
6663
6664class FunctionDeclarationCompiler extends NodeCompiler {
6665 constructor(...args) {
6666 var _temp;
6667
6668 return _temp = super(...args), Object.defineProperty(this, "kind", {
6669 configurable: true,
6670 enumerable: true,
6671 writable: true,
6672 value: Ast.SyntaxKind.FunctionDeclaration
6673 }), _temp;
6674 }
6675
6676 visitNode(sb, decl, optionsIn) {
6677 const options = sb.pushValueOptions(optionsIn);
6678 const name = sb.scope.add(decl.getName()); // [callArray]
6679
6680 sb.emitHelper(decl, options, sb.helpers.createCallArray); // [callObjectVal]
6681
6682 sb.emitHelper(decl, options, sb.helpers.createFunctionObject({
6683 property: InternalFunctionProperties.CALL
6684 }));
6685
6686 if (decl.isNamedExport() || decl.isDefaultExport()) {
6687 // [callObjectVal, callObjectVal]
6688 sb.emitOp(decl, 'DUP'); // [callObjectVal]
6689
6690 sb.emitHelper(decl, options, sb.helpers.exportSingle({
6691 name: decl.isNamedExport() ? decl.getName() : undefined,
6692 defaultExport: decl.isDefaultExport()
6693 }));
6694 } // []
6695
6696
6697 sb.scope.set(sb, decl, options, name);
6698 }
6699
6700}
6701
6702class ImportDeclarationCompiler extends NodeCompiler {
6703 constructor(...args) {
6704 var _temp;
6705
6706 return _temp = super(...args), Object.defineProperty(this, "kind", {
6707 configurable: true,
6708 enumerable: true,
6709 writable: true,
6710 value: Ast.SyntaxKind.ImportDeclaration
6711 }), _temp;
6712 }
6713
6714 visitNode(sb, node, optionsIn) {
6715 const options = sb.pushValueOptions(optionsIn); // [exports]
6716
6717 sb.loadModule(node.getModuleSpecifierSourceFileOrThrow());
6718 const namespaceImport = node.getNamespaceImport();
6719
6720 if (namespaceImport != null) {
6721 const name = namespaceImport.getText();
6722 sb.scope.add(name); // [objectVal]
6723
6724 sb.emitHelper(node, options, sb.helpers.createPropertyObject); // []
6725
6726 sb.scope.set(sb, node, options, name);
6727 } else {
6728 const defaultImport = node.getDefaultImport();
6729 const namedImports = node.getNamedImports().filter(namedImport => sb.hasExport(namedImport.getImportDeclaration().getModuleSpecifierSourceFileOrThrow(), namedImport.getName()));
6730
6731 if (defaultImport != null) {
6732 if (namedImports.length > 0) {
6733 // [exports, exports]
6734 sb.emitOp(node, 'DUP');
6735 } // ['default', exports]
6736
6737
6738 sb.emitPushString(node, 'default'); // [val]
6739
6740 sb.emitOp(node, 'PICKITEM');
6741 const name = defaultImport.getText();
6742 sb.scope.add(name); // []
6743
6744 sb.scope.set(sb, node, options, name);
6745 }
6746
6747 if (namedImports.length > 0) {
6748 for (const namedImport of namedImports) {
6749 // [exports, exports]
6750 sb.emitOp(node, 'DUP'); // [name, exports, exports]
6751
6752 sb.emitPushString(node, namedImport.getName()); // [val, exports]
6753
6754 sb.emitOp(node, 'PICKITEM');
6755 let name = namedImport.getName();
6756 const alias = namedImport.getAliasIdentifier();
6757
6758 if (alias != null) {
6759 name = alias.getText();
6760 }
6761
6762 sb.scope.add(name); // [exports]
6763
6764 sb.scope.set(sb, node, options, name);
6765 }
6766
6767 sb.emitOp(node, 'DROP');
6768 }
6769 }
6770 }
6771
6772}
6773
6774class TypeAliasDeclarationCompiler extends NodeCompiler {
6775 constructor(...args) {
6776 var _temp;
6777
6778 return _temp = super(...args), Object.defineProperty(this, "kind", {
6779 configurable: true,
6780 enumerable: true,
6781 writable: true,
6782 value: Ast.SyntaxKind.TypeAliasDeclaration
6783 }), _temp;
6784 }
6785
6786 visitNode(sb, node, optionsIn) {// do nothing
6787 }
6788
6789}
6790
6791class VariableDeclarationCompiler extends NodeCompiler {
6792 constructor(...args) {
6793 var _temp;
6794
6795 return _temp = super(...args), Object.defineProperty(this, "kind", {
6796 configurable: true,
6797 enumerable: true,
6798 writable: true,
6799 value: Ast.SyntaxKind.VariableDeclaration
6800 }), _temp;
6801 }
6802
6803 visitNode(sb, node, options) {
6804 const name = sb.scope.add(node.getName());
6805 const expr = node.getInitializer();
6806
6807 if (expr != null) {
6808 sb.visit(expr, sb.pushValueOptions(options));
6809 sb.scope.set(sb, node, options, name);
6810 }
6811 }
6812
6813}
6814
6815class VariableDeclarationListCompiler extends NodeCompiler {
6816 constructor(...args) {
6817 var _temp;
6818
6819 return _temp = super(...args), Object.defineProperty(this, "kind", {
6820 configurable: true,
6821 enumerable: true,
6822 writable: true,
6823 value: Ast.SyntaxKind.VariableDeclarationList
6824 }), _temp;
6825 }
6826
6827 visitNode(sb, node, options) {
6828 node.getDeclarations().forEach(decl => {
6829 sb.visit(decl, options);
6830 });
6831 }
6832
6833}
6834
6835var declarations = [ClassDeclarationCompiler, EnumDeclarationCompiler, EnumMemberCompiler, ExportAssignmentCompiler, ExportDeclarationCompiler, FunctionDeclarationCompiler, ImportDeclarationCompiler, TypeAliasDeclarationCompiler, VariableDeclarationCompiler, VariableDeclarationListCompiler];
6836
6837class DecoratorCompiler extends NodeCompiler {
6838 constructor(...args) {
6839 var _temp;
6840
6841 return _temp = super(...args), Object.defineProperty(this, "kind", {
6842 configurable: true,
6843 enumerable: true,
6844 writable: true,
6845 value: Ast.SyntaxKind.Decorator
6846 }), _temp;
6847 }
6848
6849 visitNode(sb, decl, options) {
6850 sb.reportUnsupported(decl);
6851 }
6852
6853}
6854
6855var decorator = [DecoratorCompiler];
6856
6857class ArrayLiteralExpressionCompiler extends NodeCompiler {
6858 constructor(...args) {
6859 var _temp;
6860
6861 return _temp = super(...args), Object.defineProperty(this, "kind", {
6862 configurable: true,
6863 enumerable: true,
6864 writable: true,
6865 value: Ast.SyntaxKind.ArrayLiteralExpression
6866 }), _temp;
6867 }
6868
6869 visitNode(sb, node, optionsIn) {
6870 const options = sb.pushValueOptions(optionsIn);
6871 const elements = [...node.getElements()].reverse();
6872
6873 for (const element of elements) {
6874 sb.visit(element, options);
6875 } // [length, ...vals]
6876
6877
6878 sb.emitPushInt(node, elements.length); // [valArr]
6879
6880 sb.emitOp(node, 'PACK'); // [arrayObjectVal]
6881
6882 sb.emitHelper(node, options, sb.helpers.wrapArray);
6883
6884 if (!optionsIn.pushValue) {
6885 sb.emitOp(node, 'DROP');
6886 }
6887 }
6888
6889}
6890
6891class ArrowFunctionCompiler extends NodeCompiler {
6892 constructor(...args) {
6893 var _temp;
6894
6895 return _temp = super(...args), Object.defineProperty(this, "kind", {
6896 configurable: true,
6897 enumerable: true,
6898 writable: true,
6899 value: Ast.SyntaxKind.ArrowFunction
6900 }), _temp;
6901 }
6902
6903 visitNode(sb, expr, options) {
6904 if (options.pushValue) {
6905 // [this]
6906 sb.scope.getThis(sb, expr, options); // [callArray, this]
6907
6908 sb.emitHelper(expr, options, sb.helpers.createCallArray); // [callArray]
6909
6910 sb.emitHelper(expr, options, sb.helpers.bindFunctionThis({
6911 overwrite: true
6912 })); // [callObjectVal]
6913
6914 sb.emitHelper(expr, options, sb.helpers.createFunctionObject({
6915 property: InternalFunctionProperties.CALL
6916 }));
6917 }
6918 }
6919
6920}
6921
6922class AsExpressionCompiler extends NodeCompiler {
6923 constructor(...args) {
6924 var _temp;
6925
6926 return _temp = super(...args), Object.defineProperty(this, "kind", {
6927 configurable: true,
6928 enumerable: true,
6929 writable: true,
6930 value: Ast.SyntaxKind.AsExpression
6931 }), _temp;
6932 }
6933
6934 visitNode(sb, expr, options) {
6935 const type = sb.getType(expr);
6936
6937 if (options.cast != null && isAnyType(type)) {
6938 sb.visit(expr.getExpression(), options);
6939 } else {
6940 sb.visit(expr.getExpression(), sb.castOptions(options, type));
6941 }
6942 }
6943
6944}
6945
6946class AwaitExpressionCompiler extends NodeCompiler {
6947 constructor(...args) {
6948 var _temp;
6949
6950 return _temp = super(...args), Object.defineProperty(this, "kind", {
6951 configurable: true,
6952 enumerable: true,
6953 writable: true,
6954 value: Ast.SyntaxKind.AwaitExpression
6955 }), _temp;
6956 }
6957
6958 visitNode(sb, expr) {
6959 sb.reportUnsupported(expr);
6960 }
6961
6962}
6963
6964class BinaryExpressionCompiler extends NodeCompiler {
6965 constructor(...args) {
6966 var _temp;
6967
6968 return _temp = super(...args), Object.defineProperty(this, "kind", {
6969 configurable: true,
6970 enumerable: true,
6971 writable: true,
6972 value: Ast.SyntaxKind.BinaryExpression
6973 }), _temp;
6974 }
6975
6976 visitNode(sb, expr, options) {
6977 const kind = expr.getOperatorToken().getKind();
6978
6979 switch (kind) {
6980 case Ast.SyntaxKind.EqualsToken:
6981 case Ast.SyntaxKind.PlusEqualsToken:
6982 case Ast.SyntaxKind.MinusEqualsToken:
6983 case Ast.SyntaxKind.AsteriskAsteriskEqualsToken:
6984 case Ast.SyntaxKind.AsteriskEqualsToken:
6985 case Ast.SyntaxKind.SlashEqualsToken:
6986 case Ast.SyntaxKind.PercentEqualsToken:
6987 case Ast.SyntaxKind.AmpersandEqualsToken:
6988 case Ast.SyntaxKind.BarEqualsToken:
6989 case Ast.SyntaxKind.CaretEqualsToken:
6990 case Ast.SyntaxKind.LessThanLessThanEqualsToken:
6991 case Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
6992 case Ast.SyntaxKind.GreaterThanGreaterThanEqualsToken:
6993 this.visitAssignmentOperator(sb, kind, expr, options);
6994 break;
6995
6996 case Ast.SyntaxKind.AsteriskToken:
6997 case Ast.SyntaxKind.SlashToken:
6998 case Ast.SyntaxKind.PercentToken:
6999 case Ast.SyntaxKind.PlusToken:
7000 case Ast.SyntaxKind.MinusToken:
7001 case Ast.SyntaxKind.GreaterThanGreaterThanToken:
7002 case Ast.SyntaxKind.LessThanLessThanToken:
7003 case Ast.SyntaxKind.LessThanToken:
7004 case Ast.SyntaxKind.LessThanEqualsToken:
7005 case Ast.SyntaxKind.GreaterThanToken:
7006 case Ast.SyntaxKind.GreaterThanEqualsToken:
7007 case Ast.SyntaxKind.ExclamationEqualsToken:
7008 case Ast.SyntaxKind.EqualsEqualsToken:
7009 case Ast.SyntaxKind.AmpersandToken:
7010 case Ast.SyntaxKind.BarToken:
7011 case Ast.SyntaxKind.CaretToken:
7012 case Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
7013 case Ast.SyntaxKind.InKeyword:
7014 case Ast.SyntaxKind.InstanceOfKeyword:
7015 case Ast.SyntaxKind.CommaToken:
7016 case Ast.SyntaxKind.AsteriskAsteriskToken:
7017 case Ast.SyntaxKind.EqualsEqualsEqualsToken:
7018 case Ast.SyntaxKind.ExclamationEqualsEqualsToken:
7019 this.visitExpressionOperator(sb, kind, expr, options);
7020 break;
7021
7022 case Ast.SyntaxKind.AmpersandAmpersandToken:
7023 case Ast.SyntaxKind.BarBarToken:
7024 this.visitLogicalExpressionOperator(sb, kind, expr, options);
7025 break;
7026
7027 default:
7028 sb.assertUnreachable(kind);
7029 }
7030 }
7031
7032 visitAssignmentOperator(sb, kind, expr, options) {
7033 const left = expr.getLeft();
7034 const right = expr.getRight();
7035 const token = expr.getOperatorToken();
7036 const pushValueOptions = sb.pushValueOptions(options);
7037
7038 switch (kind) {
7039 case Ast.SyntaxKind.EqualsToken:
7040 sb.visit(expr.getRight(), pushValueOptions);
7041 break;
7042
7043 case Ast.SyntaxKind.PlusEqualsToken:
7044 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.PlusToken, left, right, pushValueOptions);
7045 break;
7046
7047 case Ast.SyntaxKind.MinusEqualsToken:
7048 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.MinusToken, left, right, pushValueOptions);
7049 break;
7050
7051 case Ast.SyntaxKind.AsteriskAsteriskEqualsToken:
7052 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.AsteriskAsteriskToken, left, right, pushValueOptions);
7053 break;
7054
7055 case Ast.SyntaxKind.AsteriskEqualsToken:
7056 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.AsteriskToken, left, right, pushValueOptions);
7057 break;
7058
7059 case Ast.SyntaxKind.SlashEqualsToken:
7060 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.SlashToken, left, right, pushValueOptions);
7061 break;
7062
7063 case Ast.SyntaxKind.PercentEqualsToken:
7064 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.PercentToken, left, right, pushValueOptions);
7065 break;
7066
7067 case Ast.SyntaxKind.AmpersandEqualsToken:
7068 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.AmpersandToken, left, right, pushValueOptions);
7069 break;
7070
7071 case Ast.SyntaxKind.BarEqualsToken:
7072 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.BarToken, left, right, pushValueOptions);
7073 break;
7074
7075 case Ast.SyntaxKind.CaretEqualsToken:
7076 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.CaretToken, left, right, pushValueOptions);
7077 break;
7078
7079 case Ast.SyntaxKind.LessThanLessThanEqualsToken:
7080 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.LessThanLessThanToken, left, right, pushValueOptions);
7081 break;
7082
7083 case Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
7084 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanToken, left, right, pushValueOptions);
7085 break;
7086
7087 case Ast.SyntaxKind.GreaterThanGreaterThanEqualsToken:
7088 this.visitExpressionOperatorBase(sb, token, Ast.SyntaxKind.GreaterThanGreaterThanToken, left, right, pushValueOptions);
7089 break;
7090
7091 default:
7092 sb.assertUnreachable(kind);
7093 }
7094
7095 sb.visit(expr.getLeft(), sb.setValueOptions(options));
7096 }
7097
7098 visitExpressionOperator(sb, kind, expr, options) {
7099 this.visitExpressionOperatorBase(sb, expr.getOperatorToken(), kind, expr.getLeft(), expr.getRight(), options);
7100 }
7101
7102 visitLogicalExpressionOperator(sb, kind, expr, options) {
7103 this.visitLogicalExpressionOperatorBase(sb, expr.getOperatorToken(), kind, expr.getLeft(), expr.getRight(), options);
7104 }
7105
7106 visitExpressionOperatorBase(sb, node, kind, left, right, options) {
7107 if (!options.pushValue) {
7108 sb.visit(left, options);
7109 sb.visit(right, options);
7110 return;
7111 }
7112
7113 const visit = (leftHelper, rightHelper) => {
7114 sb.visit(left, options);
7115 sb.emitHelper(left, options, leftHelper({
7116 type: sb.getType(left)
7117 }));
7118 sb.visit(right, options);
7119 sb.emitHelper(right, options, (rightHelper || leftHelper)({
7120 type: sb.getType(right)
7121 }));
7122 };
7123
7124 const visitNumeric = () => visit(sb.helpers.toNumber);
7125
7126 const leftType = sb.getType(left);
7127 const rightType = sb.getType(right);
7128 const isBinaryNumeric = isOnlyNumber(leftType) && isOnlyNumber(rightType);
7129
7130 switch (kind) {
7131 case Ast.SyntaxKind.AsteriskToken:
7132 visitNumeric();
7133 sb.emitOp(node, 'MUL');
7134 sb.emitHelper(node, options, sb.helpers.createNumber);
7135 break;
7136
7137 case Ast.SyntaxKind.SlashToken:
7138 visitNumeric();
7139 sb.emitOp(node, 'DIV');
7140 sb.emitHelper(node, options, sb.helpers.createNumber);
7141 break;
7142
7143 case Ast.SyntaxKind.PercentToken:
7144 visitNumeric();
7145 sb.emitOp(node, 'MOD');
7146 sb.emitHelper(node, options, sb.helpers.createNumber);
7147 break;
7148
7149 case Ast.SyntaxKind.PlusToken:
7150 if (isBinaryNumeric) {
7151 visitNumeric();
7152 sb.emitOp(node, 'ADD');
7153 sb.emitHelper(node, options, sb.helpers.createNumber);
7154 } else if (isOnlyString(leftType) && isOnlyString(rightType)) {
7155 visit(() => sb.helpers.getString);
7156 sb.emitOp(node, 'CAT');
7157 sb.emitHelper(node, options, sb.helpers.createString);
7158 } else if (isOnlyString(leftType)) {
7159 visit(() => sb.helpers.getString, sb.helpers.toString);
7160 sb.emitOp(node, 'CAT');
7161 sb.emitHelper(node, options, sb.helpers.createString);
7162 } else if (isOnlyString(rightType)) {
7163 visit(sb.helpers.toString, () => sb.helpers.getString);
7164 sb.emitOp(node, 'CAT');
7165 sb.emitHelper(node, options, sb.helpers.createString);
7166 } else {
7167 // TODO: Add preferredType
7168 // [right, left]
7169 visit(sb.helpers.toPrimitive); // [left, right]
7170
7171 sb.emitOp(node, 'SWAP'); // [left, right, left]
7172
7173 sb.emitOp(node, 'TUCK'); // [right, left, right, left]
7174
7175 sb.emitOp(node, 'TUCK'); // [isString, left, right, left]
7176
7177 sb.emitHelper(node, options, sb.helpers.isString); // [left, isString, right, left]
7178
7179 sb.emitOp(node, 'SWAP'); // [isString, isString, right, left]
7180
7181 sb.emitHelper(node, options, sb.helpers.isString);
7182 sb.emitHelper(node, options, sb.helpers.if({
7183 condition: () => {
7184 // [isEitherString, right, left]
7185 sb.emitOp(node, 'BOOLOR');
7186 },
7187 whenTrue: () => {
7188 // [string0, left]
7189 sb.emitHelper(node, options, sb.helpers.toString({
7190 type: sb.getType(right)
7191 })); // [left, string0]
7192
7193 sb.emitOp(node, 'SWAP'); // [string1, string0]
7194
7195 sb.emitHelper(node, options, sb.helpers.toString({
7196 type: sb.getType(left)
7197 })); // [string0, string1]
7198
7199 sb.emitOp(node, 'SWAP'); // [string]
7200
7201 sb.emitOp(node, 'CAT'); // [string]
7202
7203 sb.emitHelper(node, options, sb.helpers.createString);
7204 },
7205 whenFalse: () => {
7206 // [number0, left]
7207 sb.emitHelper(node, options, sb.helpers.toNumber({
7208 type: sb.getType(right)
7209 })); // [left, number0]
7210
7211 sb.emitOp(node, 'SWAP'); // [number1, number0]
7212
7213 sb.emitHelper(node, options, sb.helpers.toNumber({
7214 type: sb.getType(left)
7215 })); // [number0, number1]
7216
7217 sb.emitOp(node, 'SWAP'); // [number]
7218
7219 sb.emitOp(node, 'ADD'); // [number]
7220
7221 sb.emitHelper(node, options, sb.helpers.createNumber);
7222 }
7223 }));
7224 }
7225
7226 break;
7227
7228 case Ast.SyntaxKind.MinusToken:
7229 visitNumeric();
7230 sb.emitOp(node, 'SUB');
7231 sb.emitHelper(node, options, sb.helpers.createNumber);
7232 break;
7233 // TODO: Should we try to make these match the js semantics?
7234
7235 case Ast.SyntaxKind.GreaterThanGreaterThanToken:
7236 visitNumeric();
7237 sb.emitOp(node, 'SHR');
7238 sb.emitHelper(node, options, sb.helpers.createNumber);
7239 break;
7240
7241 case Ast.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
7242 visitNumeric();
7243 sb.emitOp(node, 'SHR');
7244 sb.emitHelper(node, options, sb.helpers.createNumber);
7245 break;
7246
7247 case Ast.SyntaxKind.LessThanLessThanToken:
7248 visitNumeric();
7249 sb.emitOp(node, 'SHL');
7250 sb.emitHelper(node, options, sb.helpers.createNumber);
7251 break;
7252
7253 case Ast.SyntaxKind.LessThanToken:
7254 sb.emitHelper(node, options, sb.helpers.lessThan({
7255 leftFirst: true,
7256 left,
7257 right
7258 }));
7259 sb.emitHelper(node, options, sb.helpers.createBoolean);
7260 break;
7261
7262 case Ast.SyntaxKind.LessThanEqualsToken:
7263 sb.emitHelper(node, options, sb.helpers.lessThan({
7264 leftFirst: false,
7265 left: right,
7266 right: left
7267 }));
7268 sb.emitOp(node, 'NOT');
7269 sb.emitHelper(node, options, sb.helpers.createBoolean);
7270 break;
7271
7272 case Ast.SyntaxKind.GreaterThanToken:
7273 sb.emitHelper(node, options, sb.helpers.lessThan({
7274 leftFirst: false,
7275 left: right,
7276 right: left
7277 }));
7278 sb.emitHelper(node, options, sb.helpers.createBoolean);
7279 break;
7280
7281 case Ast.SyntaxKind.GreaterThanEqualsToken:
7282 sb.emitHelper(node, options, sb.helpers.lessThan({
7283 leftFirst: true,
7284 left,
7285 right
7286 }));
7287 sb.emitOp(node, 'NOT');
7288 sb.emitHelper(node, options, sb.helpers.createBoolean);
7289 break;
7290
7291 case Ast.SyntaxKind.ExclamationEqualsToken:
7292 sb.emitHelper(node, options, sb.helpers.equalsEquals({
7293 left,
7294 right
7295 }));
7296 sb.emitOp(node, 'NOT');
7297 sb.emitHelper(node, options, sb.helpers.createBoolean);
7298 break;
7299
7300 case Ast.SyntaxKind.EqualsEqualsToken:
7301 sb.emitHelper(node, options, sb.helpers.equalsEquals({
7302 left,
7303 right
7304 }));
7305 sb.emitHelper(node, options, sb.helpers.createBoolean);
7306 break;
7307
7308 case Ast.SyntaxKind.AmpersandToken:
7309 visitNumeric();
7310 sb.emitOp(node, 'AND');
7311 sb.emitHelper(node, options, sb.helpers.createNumber);
7312 break;
7313
7314 case Ast.SyntaxKind.BarToken:
7315 visitNumeric();
7316 sb.emitOp(node, 'OR');
7317 sb.emitHelper(node, options, sb.helpers.createNumber);
7318 break;
7319
7320 case Ast.SyntaxKind.CaretToken:
7321 visitNumeric();
7322 sb.emitOp(node, 'XOR');
7323 sb.emitHelper(node, options, sb.helpers.createNumber);
7324 break;
7325
7326 case Ast.SyntaxKind.InKeyword:
7327 // TODO: Implement me
7328 sb.reportUnsupported(node);
7329 break;
7330
7331 case Ast.SyntaxKind.InstanceOfKeyword:
7332 // TODO: Implement me
7333 sb.reportUnsupported(node);
7334 break;
7335
7336 case Ast.SyntaxKind.CommaToken:
7337 sb.emitOp(node, 'DROP');
7338 break;
7339
7340 case Ast.SyntaxKind.AsteriskAsteriskToken:
7341 // TODO: Implement me
7342 sb.reportUnsupported(node);
7343 break;
7344
7345 case Ast.SyntaxKind.EqualsEqualsEqualsToken:
7346 sb.emitHelper(node, options, sb.helpers.equalsEqualsEquals({
7347 left,
7348 right
7349 }));
7350 sb.emitHelper(node, options, sb.helpers.createBoolean);
7351 break;
7352
7353 case Ast.SyntaxKind.ExclamationEqualsEqualsToken:
7354 sb.emitHelper(node, options, sb.helpers.equalsEqualsEquals({
7355 left,
7356 right
7357 }));
7358 sb.emitOp(node, 'NOT');
7359 sb.emitHelper(node, options, sb.helpers.createBoolean);
7360 break;
7361
7362 default:
7363 sb.assertUnreachable(kind);
7364 }
7365 }
7366
7367 visitLogicalExpressionOperatorBase(sb, node, kind, left, right, options) {
7368 switch (kind) {
7369 case Ast.SyntaxKind.AmpersandAmpersandToken:
7370 {
7371 sb.emitHelper(node, options, sb.helpers.if({
7372 condition: () => {
7373 // [left]
7374 sb.visit(left, sb.pushValueOptions(options));
7375
7376 if (options.pushValue) {
7377 // [left, left]
7378 sb.emitOp(left, 'DUP');
7379 } // [leftBoolean, ?left]
7380
7381
7382 sb.emitHelper(left, sb.pushValueOptions(options), sb.helpers.toBoolean({
7383 type: sb.getType(left)
7384 }));
7385 },
7386 whenTrue: () => {
7387 if (options.pushValue) {
7388 sb.emitOp(node, 'DROP');
7389 }
7390
7391 sb.visit(right, options);
7392 }
7393 }));
7394 break;
7395 }
7396
7397 case Ast.SyntaxKind.BarBarToken:
7398 {
7399 sb.emitHelper(node, options, sb.helpers.if({
7400 condition: () => {
7401 // [left]
7402 sb.visit(left, sb.pushValueOptions(options));
7403
7404 if (options.pushValue) {
7405 // [left, left]
7406 sb.emitOp(left, 'DUP');
7407 } // [leftBoolean, ?left]
7408
7409
7410 sb.emitHelper(left, sb.pushValueOptions(options), sb.helpers.toBoolean({
7411 type: sb.getType(left)
7412 }));
7413 },
7414 whenFalse: () => {
7415 if (options.pushValue) {
7416 sb.emitOp(node, 'DROP');
7417 }
7418
7419 sb.visit(right, options);
7420 }
7421 }));
7422 break;
7423 }
7424
7425 default:
7426 sb.assertUnreachable(kind);
7427 }
7428 }
7429
7430}
7431
7432class BooleanLiteralCompiler extends NodeCompiler {
7433 constructor(...args) {
7434 var _temp;
7435
7436 return _temp = super(...args), Object.defineProperty(this, "value", {
7437 configurable: true,
7438 enumerable: true,
7439 writable: true,
7440 value: void 0
7441 }), _temp;
7442 }
7443
7444 visitNode(sb, expr, options) {
7445 if (options.pushValue) {
7446 sb.emitPushBoolean(expr, this.value);
7447 sb.emitHelper(expr, options, sb.helpers.createBoolean);
7448 }
7449 }
7450
7451}
7452class TrueBooleanLiteralCompiler extends BooleanLiteralCompiler {
7453 constructor(...args) {
7454 var _temp2;
7455
7456 return _temp2 = super(...args), Object.defineProperty(this, "kind", {
7457 configurable: true,
7458 enumerable: true,
7459 writable: true,
7460 value: Ast.SyntaxKind.TrueKeyword
7461 }), Object.defineProperty(this, "value", {
7462 configurable: true,
7463 enumerable: true,
7464 writable: true,
7465 value: true
7466 }), _temp2;
7467 }
7468
7469}
7470class FalseBooleanLiteralCompiler extends BooleanLiteralCompiler {
7471 constructor(...args) {
7472 var _temp3;
7473
7474 return _temp3 = super(...args), Object.defineProperty(this, "kind", {
7475 configurable: true,
7476 enumerable: true,
7477 writable: true,
7478 value: Ast.SyntaxKind.FalseKeyword
7479 }), Object.defineProperty(this, "value", {
7480 configurable: true,
7481 enumerable: true,
7482 writable: true,
7483 value: false
7484 }), _temp3;
7485 }
7486
7487}
7488
7489class SimpleSysCallType {
7490 constructor() {
7491 Object.defineProperty(this, "name", {
7492 configurable: true,
7493 enumerable: true,
7494 writable: true,
7495 value: void 0
7496 });
7497 }
7498
7499 toSignature() {
7500 return this.name;
7501 }
7502
7503}
7504
7505class VoidClass extends SimpleSysCallType {
7506 constructor(...args) {
7507 var _temp;
7508
7509 return _temp = super(...args), Object.defineProperty(this, "name", {
7510 configurable: true,
7511 enumerable: true,
7512 writable: true,
7513 value: 'void'
7514 }), _temp;
7515 }
7516
7517 isOnlyType(sb, node, type) {
7518 return false;
7519 }
7520
7521 isType(sb, node, type) {
7522 return false;
7523 }
7524
7525 isRuntimeType(sb, node, options) {
7526 throw new Error('Should not check void at runtime');
7527 }
7528
7529 handleArgument(sb, node, options, type) {
7530 throw new Error('void should not be an argument');
7531 }
7532
7533 handleResult(sb, node, options, type, native = false) {
7534 sb.emitHelper(node, options, sb.helpers.createUndefined);
7535 }
7536
7537}
7538
7539const VoidValue = new VoidClass();
7540
7541class NumberClass extends SimpleSysCallType {
7542 constructor(...args) {
7543 var _temp2;
7544
7545 return _temp2 = super(...args), Object.defineProperty(this, "name", {
7546 configurable: true,
7547 enumerable: true,
7548 writable: true,
7549 value: 'number'
7550 }), _temp2;
7551 }
7552
7553 isOnlyType(sb, node, type) {
7554 return isOnlyNumber(type);
7555 }
7556
7557 isType(sb, node, type) {
7558 return isNumber(type);
7559 }
7560
7561 isRuntimeType(sb, node, options) {
7562 sb.emitHelper(node, options, sb.helpers.isNumber);
7563 }
7564
7565 handleArgument(sb, node, options, type, native = false) {
7566 if (!native) {
7567 sb.emitHelper(node, options, sb.helpers.getNumber);
7568 }
7569 }
7570
7571 handleResult(sb, node, options, type, native = false) {
7572 if (!native) {
7573 sb.emitHelper(node, options, sb.helpers.createNumber);
7574 }
7575 }
7576
7577}
7578
7579const NumberValue = new NumberClass();
7580
7581class StringClass extends SimpleSysCallType {
7582 constructor(...args) {
7583 var _temp3;
7584
7585 return _temp3 = super(...args), Object.defineProperty(this, "name", {
7586 configurable: true,
7587 enumerable: true,
7588 writable: true,
7589 value: 'string'
7590 }), _temp3;
7591 }
7592
7593 isOnlyType(sb, node, type) {
7594 return isOnlyString(type);
7595 }
7596
7597 isType(sb, node, type) {
7598 return isString(type);
7599 }
7600
7601 isRuntimeType(sb, node, options) {
7602 sb.emitHelper(node, options, sb.helpers.isString);
7603 }
7604
7605 handleArgument(sb, node, options, type, native = false) {
7606 if (!native) {
7607 sb.emitHelper(node, options, sb.helpers.getString);
7608 }
7609 }
7610
7611 handleResult(sb, node, options, type, native = false) {
7612 if (!native) {
7613 sb.emitHelper(node, options, sb.helpers.createString);
7614 }
7615 }
7616
7617}
7618
7619const StringValue = new StringClass();
7620
7621class BooleanClass extends SimpleSysCallType {
7622 constructor(...args) {
7623 var _temp4;
7624
7625 return _temp4 = super(...args), Object.defineProperty(this, "name", {
7626 configurable: true,
7627 enumerable: true,
7628 writable: true,
7629 value: 'boolean'
7630 }), _temp4;
7631 }
7632
7633 isOnlyType(sb, node, type) {
7634 return isOnlyBoolean(type);
7635 }
7636
7637 isType(sb, node, type) {
7638 return isBoolean(type);
7639 }
7640
7641 isRuntimeType(sb, node, options) {
7642 sb.emitHelper(node, options, sb.helpers.isBoolean);
7643 }
7644
7645 handleArgument(sb, node, options, type, native = false) {
7646 if (!native) {
7647 sb.emitHelper(node, options, sb.helpers.getBoolean);
7648 }
7649 }
7650
7651 handleResult(sb, node, options, type, native = false) {
7652 if (!native) {
7653 sb.emitHelper(node, options, sb.helpers.createBoolean);
7654 }
7655 }
7656
7657}
7658
7659const BooleanValue = new BooleanClass();
7660
7661class BlockchainInterface extends SimpleSysCallType {
7662 constructor(name) {
7663 super();
7664 Object.defineProperty(this, "name", {
7665 configurable: true,
7666 enumerable: true,
7667 writable: true,
7668 value: void 0
7669 });
7670 this.name = name;
7671 }
7672
7673 isOnlyType(sb, node, type) {
7674 return sb.isOnlyGlobal(node, type, this.name);
7675 }
7676
7677 isType(sb, node, type) {
7678 return sb.isGlobal(node, type, this.name);
7679 }
7680
7681 isRuntimeType(sb, node, options) {
7682 sb.emitHelper(node, options, sb.helpers.isBlockchainInterface({
7683 name: this.name
7684 }));
7685 }
7686
7687 handleArgument(sb, node, options, type, native = false) {
7688 if (native) {
7689 throw new Error('BlockchainInterface should not be serialized/deserialized from storage');
7690 }
7691
7692 sb.emitHelper(node, options, sb.helpers.unwrapBlockchainInterface);
7693 }
7694
7695 handleResult(sb, node, options, type, native = false) {
7696 if (native) {
7697 throw new Error('BlockchainInterface should not be serialized/deserialized from storage');
7698 }
7699
7700 sb.emitHelper(node, options, sb.helpers.wrapBlockchainInterface({
7701 name: this.name
7702 }));
7703 }
7704
7705}
7706
7707const AccountValue = new BlockchainInterface('AccountBase');
7708const AssetValue = new BlockchainInterface('AssetBase');
7709const AttributeValue = new BlockchainInterface('AttributeBase');
7710const BlockValue = new BlockchainInterface('BlockBase');
7711const ContractValue = new BlockchainInterface('ContractBase');
7712const HeaderValue = new BlockchainInterface('HeaderBase');
7713const InputValue = new BlockchainInterface('InputBase');
7714const OutputValue = new BlockchainInterface('OutputBase');
7715const TransactionValue = new BlockchainInterface('TransactionBase');
7716const ValidatorValue = new BlockchainInterface('ValidatorBase');
7717const StorageContextValue = new BlockchainInterface('StorageContextBase');
7718const StorageIteratorValue = new BlockchainInterface('StorageIteratorBase');
7719const BLOCKCHAIN_INTERFACES = [AccountValue, AssetValue, AttributeValue, BlockValue, ContractValue, HeaderValue, InputValue, OutputValue, TransactionValue, ValidatorValue, StorageContextValue, StorageIteratorValue].map(value => value.name);
7720
7721class BufferClass extends SimpleSysCallType {
7722 constructor(...args) {
7723 var _temp5;
7724
7725 return _temp5 = super(...args), Object.defineProperty(this, "name", {
7726 configurable: true,
7727 enumerable: true,
7728 writable: true,
7729 value: 'Buffer'
7730 }), _temp5;
7731 }
7732
7733 isOnlyType(sb, node, type) {
7734 return sb.isOnlyGlobal(node, type, this.name);
7735 }
7736
7737 isType(sb, node, type) {
7738 return sb.isGlobal(node, type, this.name);
7739 }
7740
7741 isRuntimeType(sb, node, options) {
7742 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
7743 property: this.name
7744 }));
7745 sb.emitHelper(node, options, sb.helpers.instanceof);
7746 }
7747
7748 handleArgument(sb, node, options, type, native = false) {
7749 sb.emitHelper(node, options, sb.helpers.unwrapBuffer);
7750
7751 if (native) {
7752 serializeType(sb, node, options, SerializableType.Buffer);
7753 }
7754 }
7755
7756 handleResult(sb, node, options, type, native = false) {
7757 if (native) {
7758 deserializeType(sb, node, options);
7759 }
7760
7761 sb.emitHelper(node, options, sb.helpers.wrapBuffer);
7762 }
7763
7764}
7765
7766const BufferValue = new BufferClass();
7767
7768class ArrayValue extends SimpleSysCallType {
7769 constructor(valueType) {
7770 super();
7771 Object.defineProperty(this, "name", {
7772 configurable: true,
7773 enumerable: true,
7774 writable: true,
7775 value: void 0
7776 });
7777 Object.defineProperty(this, "valueType", {
7778 configurable: true,
7779 enumerable: true,
7780 writable: true,
7781 value: void 0
7782 });
7783 this.name = `Array<${valueType.name}>`;
7784 this.valueType = typeof valueType === 'function' ? valueType : () => valueType;
7785 }
7786
7787 isOnlyType(sb, node, type) {
7788 return isOnlyArray(type) && !isOnlyTuple(type) && type != null && this.valueType().isOnlyType(sb, node, type.getArrayType());
7789 }
7790
7791 isType(sb, node, type) {
7792 return isArray(type) && !isTuple(type) && type != null && this.valueType().isType(sb, node, type.getArrayType());
7793 }
7794
7795 isRuntimeType(sb, node, options) {
7796 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
7797 property: 'Array'
7798 }));
7799 sb.emitHelper(node, options, sb.helpers.instanceof);
7800 }
7801
7802 handleArgument(sb, node, options, type, native = false) {
7803 sb.emitHelper(node, options, sb.helpers.unwrapArray);
7804 sb.emitHelper(node, options, sb.helpers.arrMap({
7805 map: () => {
7806 this.valueType().handleArgument(sb, node, options, type == null ? type : type.getArrayType(), native);
7807 }
7808 }));
7809
7810 if (native) {
7811 serializeType(sb, node, options, SerializableType.Array);
7812 }
7813 }
7814
7815 handleResult(sb, node, options, type, native = false) {
7816 if (native) {
7817 deserializeType(sb, node, options);
7818 }
7819
7820 sb.emitHelper(node, options, sb.helpers.arrMap({
7821 map: () => {
7822 this.valueType().handleResult(sb, node, options, type == null ? type : type.getArrayType(), native);
7823 }
7824 }));
7825 sb.emitHelper(node, options, sb.helpers.wrapArray);
7826 }
7827
7828}
7829
7830class TupleValue extends SimpleSysCallType {
7831 constructor(valueType) {
7832 super();
7833 Object.defineProperty(this, "name", {
7834 configurable: true,
7835 enumerable: true,
7836 writable: true,
7837 value: void 0
7838 });
7839 Object.defineProperty(this, "valueType", {
7840 configurable: true,
7841 enumerable: true,
7842 writable: true,
7843 value: void 0
7844 });
7845 this.name = 'any';
7846 this.valueType = typeof valueType === 'function' ? valueType : () => valueType;
7847 }
7848
7849 isOnlyType(sb, node, type) {
7850 return isOnlyTuple(type) && type != null && type.getTupleElements().every(tupleType => this.valueType().isOnlyType(sb, node, tupleType));
7851 }
7852
7853 isType(sb, node, type) {
7854 return isTuple(type) && type != null && type.getTupleElements().every(tupleType => this.valueType().isType(sb, node, tupleType));
7855 }
7856
7857 isRuntimeType(sb, node, options) {
7858 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
7859 property: 'Array'
7860 }));
7861 sb.emitHelper(node, options, sb.helpers.instanceof);
7862 }
7863
7864 handleArgument(sb, node, options, type, native = false) {
7865 throw new Error('Not Implemented');
7866 }
7867
7868 handleResult(sb, node, options, type, native = false) {
7869 if (type == null) {
7870 sb.reportError(node, 'Syscall return type must be explicitly casted to expected type.', DiagnosticCode.UNKNOWN_TYPE);
7871 } else {
7872 // [length, ...value]
7873 sb.emitOp(node, 'UNPACK'); // [...value]
7874
7875 sb.emitOp(node, 'DROP'); // [0, ...value]
7876
7877 sb.emitPushInt(node, 0); // [arr, ...value]
7878
7879 sb.emitOp(node, 'NEWARRAY');
7880
7881 for (const tupleType of type.getTupleElements()) {
7882 // [arr, arr, ...value]
7883 sb.emitOp(node, 'DUP'); // [value, arr, arr, ...value]
7884
7885 sb.emitOp(node, 'ROT'); // [val, arr, arr, ...value]
7886
7887 this.valueType().handleResult(sb, node, options, tupleType, native); // [arr, ...value]
7888
7889 sb.emitOp(node, 'APPEND');
7890 } // [arrayObjectValue]
7891
7892
7893 sb.emitHelper(node, options, sb.helpers.wrapArray);
7894 }
7895 }
7896
7897}
7898
7899class UnionValue extends SimpleSysCallType {
7900 constructor(valueTypes) {
7901 super();
7902 Object.defineProperty(this, "name", {
7903 configurable: true,
7904 enumerable: true,
7905 writable: true,
7906 value: void 0
7907 });
7908 Object.defineProperty(this, "valueTypes", {
7909 configurable: true,
7910 enumerable: true,
7911 writable: true,
7912 value: void 0
7913 });
7914 this.name = valueTypes.map(valueType => valueType.name).join(' | ');
7915 this.valueTypes = valueTypes;
7916 }
7917
7918 isOnlyType(sb, node, type) {
7919 return isUnion(type) && type != null && type.getUnionTypes().every(unionType => this.valueTypes.some(valueType => valueType.isOnlyType(sb, node, unionType))) || !isUnion(type) && type != null && this.valueTypes.some(valueType => valueType.isOnlyType(sb, node, type));
7920 }
7921
7922 isType(sb, node, type) {
7923 return isUnion(type) && type != null && type.getUnionTypes().every(unionType => this.valueTypes.some(valueType => valueType.isType(sb, node, unionType))) || !isUnion(type) && type != null && this.valueTypes.some(valueType => valueType.isType(sb, node, type));
7924 }
7925
7926 isRuntimeType(sb, node, options) {
7927 throw new Error('Union should not be checked at runtime');
7928 }
7929
7930 handleArgument(sb, node, options, type, native = false) {
7931 const foundType = this.valueTypes.find(valueType => valueType.isOnlyType(sb, node, type));
7932
7933 if (foundType == null) {
7934 if (native) {
7935 sb.emitHelper(node, options, sb.helpers.genericSerialize);
7936 } else {
7937 sb.emitHelper(node, options, sb.helpers.forType({
7938 types: this.valueTypes.map(valueType => ({
7939 isType: innerType => valueType.isType(sb, node, innerType),
7940 isRuntimeType: innerOptions => valueType.isRuntimeType(sb, node, innerOptions),
7941 process: innerOptions => valueType.handleArgument(sb, node, innerOptions, type, native)
7942 }))
7943 }));
7944 }
7945 } else {
7946 foundType.handleArgument(sb, node, options, type, native);
7947 }
7948 }
7949
7950 handleResult(sb, node, options, type, native = false) {
7951 const foundType = this.valueTypes.find(valueType => valueType.isOnlyType(sb, node, type));
7952
7953 if (foundType == null) {
7954 if (native) {
7955 sb.emitHelper(node, options, sb.helpers.genericDeserialize);
7956 } else {
7957 sb.reportError(node, 'Syscall return type must be explicitly casted to expected type.', DiagnosticCode.UNKNOWN_TYPE);
7958 }
7959 } else {
7960 foundType.handleResult(sb, node, options, type, native);
7961 }
7962 }
7963
7964}
7965
7966const StorageKey = new UnionValue([BufferValue, StringValue]);
7967const StorageValue = new UnionValue([BufferValue, NumberValue, StringValue, BooleanValue]);
7968class TypeAlias {
7969 constructor(name, declaration) {
7970 this.name = name;
7971 this.declaration = declaration;
7972 this.name = name;
7973 this.declaration = declaration;
7974 }
7975
7976 toSignature() {
7977 return this.name;
7978 }
7979
7980 toDeclaration() {
7981 return this.declaration;
7982 }
7983
7984}
7985const SerializableValueArrayAlias = new TypeAlias('SerializableValueArray', 'interface SerializableValueArray extends Array<SerializableValue> { }');
7986const SerializableValueObjectAlias = new TypeAlias('SerializableValueObject', `interface SerializableValueObject {
7987 [key: string]: SerializableValue;
7988}`);
7989const SerializableValueAlias = new TypeAlias('SerializableValue', 'type SerializableValue = undefined | number | string | boolean | Buffer | ' + `${SerializableValueArrayAlias.toSignature()} | ${SerializableValueObjectAlias.toSignature()}`);
7990
7991class Serializable extends SimpleSysCallType {
7992 constructor(shouldSerialize = false, shouldHandleNull = false) {
7993 super();
7994 this.shouldSerialize = shouldSerialize;
7995 this.shouldHandleNull = shouldHandleNull;
7996 Object.defineProperty(this, "name", {
7997 configurable: true,
7998 enumerable: true,
7999 writable: true,
8000 value: void 0
8001 });
8002 this.name = SerializableValueAlias.toSignature();
8003 }
8004
8005 get type() {
8006 return new UnionValue([BooleanValue, StringValue, NumberValue, BufferValue, new ArrayValue(() => this.type)]);
8007 }
8008
8009 toDeclaration() {
8010 return SerializableValueAlias.toDeclaration();
8011 }
8012
8013 isOnlyType(sb, node, type) {
8014 return this.type.isOnlyType(sb, node, type);
8015 }
8016
8017 isType(sb, node, type) {
8018 return this.type.isType(sb, node, type);
8019 }
8020
8021 isRuntimeType(sb, node, options) {
8022 this.type.isRuntimeType(sb, node, options);
8023 }
8024
8025 handleArgument(sb, node, options, type) {
8026 this.type.handleArgument(sb, node, options, type, true);
8027
8028 if (this.shouldSerialize) {
8029 sb.emitSysCall(node, 'Neo.Runtime.Serialize');
8030 }
8031 }
8032
8033 handleResult(sb, node, options, typeIn) {
8034 let type = typeIn;
8035
8036 if (type != null && this.shouldHandleNull && type.isUnionType() && type.getUnionTypes().some(unionType => isOnlyUndefined(unionType))) {
8037 type = type.getUnionTypes().find(unionType => !isOnlyUndefined(unionType));
8038 }
8039
8040 const handleValue = () => {
8041 if (this.shouldSerialize) {
8042 sb.emitSysCall(node, 'Neo.Runtime.Deserialize');
8043 }
8044
8045 this.type.handleResult(sb, node, options, type, true);
8046 };
8047
8048 if (this.shouldHandleNull) {
8049 sb.emitHelper(node, options, sb.helpers.if({
8050 condition: () => {
8051 // [value, value]
8052 sb.emitOp(node, 'DUP'); // [length, value]
8053
8054 sb.emitOp(node, 'SIZE'); // [0, length, value]
8055
8056 sb.emitPushInt(node, 0); // [length === 0, value]
8057
8058 sb.emitOp(node, 'NUMEQUAL');
8059 },
8060 whenTrue: () => {
8061 // []
8062 sb.emitOp(node, 'DROP'); // [val]
8063
8064 sb.emitHelper(node, options, sb.helpers.createUndefined);
8065 },
8066 whenFalse: () => {
8067 handleValue();
8068 }
8069 }));
8070 } else {
8071 handleValue();
8072 }
8073 }
8074
8075 addSerialize() {
8076 return new Serializable(true, this.shouldHandleNull);
8077 }
8078
8079 handleNull() {
8080 return new Serializable(this.shouldSerialize, true);
8081 }
8082
8083}
8084
8085const SerializableValue = new Serializable();
8086class SysCallArgument {
8087 constructor(name, type) {
8088 Object.defineProperty(this, "name", {
8089 configurable: true,
8090 enumerable: true,
8091 writable: true,
8092 value: void 0
8093 });
8094 Object.defineProperty(this, "type", {
8095 configurable: true,
8096 enumerable: true,
8097 writable: true,
8098 value: void 0
8099 });
8100 this.name = name;
8101 this.type = type;
8102 }
8103
8104 handleArgument(sb, node, options, type) {
8105 this.type.handleArgument(sb, node, options, type);
8106 }
8107
8108 toSignature() {
8109 return `${this.name}: ${this.type.toSignature()}`;
8110 }
8111
8112}
8113class SimpleSysCall {
8114 constructor(options) {
8115 Object.defineProperty(this, "name", {
8116 configurable: true,
8117 enumerable: true,
8118 writable: true,
8119 value: void 0
8120 });
8121 Object.defineProperty(this, "args", {
8122 configurable: true,
8123 enumerable: true,
8124 writable: true,
8125 value: void 0
8126 });
8127 Object.defineProperty(this, "returnType", {
8128 configurable: true,
8129 enumerable: true,
8130 writable: true,
8131 value: void 0
8132 });
8133 this.name = options.name;
8134 this.args = options.args || [];
8135 this.returnType = options.returnType || VoidValue;
8136 }
8137
8138 toDeclaration() {
8139 const args = [`name: '${this.name}'`].concat(this.args.map(arg => arg.toSignature()));
8140 return `function syscall(${args.join(', ')}): ${this.returnType.toSignature()};`;
8141 }
8142
8143 handleCall(sb, node, optionsIn) {
8144 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn));
8145 const args = [...node.getArguments().slice(1)].reverse();
8146
8147 for (const [idx, arg] of args.entries()) {
8148 sb.visit(arg, options);
8149 this.args[args.length - idx - 1].handleArgument(sb, arg, options, sb.getType(arg));
8150 }
8151
8152 sb.emitSysCall(node, this.name);
8153
8154 if (optionsIn.pushValue) {
8155 this.returnType.handleResult(sb, node, options, optionsIn.cast);
8156 } else if (this.returnType !== VoidValue) {
8157 sb.emitOp(node, 'DROP');
8158 }
8159 }
8160
8161}
8162const SYSCALLS = {
8163 'Neo.Runtime.GetTrigger': new SimpleSysCall({
8164 name: 'Neo.Runtime.GetTrigger',
8165 returnType: NumberValue
8166 }),
8167 'Neo.Runtime.CheckWitness': new SimpleSysCall({
8168 name: 'Neo.Runtime.CheckWitness',
8169 args: [new SysCallArgument('witness', BufferValue)],
8170 returnType: BooleanValue
8171 }),
8172 'Neo.Runtime.Notify': (() => {
8173 const name = 'Neo.Runtime.Notify';
8174 const valueType = new UnionValue([BufferValue, NumberValue, StringValue, BooleanValue]);
8175 const arrayType = new ArrayValue(valueType);
8176 const returnType = VoidValue;
8177 return {
8178 name,
8179
8180 toDeclaration() {
8181 const sig = arrayType.toSignature();
8182 return `function syscall(name: '${name}', ...args: ${sig}): ${returnType.toSignature()};`;
8183 },
8184
8185 handleCall(sb, node, optionsIn) {
8186 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn));
8187 const args = [...node.getArguments().slice(1)].reverse();
8188
8189 for (const arg of args) {
8190 sb.visit(arg, options);
8191 valueType.handleArgument(sb, arg, options, sb.getType(arg));
8192 } // [length, ...]
8193
8194
8195 sb.emitPushInt(node, args.length); // [arr]
8196
8197 sb.emitOp(node, 'PACK');
8198 sb.emitSysCall(node, name);
8199
8200 if (optionsIn.pushValue) {
8201 returnType.handleResult(sb, node, options, optionsIn.cast);
8202 }
8203 }
8204
8205 };
8206 })(),
8207 'Neo.Runtime.Log': new SimpleSysCall({
8208 name: 'Neo.Runtime.Log',
8209 args: [new SysCallArgument('value', StringValue)]
8210 }),
8211 'Neo.Runtime.GetTime': new SimpleSysCall({
8212 name: 'Neo.Runtime.GetTime',
8213 returnType: NumberValue
8214 }),
8215 'Neo.Runtime.Serialize': new SimpleSysCall({
8216 name: 'Neo.Runtime.Serialize',
8217 args: [new SysCallArgument('value', SerializableValue)],
8218 returnType: BufferValue
8219 }),
8220 'Neo.Runtime.Deserialize': new SimpleSysCall({
8221 name: 'Neo.Runtime.Deserialize',
8222 args: [new SysCallArgument('value', BufferValue)],
8223 returnType: SerializableValue
8224 }),
8225 'Neo.Blockchain.GetHeight': new SimpleSysCall({
8226 name: 'Neo.Blockchain.GetHeight',
8227 returnType: NumberValue
8228 }),
8229 'Neo.Blockchain.GetHeader': new SimpleSysCall({
8230 name: 'Neo.Blockchain.GetHeader',
8231 args: [new SysCallArgument('hashOrIndex', new UnionValue([BufferValue, NumberValue]))],
8232 returnType: HeaderValue
8233 }),
8234 'Neo.Blockchain.GetBlock': new SimpleSysCall({
8235 name: 'Neo.Blockchain.GetBlock',
8236 args: [new SysCallArgument('hashOrIndex', new UnionValue([BufferValue, NumberValue]))],
8237 returnType: BlockValue
8238 }),
8239 'Neo.Blockchain.GetTransaction': new SimpleSysCall({
8240 name: 'Neo.Blockchain.GetTransaction',
8241 args: [new SysCallArgument('hash', BufferValue)],
8242 returnType: TransactionValue
8243 }),
8244 'Neo.Blockchain.GetAccount': new SimpleSysCall({
8245 name: 'Neo.Blockchain.GetAccount',
8246 args: [new SysCallArgument('hash', BufferValue)],
8247 returnType: AccountValue
8248 }),
8249 'Neo.Blockchain.GetValidators': new SimpleSysCall({
8250 name: 'Neo.Blockchain.GetValidators',
8251 returnType: new ArrayValue(BufferValue)
8252 }),
8253 'Neo.Blockchain.GetAsset': new SimpleSysCall({
8254 name: 'Neo.Blockchain.GetAsset',
8255 args: [new SysCallArgument('hash', BufferValue)],
8256 returnType: AssetValue
8257 }),
8258 'Neo.Blockchain.GetContract': new SimpleSysCall({
8259 name: 'Neo.Blockchain.GetContract',
8260 args: [new SysCallArgument('hash', BufferValue)],
8261 returnType: ContractValue
8262 }),
8263 'Neo.Header.GetHash': new SimpleSysCall({
8264 name: 'Neo.Header.GetHash',
8265 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8266 returnType: BufferValue
8267 }),
8268 'Neo.Header.GetVersion': new SimpleSysCall({
8269 name: 'Neo.Header.GetVersion',
8270 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8271 returnType: NumberValue
8272 }),
8273 'Neo.Header.GetPrevHash': new SimpleSysCall({
8274 name: 'Neo.Header.GetPrevHash',
8275 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8276 returnType: BufferValue
8277 }),
8278 'Neo.Header.GetIndex': new SimpleSysCall({
8279 name: 'Neo.Header.GetIndex',
8280 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8281 returnType: NumberValue
8282 }),
8283 'Neo.Header.GetMerkleRoot': new SimpleSysCall({
8284 name: 'Neo.Header.GetMerkleRoot',
8285 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8286 returnType: BufferValue
8287 }),
8288 'Neo.Header.GetTimestamp': new SimpleSysCall({
8289 name: 'Neo.Header.GetTimestamp',
8290 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8291 returnType: NumberValue
8292 }),
8293 'Neo.Header.GetConsensusData': new SimpleSysCall({
8294 name: 'Neo.Header.GetConsensusData',
8295 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8296 returnType: NumberValue
8297 }),
8298 'Neo.Header.GetNextConsensus': new SimpleSysCall({
8299 name: 'Neo.Header.GetNextConsensus',
8300 args: [new SysCallArgument('blockOrHeader', new UnionValue([BlockValue, HeaderValue]))],
8301 returnType: BufferValue
8302 }),
8303 'Neo.Block.GetTransactionCount': new SimpleSysCall({
8304 name: 'Neo.Block.GetTransactionCount',
8305 args: [new SysCallArgument('block', BlockValue)],
8306 returnType: NumberValue
8307 }),
8308 'Neo.Block.GetTransactions': new SimpleSysCall({
8309 name: 'Neo.Block.GetTransactions',
8310 args: [new SysCallArgument('block', BlockValue)],
8311 returnType: new ArrayValue(TransactionValue)
8312 }),
8313 'Neo.Block.GetTransaction': new SimpleSysCall({
8314 name: 'Neo.Block.GetTransaction',
8315 args: [new SysCallArgument('block', BlockValue), new SysCallArgument('index', NumberValue)],
8316 returnType: TransactionValue
8317 }),
8318 'Neo.Transaction.GetHash': new SimpleSysCall({
8319 name: 'Neo.Transaction.GetHash',
8320 args: [new SysCallArgument('transaction', TransactionValue)],
8321 returnType: BufferValue
8322 }),
8323 'Neo.Transaction.GetType': new SimpleSysCall({
8324 name: 'Neo.Transaction.GetType',
8325 args: [new SysCallArgument('transaction', TransactionValue)],
8326 returnType: NumberValue
8327 }),
8328 'Neo.Transaction.GetAttributes': new SimpleSysCall({
8329 name: 'Neo.Transaction.GetAttributes',
8330 args: [new SysCallArgument('transaction', TransactionValue)],
8331 returnType: new ArrayValue(AttributeValue)
8332 }),
8333 'Neo.Transaction.GetInputs': new SimpleSysCall({
8334 name: 'Neo.Transaction.GetInputs',
8335 args: [new SysCallArgument('transaction', TransactionValue)],
8336 returnType: new ArrayValue(InputValue)
8337 }),
8338 'Neo.Transaction.GetOutputs': new SimpleSysCall({
8339 name: 'Neo.Transaction.GetOutputs',
8340 args: [new SysCallArgument('transaction', TransactionValue)],
8341 returnType: new ArrayValue(OutputValue)
8342 }),
8343 'Neo.Transaction.GetReferences': new SimpleSysCall({
8344 name: 'Neo.Transaction.GetReferences',
8345 args: [new SysCallArgument('transaction', TransactionValue)],
8346 returnType: new ArrayValue(OutputValue)
8347 }),
8348 'Neo.Transaction.GetUnspentCoins': new SimpleSysCall({
8349 name: 'Neo.Transaction.GetUnspentCoins',
8350 args: [new SysCallArgument('transaction', TransactionValue)],
8351 returnType: new ArrayValue(OutputValue)
8352 }),
8353 'Neo.InvocationTransaction.GetScript': new SimpleSysCall({
8354 name: 'Neo.InvocationTransaction.GetScript',
8355 args: [new SysCallArgument('transaction', TransactionValue)],
8356 returnType: BufferValue
8357 }),
8358 'Neo.Attribute.GetUsage': new SimpleSysCall({
8359 name: 'Neo.Attribute.GetUsage',
8360 args: [new SysCallArgument('attribute', AttributeValue)],
8361 returnType: NumberValue
8362 }),
8363 'Neo.Attribute.GetData': new SimpleSysCall({
8364 name: 'Neo.Attribute.GetData',
8365 args: [new SysCallArgument('attribute', AttributeValue)],
8366 returnType: BufferValue
8367 }),
8368 'Neo.Input.GetHash': new SimpleSysCall({
8369 name: 'Neo.Input.GetHash',
8370 args: [new SysCallArgument('input', InputValue)],
8371 returnType: BufferValue
8372 }),
8373 'Neo.Input.GetIndex': new SimpleSysCall({
8374 name: 'Neo.Input.GetIndex',
8375 args: [new SysCallArgument('input', InputValue)],
8376 returnType: NumberValue
8377 }),
8378 'Neo.Output.GetAssetId': new SimpleSysCall({
8379 name: 'Neo.Output.GetAssetId',
8380 args: [new SysCallArgument('output', OutputValue)],
8381 returnType: BufferValue
8382 }),
8383 'Neo.Output.GetValue': new SimpleSysCall({
8384 name: 'Neo.Output.GetValue',
8385 args: [new SysCallArgument('output', OutputValue)],
8386 returnType: NumberValue
8387 }),
8388 'Neo.Output.GetScriptHash': new SimpleSysCall({
8389 name: 'Neo.Output.GetScriptHash',
8390 args: [new SysCallArgument('output', OutputValue)],
8391 returnType: BufferValue
8392 }),
8393 'Neo.Account.GetScriptHash': new SimpleSysCall({
8394 name: 'Neo.Account.GetScriptHash',
8395 args: [new SysCallArgument('account', AccountValue)],
8396 returnType: BufferValue
8397 }),
8398 'Neo.Account.GetVotes': new SimpleSysCall({
8399 name: 'Neo.Account.GetVotes',
8400 args: [new SysCallArgument('account', AccountValue)],
8401 returnType: new ArrayValue(BufferValue)
8402 }),
8403 'Neo.Account.GetBalance': new SimpleSysCall({
8404 name: 'Neo.Account.GetBalance',
8405 args: [new SysCallArgument('account', AccountValue), new SysCallArgument('assetHash', BufferValue)],
8406 returnType: NumberValue
8407 }),
8408 'Neo.Asset.GetAssetId': new SimpleSysCall({
8409 name: 'Neo.Asset.GetAssetId',
8410 args: [new SysCallArgument('asset', AssetValue)],
8411 returnType: BufferValue
8412 }),
8413 'Neo.Asset.GetAssetType': new SimpleSysCall({
8414 name: 'Neo.Asset.GetAssetType',
8415 args: [new SysCallArgument('asset', AssetValue)],
8416 returnType: NumberValue
8417 }),
8418 'Neo.Asset.GetAmount': new SimpleSysCall({
8419 name: 'Neo.Asset.GetAmount',
8420 args: [new SysCallArgument('asset', AssetValue)],
8421 returnType: NumberValue
8422 }),
8423 'Neo.Asset.GetAvailable': new SimpleSysCall({
8424 name: 'Neo.Asset.GetAvailable',
8425 args: [new SysCallArgument('asset', AssetValue)],
8426 returnType: NumberValue
8427 }),
8428 'Neo.Asset.GetPrecision': new SimpleSysCall({
8429 name: 'Neo.Asset.GetPrecision',
8430 args: [new SysCallArgument('asset', AssetValue)],
8431 returnType: NumberValue
8432 }),
8433 'Neo.Asset.GetOwner': new SimpleSysCall({
8434 name: 'Neo.Asset.GetOwner',
8435 args: [new SysCallArgument('asset', AssetValue)],
8436 returnType: BufferValue
8437 }),
8438 'Neo.Asset.GetAdmin': new SimpleSysCall({
8439 name: 'Neo.Asset.GetAdmin',
8440 args: [new SysCallArgument('asset', AssetValue)],
8441 returnType: BufferValue
8442 }),
8443 'Neo.Asset.GetIssuer': new SimpleSysCall({
8444 name: 'Neo.Asset.GetIssuer',
8445 args: [new SysCallArgument('asset', AssetValue)],
8446 returnType: BufferValue
8447 }),
8448 'Neo.Contract.GetScript': new SimpleSysCall({
8449 name: 'Neo.Contract.GetScript',
8450 args: [new SysCallArgument('contract', ContractValue)],
8451 returnType: BufferValue
8452 }),
8453 'Neo.Storage.GetContext': new SimpleSysCall({
8454 name: 'Neo.Storage.GetContext',
8455 returnType: StorageContextValue
8456 }),
8457 'Neo.Storage.Get': new SimpleSysCall({
8458 name: 'Neo.Storage.Get',
8459 args: [new SysCallArgument('context', StorageContextValue), new SysCallArgument('key', StorageKey)],
8460 returnType: SerializableValue.addSerialize().handleNull()
8461 }),
8462 'Neo.Storage.Find': new SimpleSysCall({
8463 name: 'Neo.Storage.Find',
8464 args: [new SysCallArgument('context', StorageContextValue), new SysCallArgument('prefix', StorageKey)],
8465 returnType: StorageIteratorValue
8466 }),
8467 'Neo.Iterator.Next': new SimpleSysCall({
8468 name: 'Neo.Iterator.Next',
8469 args: [new SysCallArgument('iterator', StorageIteratorValue)],
8470 returnType: BooleanValue
8471 }),
8472 'Neo.Iterator.Key': new SimpleSysCall({
8473 name: 'Neo.Iterator.Key',
8474 args: [new SysCallArgument('iterator', StorageIteratorValue)],
8475 returnType: StorageKey
8476 }),
8477 'Neo.Iterator.Value': new SimpleSysCall({
8478 name: 'Neo.Iterator.Value',
8479 args: [new SysCallArgument('iterator', StorageIteratorValue)],
8480 returnType: StorageValue
8481 }),
8482 'Neo.Account.SetVotes': new SimpleSysCall({
8483 name: 'Neo.Account.SetVotes',
8484 args: [new SysCallArgument('account', AccountValue), new SysCallArgument('votes', new ArrayValue(BufferValue))]
8485 }),
8486 'Neo.Validator.Register': new SimpleSysCall({
8487 name: 'Neo.Validator.Register',
8488 args: [new SysCallArgument('publicKey', BufferValue)],
8489 returnType: ValidatorValue
8490 }),
8491 'Neo.Asset.Create': new SimpleSysCall({
8492 name: 'Neo.Asset.Create',
8493 args: [new SysCallArgument('assetType', NumberValue), new SysCallArgument('assetName', StringValue), new SysCallArgument('amount', NumberValue), new SysCallArgument('precision', NumberValue), new SysCallArgument('owner', BufferValue), new SysCallArgument('admin', BufferValue), new SysCallArgument('issuer', BufferValue)],
8494 returnType: AssetValue
8495 }),
8496 'Neo.Asset.Renew': new SimpleSysCall({
8497 name: 'Neo.Asset.Renew',
8498 args: [new SysCallArgument('asset', AssetValue), new SysCallArgument('years', NumberValue)],
8499 returnType: NumberValue
8500 }),
8501 'Neo.Contract.Create': new SimpleSysCall({
8502 name: 'Neo.Contract.Create',
8503 args: [new SysCallArgument('script', BufferValue), new SysCallArgument('parameterList', BufferValue), new SysCallArgument('returnType', NumberValue), new SysCallArgument('properties', NumberValue), new SysCallArgument('contractName', StringValue), new SysCallArgument('codeVersion', StringValue), new SysCallArgument('author', StringValue), new SysCallArgument('email', StringValue), new SysCallArgument('description', StringValue)],
8504 returnType: ContractValue
8505 }),
8506 'Neo.Contract.Migrate': new SimpleSysCall({
8507 name: 'Neo.Contract.Migrate',
8508 args: [new SysCallArgument('script', BufferValue), new SysCallArgument('parameterList', BufferValue), new SysCallArgument('returnType', NumberValue), new SysCallArgument('properties', NumberValue), new SysCallArgument('contractName', StringValue), new SysCallArgument('codeVersion', StringValue), new SysCallArgument('author', StringValue), new SysCallArgument('email', StringValue), new SysCallArgument('description', StringValue)],
8509 returnType: ContractValue
8510 }),
8511 'Neo.Contract.GetStorageContext': new SimpleSysCall({
8512 name: 'Neo.Contract.GetStorageContext',
8513 args: [new SysCallArgument('contract', ContractValue)],
8514 returnType: StorageContextValue
8515 }),
8516 'Neo.Contract.Destroy': new SimpleSysCall({
8517 name: 'Neo.Contract.Destroy'
8518 }),
8519 'Neo.Storage.Put': new SimpleSysCall({
8520 name: 'Neo.Storage.Put',
8521 args: [new SysCallArgument('context', StorageContextValue), new SysCallArgument('key', StorageKey), new SysCallArgument('value', SerializableValue.addSerialize())]
8522 }),
8523 'Neo.Storage.Delete': new SimpleSysCall({
8524 name: 'Neo.Storage.Delete',
8525 args: [new SysCallArgument('context', StorageContextValue), new SysCallArgument('key', StorageKey)]
8526 }),
8527 'System.ExecutionEngine.GetScriptContainer': new SimpleSysCall({
8528 name: 'System.ExecutionEngine.GetScriptContainer',
8529 returnType: TransactionValue
8530 }),
8531 'System.ExecutionEngine.GetExecutingScriptHash': new SimpleSysCall({
8532 name: 'System.ExecutionEngine.GetExecutingScriptHash',
8533 returnType: BufferValue
8534 }),
8535 'System.ExecutionEngine.GetCallingScriptHash': new SimpleSysCall({
8536 name: 'System.ExecutionEngine.GetCallingScriptHash',
8537 returnType: BufferValue
8538 }),
8539 'System.ExecutionEngine.GetEntryScriptHash': new SimpleSysCall({
8540 name: 'System.ExecutionEngine.GetEntryScriptHash',
8541 returnType: BufferValue
8542 }),
8543 'Neo.Runtime.Return': (() => {
8544 const name = 'Neo.Runtime.Return';
8545 const valueType = new UnionValue([BufferValue, NumberValue, StringValue, BooleanValue]);
8546 const returnType = VoidValue;
8547 return {
8548 name,
8549
8550 toDeclaration() {
8551 const sig = valueType.toSignature();
8552 return `function syscall(name: '${name}', value: ${sig}): ${returnType.toSignature()};`;
8553 },
8554
8555 handleCall(sb, node, optionsIn) {
8556 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn));
8557 const arg = node.getArguments()[1];
8558 sb.visit(arg, options);
8559 valueType.handleArgument(sb, arg, options, sb.getType(arg));
8560 }
8561
8562 };
8563 })(),
8564 'Neo.Runtime.GetArgument': (() => {
8565 const name = 'Neo.Runtime.GetArgument';
8566 const valueType = NumberValue;
8567 const returnType = new UnionValue([BufferValue, BooleanValue, NumberValue, StringValue, new ArrayValue(() => returnType), new TupleValue(() => returnType)]);
8568 return {
8569 name,
8570
8571 toDeclaration() {
8572 const sig = valueType.toSignature();
8573 return `function syscall(name: '${name}', idx: ${sig}): any;`;
8574 },
8575
8576 handleCall(sb, node, optionsIn) {
8577 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn));
8578 const arg = node.getArguments()[1];
8579 sb.visit(arg, options);
8580 sb.emitHelper(arg, options, sb.helpers.getArgument({
8581 type: sb.getType(arg)
8582 }));
8583
8584 if (optionsIn.pushValue) {
8585 returnType.handleResult(sb, node, optionsIn, optionsIn.cast);
8586 } else {
8587 sb.emitOp(node, 'DROP');
8588 }
8589 }
8590
8591 };
8592 })()
8593};
8594
8595class CallExpressionCompiler extends NodeCompiler {
8596 constructor(...args) {
8597 var _temp;
8598
8599 return _temp = super(...args), Object.defineProperty(this, "kind", {
8600 configurable: true,
8601 enumerable: true,
8602 writable: true,
8603 value: Ast.SyntaxKind.CallExpression
8604 }), _temp;
8605 }
8606
8607 visitNode(sb, expr, optionsIn) {
8608 const func = expr.getExpression();
8609
8610 if (Ast.TypeGuards.isIdentifier(func) && sb.isGlobalSymbol(func, sb.getSymbol(func), 'syscall')) {
8611 this.handleSysCall(sb, expr, optionsIn);
8612 return;
8613 }
8614
8615 const options = sb.pushValueOptions(sb.noCastOptions(optionsIn)); // [argsarr]
8616
8617 sb.emitHelper(expr, options, sb.helpers.args);
8618
8619 if (Ast.TypeGuards.isSuperExpression(func)) {
8620 this.handleSuperConstruct(sb, expr, options);
8621 return;
8622 }
8623
8624 let bindThis;
8625
8626 if (Ast.TypeGuards.isElementAccessExpression(func) || Ast.TypeGuards.isPropertyAccessExpression(func)) {
8627 bindThis = true;
8628 const lhs = func.getExpression();
8629
8630 if (Ast.TypeGuards.isSuperExpression(lhs)) {
8631 // [thisValue, argsarr]
8632 sb.scope.getThis(sb, lhs, options); // [superPrototype, thisValue, argsarr]
8633
8634 sb.visit(lhs, options);
8635 } else {
8636 // [expr, argsarr]
8637 sb.visit(lhs, options); // [expr, expr, argsarr]
8638
8639 sb.emitOp(func, 'DUP');
8640 }
8641
8642 if (Ast.TypeGuards.isElementAccessExpression(func)) {
8643 // [objectVal, expr, argsarr]
8644 sb.emitHelper(func, options, sb.helpers.elementAccess);
8645 } else {
8646 // [name, expr, expr, argsarr]
8647 sb.emitPushString(func.getNameNode(), func.getName()); // [objectVal, expr, argsarr]
8648
8649 sb.emitHelper(expr, options, sb.helpers.getPropertyObjectProperty);
8650 }
8651 } else {
8652 bindThis = false; // [objectVal, argsarr]
8653
8654 sb.visit(func, options);
8655 }
8656
8657 sb.emitHelper(expr, options, sb.helpers.invokeCall({
8658 bindThis
8659 }));
8660
8661 if (!optionsIn.pushValue) {
8662 sb.emitOp(expr, 'DROP');
8663 }
8664 }
8665
8666 handleSysCall(sb, node, options) {
8667 const sysCallName = node.getArguments()[0];
8668
8669 const reportError = () => {
8670 sb.reportError(node, 'First argument to syscall must be a string literal corresponding to a NEO syscall.', DiagnosticCode.INVALID_SYS_CALL);
8671 };
8672
8673 if (sysCallName == null || !Ast.TypeGuards.isStringLiteral(sysCallName)) {
8674 reportError();
8675 return;
8676 }
8677
8678 const sysCallKey = sysCallName.getLiteralValue();
8679 const sysCall = SYSCALLS[sysCallKey];
8680
8681 if (sysCall == null) {
8682 reportError();
8683 } else {
8684 sysCall.handleCall(sb, node, options);
8685 }
8686 }
8687
8688 handleSuperConstruct(sb, node, options) {
8689 const superClass = options.superClass;
8690
8691 if (superClass == null) {
8692 throw new Error('Something went wrong, expected super class to be defined.');
8693 } // [thisValue, argsarr]
8694
8695
8696 sb.scope.getThis(sb, node, options); // [ctor, thisValue, argsarr]
8697
8698 sb.scope.get(sb, node, options, superClass); // []
8699
8700 sb.emitHelper(node, options, sb.helpers.invokeConstruct());
8701 }
8702
8703}
8704
8705class CommaListExpressionCompiler extends NodeCompiler {
8706 constructor(...args) {
8707 var _temp;
8708
8709 return _temp = super(...args), Object.defineProperty(this, "kind", {
8710 configurable: true,
8711 enumerable: true,
8712 writable: true,
8713 value: Ast.SyntaxKind.CommaListExpression
8714 }), _temp;
8715 }
8716
8717 visitNode(sb, expr, options) {
8718 // TODO: What is this??
8719 sb.reportUnsupported(expr);
8720 }
8721
8722}
8723
8724class ConditionalExpressionCompiler extends NodeCompiler {
8725 constructor(...args) {
8726 var _temp;
8727
8728 return _temp = super(...args), Object.defineProperty(this, "kind", {
8729 configurable: true,
8730 enumerable: true,
8731 writable: true,
8732 value: Ast.SyntaxKind.ConditionalExpression
8733 }), _temp;
8734 }
8735
8736 visitNode(sb, expr, options) {
8737 sb.emitHelper(expr, options, sb.helpers.if({
8738 condition: () => {
8739 // [val]
8740 sb.visit(expr.getCondition(), sb.pushValueOptions(options)); // [boolean]
8741
8742 sb.emitHelper(expr.getCondition(), sb.pushValueOptions(options), sb.helpers.toBoolean({
8743 type: sb.getType(expr.getCondition())
8744 }));
8745 },
8746 whenTrue: () => {
8747 sb.visit(expr.getWhenTrue(), options);
8748 },
8749 whenFalse: () => {
8750 sb.visit(expr.getWhenFalse(), options);
8751 }
8752 }));
8753 }
8754
8755}
8756
8757class DeleteExpressionCompiler extends NodeCompiler {
8758 constructor(...args) {
8759 var _temp;
8760
8761 return _temp = super(...args), Object.defineProperty(this, "kind", {
8762 configurable: true,
8763 enumerable: true,
8764 writable: true,
8765 value: Ast.SyntaxKind.DeleteExpression
8766 }), _temp;
8767 }
8768
8769 visitNode(sb, expr, options) {
8770 sb.reportUnsupported(expr);
8771 }
8772
8773}
8774
8775class ElementAccessExpressionCompiler extends NodeCompiler {
8776 constructor(...args) {
8777 var _temp;
8778
8779 return _temp = super(...args), Object.defineProperty(this, "kind", {
8780 configurable: true,
8781 enumerable: true,
8782 writable: true,
8783 value: Ast.SyntaxKind.ElementAccessExpression
8784 }), _temp;
8785 }
8786
8787 visitNode(sb, expr, options) {
8788 const value = expr.getExpression(); // [val]
8789
8790 sb.visit(value, sb.pushValueOptions(sb.noSetValueOptions(options))); // [val]
8791
8792 sb.emitHelper(expr, options, sb.helpers.elementAccess);
8793 }
8794
8795}
8796
8797class FunctionExpressionCompiler extends NodeCompiler {
8798 constructor(...args) {
8799 var _temp;
8800
8801 return _temp = super(...args), Object.defineProperty(this, "kind", {
8802 configurable: true,
8803 enumerable: true,
8804 writable: true,
8805 value: Ast.SyntaxKind.FunctionExpression
8806 }), _temp;
8807 }
8808
8809 visitNode(sb, expr, options) {
8810 sb.reportUnsupported(expr);
8811 }
8812
8813}
8814
8815class IdentifierCompiler extends NodeCompiler {
8816 constructor(...args) {
8817 var _temp;
8818
8819 return _temp = super(...args), Object.defineProperty(this, "kind", {
8820 configurable: true,
8821 enumerable: true,
8822 writable: true,
8823 value: Ast.SyntaxKind.Identifier
8824 }), _temp;
8825 }
8826
8827 visitNode(sb, expr, options) {
8828 if (options.setValue) {
8829 sb.scope.set(sb, expr, sb.noSetValueOptions(options), expr.getText());
8830 }
8831
8832 if (options.pushValue) {
8833 if (expr.compilerNode.originalKeywordKind != null && expr.compilerNode.originalKeywordKind === Ast.SyntaxKind.UndefinedKeyword) {
8834 sb.emitHelper(expr, options, sb.helpers.createUndefined);
8835 } else {
8836 sb.scope.get(sb, expr, options, expr.getText());
8837 }
8838 }
8839 }
8840
8841}
8842
8843class ImportExpressionCompiler extends NodeCompiler {
8844 constructor(...args) {
8845 var _temp;
8846
8847 return _temp = super(...args), Object.defineProperty(this, "kind", {
8848 configurable: true,
8849 enumerable: true,
8850 writable: true,
8851 value: Ast.SyntaxKind.ImportKeyword
8852 }), _temp;
8853 }
8854
8855 visitNode(sb, expr, options) {
8856 sb.reportUnsupported(expr);
8857 }
8858
8859}
8860
8861class MetaPropertyCompiler extends NodeCompiler {
8862 constructor(...args) {
8863 var _temp;
8864
8865 return _temp = super(...args), Object.defineProperty(this, "kind", {
8866 configurable: true,
8867 enumerable: true,
8868 writable: true,
8869 value: Ast.SyntaxKind.MetaProperty
8870 }), _temp;
8871 }
8872
8873 visitNode(sb, expr, options) {
8874 sb.reportUnsupported(expr);
8875 }
8876
8877}
8878
8879class NewExpressionCompiler extends NodeCompiler {
8880 constructor(...args) {
8881 var _temp;
8882
8883 return _temp = super(...args), Object.defineProperty(this, "kind", {
8884 configurable: true,
8885 enumerable: true,
8886 writable: true,
8887 value: Ast.SyntaxKind.NewExpression
8888 }), _temp;
8889 }
8890
8891 visitNode(sb, expr, optionsIn) {
8892 const options = sb.pushValueOptions(optionsIn); // [argsarr]
8893
8894 sb.emitHelper(expr, options, sb.helpers.args); // [objectVal, argsarr]
8895
8896 sb.visit(expr.getExpression(), options); // [thisVal]
8897
8898 sb.emitHelper(expr, options, sb.helpers.new());
8899 }
8900
8901}
8902
8903class NonNullExpressionCompiler extends NodeCompiler {
8904 constructor(...args) {
8905 var _temp;
8906
8907 return _temp = super(...args), Object.defineProperty(this, "kind", {
8908 configurable: true,
8909 enumerable: true,
8910 writable: true,
8911 value: Ast.SyntaxKind.NonNullExpression
8912 }), _temp;
8913 }
8914
8915 visitNode(sb, expr, options) {
8916 sb.reportUnsupported(expr);
8917 }
8918
8919}
8920
8921class NoSubstitutionTemplateLiteralCompiler extends NodeCompiler {
8922 constructor(...args) {
8923 var _temp;
8924
8925 return _temp = super(...args), Object.defineProperty(this, "kind", {
8926 configurable: true,
8927 enumerable: true,
8928 writable: true,
8929 value: Ast.SyntaxKind.NoSubstitutionTemplateLiteral
8930 }), _temp;
8931 }
8932
8933 visitNode(sb, expr, options) {
8934 sb.reportUnsupported(expr);
8935 }
8936
8937}
8938
8939class NullLiteralCompiler extends NodeCompiler {
8940 constructor(...args) {
8941 var _temp;
8942
8943 return _temp = super(...args), Object.defineProperty(this, "kind", {
8944 configurable: true,
8945 enumerable: true,
8946 writable: true,
8947 value: Ast.SyntaxKind.NullKeyword
8948 }), _temp;
8949 }
8950
8951 visitNode(sb, expr, options) {
8952 if (options.pushValue) {
8953 sb.emitHelper(expr, options, sb.helpers.createNull);
8954 }
8955 }
8956
8957}
8958
8959class NumericLiteralCompiler extends NodeCompiler {
8960 constructor(...args) {
8961 var _temp;
8962
8963 return _temp = super(...args), Object.defineProperty(this, "kind", {
8964 configurable: true,
8965 enumerable: true,
8966 writable: true,
8967 value: Ast.SyntaxKind.NumericLiteral
8968 }), _temp;
8969 }
8970
8971 visitNode(sb, expr, options) {
8972 if (options.pushValue) {
8973 sb.emitPushInt(expr, expr.getLiteralValue());
8974 sb.emitHelper(expr, options, sb.helpers.createNumber);
8975 }
8976 }
8977
8978}
8979
8980class ObjectLiteralExpressionCompiler extends NodeCompiler {
8981 constructor(...args) {
8982 var _temp;
8983
8984 return _temp = super(...args), Object.defineProperty(this, "kind", {
8985 configurable: true,
8986 enumerable: true,
8987 writable: true,
8988 value: Ast.SyntaxKind.ObjectLiteralExpression
8989 }), _temp;
8990 }
8991
8992 visitNode(sb, node, optionsIn) {
8993 const options = sb.pushValueOptions(optionsIn); // [objectVal]
8994
8995 sb.emitHelper(node, options, sb.helpers.createObject);
8996 node.getProperties().forEach(prop => {
8997 // [objectVal, objectVal]
8998 sb.emitOp(node, 'DUP');
8999
9000 if (Ast.TypeGuards.isPropertyAssignment(prop) || Ast.TypeGuards.isShorthandPropertyAssignment(prop) || Ast.TypeGuards.isMethodDeclaration(prop)) {
9001 // [propString, objectVal, objectVal]
9002 sb.emitPushString(prop, prop.getName());
9003
9004 if (Ast.TypeGuards.isPropertyAssignment(prop)) {
9005 // [val, propString, objectVal, objectVal]
9006 sb.visit(prop.getInitializerOrThrow(), options);
9007 } else if (Ast.TypeGuards.isShorthandPropertyAssignment(prop)) {
9008 // [val, propString, objectVal, objectVal]
9009 sb.visit(prop.getNameNode(), options);
9010 } else if (Ast.TypeGuards.isMethodDeclaration(prop)) {
9011 // [callArr, propString, objectVal, objectVal]
9012 sb.emitHelper(prop, options, sb.helpers.createCallArray); // [callObj, propString, objectVal, objectVal]
9013
9014 sb.emitHelper(prop, options, sb.helpers.createFunctionObject({
9015 property: InternalFunctionProperties.CALL
9016 }));
9017 } else {
9018 // TODO: Support get/set accessors
9019 sb.reportUnsupported(prop);
9020 } // [objectVal]
9021
9022
9023 sb.emitHelper(prop, options, sb.helpers.setDataPropertyObjectProperty);
9024 } else {
9025 sb.reportUnsupported(prop);
9026 }
9027 });
9028
9029 if (!optionsIn.pushValue) {
9030 sb.emitOp(node, 'DROP');
9031 }
9032 }
9033
9034}
9035
9036class OmittedExpressionCompiler extends NodeCompiler {
9037 constructor(...args) {
9038 var _temp;
9039
9040 return _temp = super(...args), Object.defineProperty(this, "kind", {
9041 configurable: true,
9042 enumerable: true,
9043 writable: true,
9044 value: Ast.SyntaxKind.OmittedExpression
9045 }), _temp;
9046 }
9047
9048 visitNode(sb, expr, options) {
9049 sb.reportUnsupported(expr);
9050 }
9051
9052}
9053
9054class ParenthesizedExpressionCompiler extends NodeCompiler {
9055 constructor(...args) {
9056 var _temp;
9057
9058 return _temp = super(...args), Object.defineProperty(this, "kind", {
9059 configurable: true,
9060 enumerable: true,
9061 writable: true,
9062 value: Ast.SyntaxKind.ParenthesizedExpression
9063 }), _temp;
9064 }
9065
9066 visitNode(sb, expr, options) {
9067 sb.visit(expr.getExpression(), options);
9068 }
9069
9070}
9071
9072class PartiallyEmittedExpressionCompiler extends NodeCompiler {
9073 constructor(...args) {
9074 var _temp;
9075
9076 return _temp = super(...args), Object.defineProperty(this, "kind", {
9077 configurable: true,
9078 enumerable: true,
9079 writable: true,
9080 value: Ast.SyntaxKind.PartiallyEmittedExpression
9081 }), _temp;
9082 }
9083
9084 visitNode(sb, expr, options) {
9085 sb.reportUnsupported(expr);
9086 }
9087
9088}
9089
9090class PostfixUnaryExpressionCompiler extends NodeCompiler {
9091 constructor(...args) {
9092 var _temp;
9093
9094 return _temp = super(...args), Object.defineProperty(this, "kind", {
9095 configurable: true,
9096 enumerable: true,
9097 writable: true,
9098 value: Ast.SyntaxKind.PostfixUnaryExpression
9099 }), _temp;
9100 }
9101
9102 visitNode(sb, expr, options) {
9103 sb.visit(expr.getOperand(), sb.noSetValueOptions(sb.pushValueOptions(options)));
9104 const token = expr.getOperatorToken();
9105
9106 switch (token) {
9107 case Ast.SyntaxKind.PlusPlusToken:
9108 case Ast.SyntaxKind.MinusMinusToken:
9109 this.visitAssignment(sb, token, expr, options);
9110 break;
9111
9112 default:
9113 sb.assertUnreachable(token);
9114 }
9115 }
9116
9117 visitAssignment(sb, token, expr, options) {
9118 if (options.pushValue) {
9119 sb.emitOp(expr, 'DUP');
9120 }
9121
9122 switch (token) {
9123 case Ast.SyntaxKind.PlusPlusToken:
9124 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.toNumber({
9125 type: sb.getType(expr)
9126 }));
9127 sb.emitOp(expr, 'INC');
9128 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.createNumber);
9129 break;
9130
9131 case Ast.SyntaxKind.MinusMinusToken:
9132 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.toNumber({
9133 type: sb.getType(expr)
9134 }));
9135 sb.emitOp(expr, 'DEC');
9136 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.createNumber);
9137 break;
9138
9139 default:
9140 sb.assertUnreachable(token);
9141 }
9142
9143 sb.visit(expr.getOperand(), sb.noPushValueOptions(sb.setValueOptions(options)));
9144 }
9145
9146}
9147
9148class PrefixUnaryExpressionCompiler extends NodeCompiler {
9149 constructor(...args) {
9150 var _temp;
9151
9152 return _temp = super(...args), Object.defineProperty(this, "kind", {
9153 configurable: true,
9154 enumerable: true,
9155 writable: true,
9156 value: Ast.SyntaxKind.PrefixUnaryExpression
9157 }), _temp;
9158 }
9159
9160 visitNode(sb, expr, options) {
9161 const token = expr.getOperatorToken();
9162
9163 switch (token) {
9164 case Ast.SyntaxKind.PlusPlusToken:
9165 case Ast.SyntaxKind.MinusMinusToken:
9166 this.visitAssignment(sb, token, expr, options);
9167 break;
9168
9169 case Ast.SyntaxKind.PlusToken:
9170 case Ast.SyntaxKind.MinusToken:
9171 case Ast.SyntaxKind.TildeToken:
9172 case Ast.SyntaxKind.ExclamationToken:
9173 this.visitValue(sb, token, expr, options);
9174 break;
9175
9176 default:
9177 sb.assertUnreachable(token);
9178 }
9179 }
9180
9181 visitAssignment(sb, token, expr, options) {
9182 sb.visit(expr.getOperand(), sb.noSetValueOptions(sb.pushValueOptions(options)));
9183
9184 switch (token) {
9185 case Ast.SyntaxKind.PlusPlusToken:
9186 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.toNumber({
9187 type: sb.getType(expr)
9188 }));
9189 sb.emitOp(expr, 'INC');
9190 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.createNumber);
9191 break;
9192
9193 case Ast.SyntaxKind.MinusMinusToken:
9194 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.toNumber({
9195 type: sb.getType(expr)
9196 }));
9197 sb.emitOp(expr, 'DEC');
9198 sb.emitHelper(expr, sb.pushValueOptions(options), sb.helpers.createNumber);
9199 break;
9200
9201 default:
9202 sb.assertUnreachable(token);
9203 }
9204
9205 sb.visit(expr.getOperand(), sb.setValueOptions(options));
9206 }
9207
9208 visitValue(sb, token, expr, options) {
9209 const operand = expr.getOperand();
9210 sb.visit(operand, sb.noSetValueOptions(sb.pushValueOptions(options)));
9211
9212 if (!options.pushValue) {
9213 sb.emitOp(expr, 'DROP');
9214 return;
9215 }
9216
9217 switch (token) {
9218 case Ast.SyntaxKind.PlusToken:
9219 sb.emitHelper(expr, options, sb.helpers.toNumber({
9220 type: sb.getType(expr)
9221 }));
9222 sb.emitHelper(expr, options, sb.helpers.createNumber);
9223 break;
9224
9225 case Ast.SyntaxKind.MinusToken:
9226 sb.emitHelper(expr, options, sb.helpers.toNumber({
9227 type: sb.getType(expr)
9228 }));
9229 sb.emitOp(expr, 'NEGATE');
9230 sb.emitHelper(expr, options, sb.helpers.createNumber);
9231 break;
9232
9233 case Ast.SyntaxKind.TildeToken:
9234 sb.emitHelper(expr, options, sb.helpers.toNumber({
9235 type: sb.getType(expr)
9236 }));
9237 sb.emitOp(expr, 'INVERT');
9238 sb.emitHelper(expr, options, sb.helpers.createNumber);
9239 break;
9240
9241 case Ast.SyntaxKind.ExclamationToken:
9242 sb.emitHelper(operand, options, sb.helpers.toBoolean({
9243 type: sb.getType(operand)
9244 }));
9245 sb.emitOp(expr, 'NOT');
9246 sb.emitHelper(operand, options, sb.helpers.createBoolean);
9247 break;
9248
9249 default:
9250 sb.assertUnreachable(token);
9251 }
9252 }
9253
9254}
9255
9256class PropertyAccessExpressionCompiler extends NodeCompiler {
9257 constructor(...args) {
9258 var _temp;
9259
9260 return _temp = super(...args), Object.defineProperty(this, "kind", {
9261 configurable: true,
9262 enumerable: true,
9263 writable: true,
9264 value: Ast.SyntaxKind.PropertyAccessExpression
9265 }), _temp;
9266 }
9267
9268 visitNode(sb, expr, optionsIn) {
9269 const options = sb.pushValueOptions(sb.noSetValueOptions(optionsIn));
9270 const expression = expr.getExpression(); // [val]
9271
9272 sb.visit(expression, options); // [objectVal]
9273
9274 sb.emitHelper(expression, options, sb.helpers.toObject({
9275 type: sb.getType(expression)
9276 }));
9277
9278 if (optionsIn.setValue) {
9279 if (optionsIn.pushValue) {
9280 // [objectVal, value, objectVal]
9281 sb.emitOp(expression, 'TUCK');
9282 } // [name, objectVal, value, objectVal]
9283
9284
9285 sb.emitPushString(expr, expr.getName()); // [value, name, objectVal, objectVal]
9286
9287 sb.emitOp(expr, 'ROT'); // [objectVal]
9288
9289 sb.emitHelper(expr, options, sb.helpers.setPropertyObjectProperty);
9290 }
9291
9292 if (optionsIn.pushValue || !optionsIn.setValue) {
9293 // [name, objectVal]
9294 sb.emitPushString(expr, expr.getName()); // [value]
9295
9296 sb.emitHelper(expr, options, sb.helpers.getPropertyObjectProperty);
9297
9298 if (!optionsIn.pushValue) {
9299 sb.emitOp(expr, 'DROP');
9300 }
9301 }
9302 }
9303
9304}
9305
9306class RegularExpressionLiteralCompiler extends NodeCompiler {
9307 constructor(...args) {
9308 var _temp;
9309
9310 return _temp = super(...args), Object.defineProperty(this, "kind", {
9311 configurable: true,
9312 enumerable: true,
9313 writable: true,
9314 value: Ast.SyntaxKind.RegularExpressionLiteral
9315 }), _temp;
9316 }
9317
9318 visitNode(sb, expr, options) {
9319 sb.reportUnsupported(expr);
9320 }
9321
9322}
9323
9324class SpreadElementCompiler extends NodeCompiler {
9325 constructor(...args) {
9326 var _temp;
9327
9328 return _temp = super(...args), Object.defineProperty(this, "kind", {
9329 configurable: true,
9330 enumerable: true,
9331 writable: true,
9332 value: Ast.SyntaxKind.SpreadElement
9333 }), _temp;
9334 }
9335
9336 visitNode(sb, expr, options) {
9337 sb.reportUnsupported(expr);
9338 }
9339
9340}
9341
9342class StringLiteralCompiler extends NodeCompiler {
9343 constructor(...args) {
9344 var _temp;
9345
9346 return _temp = super(...args), Object.defineProperty(this, "kind", {
9347 configurable: true,
9348 enumerable: true,
9349 writable: true,
9350 value: Ast.SyntaxKind.StringLiteral
9351 }), _temp;
9352 }
9353
9354 visitNode(sb, expr, options) {
9355 if (options.pushValue) {
9356 sb.emitPushString(expr, expr.getLiteralValue());
9357 sb.emitHelper(expr, options, sb.helpers.createString);
9358 }
9359 }
9360
9361}
9362
9363class SuperExpressionCompiler extends NodeCompiler {
9364 constructor(...args) {
9365 var _temp;
9366
9367 return _temp = super(...args), Object.defineProperty(this, "kind", {
9368 configurable: true,
9369 enumerable: true,
9370 writable: true,
9371 value: Ast.SyntaxKind.SuperKeyword
9372 }), _temp;
9373 }
9374
9375 visitNode(sb, expr, options) {
9376 if (options.pushValue) {
9377 const superClass = options.superClass;
9378
9379 if (superClass == null) {
9380 throw new Error('Something went wrong, expected super class to be defined.');
9381 } // [superClass]
9382
9383
9384 sb.scope.get(sb, expr, options, superClass); // ['prototype', superClass]
9385
9386 sb.emitPushString(expr, 'prototype'); // [superPrototype]
9387
9388 sb.emitHelper(expr, options, sb.helpers.getPropertyObjectProperty);
9389 }
9390 }
9391
9392}
9393
9394class TaggedTemplateExpressionCompiler extends NodeCompiler {
9395 constructor(...args) {
9396 var _temp;
9397
9398 return _temp = super(...args), Object.defineProperty(this, "kind", {
9399 configurable: true,
9400 enumerable: true,
9401 writable: true,
9402 value: Ast.SyntaxKind.TaggedTemplateExpression
9403 }), _temp;
9404 }
9405
9406 visitNode(sb, expr, options) {
9407 sb.reportUnsupported(expr);
9408 }
9409
9410}
9411
9412class ThisExpressionCompiler extends NodeCompiler {
9413 constructor(...args) {
9414 var _temp;
9415
9416 return _temp = super(...args), Object.defineProperty(this, "kind", {
9417 configurable: true,
9418 enumerable: true,
9419 writable: true,
9420 value: Ast.SyntaxKind.ThisKeyword
9421 }), _temp;
9422 }
9423
9424 visitNode(sb, expr, options) {
9425 if (options.pushValue) {
9426 sb.scope.getThis(sb, expr, options);
9427 }
9428 }
9429
9430}
9431
9432class TypeAssertionCompiler extends NodeCompiler {
9433 constructor(...args) {
9434 var _temp;
9435
9436 return _temp = super(...args), Object.defineProperty(this, "kind", {
9437 configurable: true,
9438 enumerable: true,
9439 writable: true,
9440 value: Ast.SyntaxKind.TypeAssertionExpression
9441 }), _temp;
9442 }
9443
9444 visitNode(sb, expr, options) {
9445 sb.reportUnsupported(expr);
9446 }
9447
9448}
9449
9450class TypeOfExpressionCompiler extends NodeCompiler {
9451 constructor(...args) {
9452 var _temp;
9453
9454 return _temp = super(...args), Object.defineProperty(this, "kind", {
9455 configurable: true,
9456 enumerable: true,
9457 writable: true,
9458 value: Ast.SyntaxKind.TypeOfExpression
9459 }), _temp;
9460 }
9461
9462 visitNode(sb, expr, options) {
9463 sb.reportUnsupported(expr);
9464 }
9465
9466}
9467
9468class VoidExpressionCompiler extends NodeCompiler {
9469 constructor(...args) {
9470 var _temp;
9471
9472 return _temp = super(...args), Object.defineProperty(this, "kind", {
9473 configurable: true,
9474 enumerable: true,
9475 writable: true,
9476 value: Ast.SyntaxKind.VoidExpression
9477 }), _temp;
9478 }
9479
9480 visitNode(sb, expr, options) {
9481 if (options.pushValue) {
9482 sb.emitHelper(expr, options, sb.helpers.createUndefined);
9483 }
9484 }
9485
9486}
9487
9488class YieldExpressionCompiler extends NodeCompiler {
9489 constructor(...args) {
9490 var _temp;
9491
9492 return _temp = super(...args), Object.defineProperty(this, "kind", {
9493 configurable: true,
9494 enumerable: true,
9495 writable: true,
9496 value: Ast.SyntaxKind.YieldExpression
9497 }), _temp;
9498 }
9499
9500 visitNode(sb, expr, options) {
9501 sb.reportUnsupported(expr);
9502 }
9503
9504}
9505
9506var expression = [ArrayLiteralExpressionCompiler, ArrowFunctionCompiler, AsExpressionCompiler, AwaitExpressionCompiler, BinaryExpressionCompiler, TrueBooleanLiteralCompiler, FalseBooleanLiteralCompiler, CallExpressionCompiler, CommaListExpressionCompiler, ConditionalExpressionCompiler, DeleteExpressionCompiler, ElementAccessExpressionCompiler, FunctionExpressionCompiler, IdentifierCompiler, ImportExpressionCompiler, MetaPropertyCompiler, NewExpressionCompiler, NonNullExpressionCompiler, NoSubstitutionTemplateLiteralCompiler, NullLiteralCompiler, NumericLiteralCompiler, ObjectLiteralExpressionCompiler, OmittedExpressionCompiler, ParenthesizedExpressionCompiler, PartiallyEmittedExpressionCompiler, PostfixUnaryExpressionCompiler, PrefixUnaryExpressionCompiler, PropertyAccessExpressionCompiler, RegularExpressionLiteralCompiler, SpreadElementCompiler, StringLiteralCompiler, SuperExpressionCompiler, TaggedTemplateExpressionCompiler, ThisExpressionCompiler, TypeAssertionCompiler, TypeOfExpressionCompiler, VoidExpressionCompiler, YieldExpressionCompiler];
9507
9508class SourceFileCompiler extends NodeCompiler {
9509 constructor(...args) {
9510 var _temp;
9511
9512 return _temp = super(...args), Object.defineProperty(this, "kind", {
9513 configurable: true,
9514 enumerable: true,
9515 writable: true,
9516 value: Ast.SyntaxKind.SourceFile
9517 }), _temp;
9518 }
9519
9520 visitNode(sb, node, options) {
9521 node.getImportDeclarations().forEach(decl => {
9522 sb.visit(decl, options);
9523 });
9524 sb.emitHelper(node, options, sb.helpers.processStatements({
9525 createScope: false
9526 }));
9527 node.getExportDeclarations().forEach(decl => {
9528 sb.visit(decl, options);
9529 });
9530 node.getExportAssignments().forEach(assignment => {
9531 sb.visit(assignment, options);
9532 });
9533 }
9534
9535}
9536
9537var file = [SourceFileCompiler];
9538
9539class BlockCompiler extends NodeCompiler {
9540 constructor(...args) {
9541 var _temp;
9542
9543 return _temp = super(...args), Object.defineProperty(this, "kind", {
9544 configurable: true,
9545 enumerable: true,
9546 writable: true,
9547 value: Ast.SyntaxKind.Block
9548 }), _temp;
9549 }
9550
9551 visitNode(sb, expr, options) {
9552 sb.emitHelper(expr, options, sb.helpers.processStatements({
9553 createScope: true
9554 }));
9555 }
9556
9557}
9558
9559class BreakStatementCompiler extends NodeCompiler {
9560 constructor(...args) {
9561 var _temp;
9562
9563 return _temp = super(...args), Object.defineProperty(this, "kind", {
9564 configurable: true,
9565 enumerable: true,
9566 writable: true,
9567 value: Ast.SyntaxKind.BreakStatement
9568 }), _temp;
9569 }
9570
9571 visitNode(sb, node, options) {
9572 const label = node.getLabel();
9573
9574 if (label != null) {
9575 sb.reportUnsupported(label);
9576 }
9577
9578 if (options.breakPC == null) {
9579 sb.reportError(node, 'Something went wrong. Expected a break jump location.', DiagnosticCode.SOMETHING_WENT_WRONG);
9580 } else {
9581 sb.emitPushInt(node, BREAK_COMPLETION);
9582 sb.emitJmp(node, 'JMP', options.breakPC);
9583 }
9584 }
9585
9586}
9587
9588class CaseBlockCompiler extends NodeCompiler {
9589 constructor(...args) {
9590 var _temp;
9591
9592 return _temp = super(...args), Object.defineProperty(this, "kind", {
9593 configurable: true,
9594 enumerable: true,
9595 writable: true,
9596 value: Ast.SyntaxKind.CaseBlock
9597 }), _temp;
9598 }
9599
9600 visitNode(sb, node, options) {
9601 node.getClauses().forEach(clause => {
9602 sb.visit(clause, options);
9603 });
9604 }
9605
9606}
9607
9608class CaseClauseCompiler extends NodeCompiler {
9609 constructor(...args) {
9610 var _temp;
9611
9612 return _temp = super(...args), Object.defineProperty(this, "kind", {
9613 configurable: true,
9614 enumerable: true,
9615 writable: true,
9616 value: Ast.SyntaxKind.CaseClause
9617 }), _temp;
9618 }
9619
9620 visitNode(sb, node, options) {
9621 sb.reportUnsupported(node);
9622 }
9623
9624}
9625
9626class CatchClauseCompiler extends NodeCompiler {
9627 constructor(...args) {
9628 var _temp;
9629
9630 return _temp = super(...args), Object.defineProperty(this, "kind", {
9631 configurable: true,
9632 enumerable: true,
9633 writable: true,
9634 value: Ast.SyntaxKind.CatchClause
9635 }), _temp;
9636 }
9637
9638 visitNode(sb, node, options) {
9639 const variable = node.getVariableDeclaration();
9640
9641 if (variable == null) {
9642 sb.visit(node.getBlock(), options);
9643 } else {
9644 sb.withScope(node, options, innerOptions => {
9645 sb.visit(variable, innerOptions);
9646 sb.visit(node.getBlock(), innerOptions);
9647 });
9648 }
9649 }
9650
9651}
9652
9653class ContinueStatementCompiler extends NodeCompiler {
9654 constructor(...args) {
9655 var _temp;
9656
9657 return _temp = super(...args), Object.defineProperty(this, "kind", {
9658 configurable: true,
9659 enumerable: true,
9660 writable: true,
9661 value: Ast.SyntaxKind.ContinueStatement
9662 }), _temp;
9663 }
9664
9665 visitNode(sb, node, options) {
9666 const label = node.getLabel();
9667
9668 if (label != null) {
9669 sb.reportUnsupported(label);
9670 }
9671
9672 if (options.continuePC == null) {
9673 sb.reportError(node, 'Something went wrong. Expected a continue jump location.', DiagnosticCode.SOMETHING_WENT_WRONG);
9674 } else {
9675 sb.emitPushInt(node, CONTINUE_COMPLETION);
9676 sb.emitJmp(node, 'JMP', options.continuePC);
9677 }
9678 }
9679
9680}
9681
9682class DebuggerStatementCompiler extends NodeCompiler {
9683 constructor(...args) {
9684 var _temp;
9685
9686 return _temp = super(...args), Object.defineProperty(this, "kind", {
9687 configurable: true,
9688 enumerable: true,
9689 writable: true,
9690 value: Ast.SyntaxKind.DebuggerStatement
9691 }), _temp;
9692 }
9693
9694 visitNode(sb, node, options) {
9695 sb.reportUnsupported(node);
9696 }
9697
9698}
9699
9700class DefaultClauseCompiler extends NodeCompiler {
9701 constructor(...args) {
9702 var _temp;
9703
9704 return _temp = super(...args), Object.defineProperty(this, "kind", {
9705 configurable: true,
9706 enumerable: true,
9707 writable: true,
9708 value: Ast.SyntaxKind.DefaultClause
9709 }), _temp;
9710 }
9711
9712 visitNode(sb, node, options) {
9713 sb.emitOp(node, 'DROP');
9714 sb.emitHelper(node, options, sb.helpers.processStatements({
9715 createScope: false
9716 }));
9717 }
9718
9719}
9720
9721class DoStatementCompiler extends NodeCompiler {
9722 constructor(...args) {
9723 var _temp;
9724
9725 return _temp = super(...args), Object.defineProperty(this, "kind", {
9726 configurable: true,
9727 enumerable: true,
9728 writable: true,
9729 value: Ast.SyntaxKind.DoStatement
9730 }), _temp;
9731 }
9732
9733 visitNode(sb, node, options) {
9734 sb.withProgramCounter(pc => {
9735 sb.withProgramCounter(innerPC => {
9736 sb.visit(node.getStatement(), sb.breakPCOptions(sb.continuePCOptions(options, innerPC.getLast()), pc.getLast()));
9737 });
9738 sb.emitHelper(node.getExpression(), options, sb.helpers.if({
9739 condition: () => {
9740 sb.visit(node.getExpression(), sb.pushValueOptions(options));
9741 },
9742 whenTrue: () => {
9743 sb.emitJmp(node, 'JMP', pc.getFirst());
9744 }
9745 }));
9746 });
9747 }
9748
9749}
9750
9751class EmptyStatementCompiler extends NodeCompiler {
9752 constructor(...args) {
9753 var _temp;
9754
9755 return _temp = super(...args), Object.defineProperty(this, "kind", {
9756 configurable: true,
9757 enumerable: true,
9758 writable: true,
9759 value: Ast.SyntaxKind.EmptyStatement
9760 }), _temp;
9761 }
9762
9763 visitNode(sb, node, options) {// tslint:disable-line
9764 }
9765
9766}
9767
9768class ExpressionStatementCompiler extends NodeCompiler {
9769 constructor(...args) {
9770 var _temp;
9771
9772 return _temp = super(...args), Object.defineProperty(this, "kind", {
9773 configurable: true,
9774 enumerable: true,
9775 writable: true,
9776 value: Ast.SyntaxKind.ExpressionStatement
9777 }), _temp;
9778 }
9779
9780 visitNode(sb, node, options) {
9781 sb.visit(node.getExpression(), sb.noPushValueOptions(options));
9782 }
9783
9784}
9785
9786class ForInStatementCompiler extends NodeCompiler {
9787 constructor(...args) {
9788 var _temp;
9789
9790 return _temp = super(...args), Object.defineProperty(this, "kind", {
9791 configurable: true,
9792 enumerable: true,
9793 writable: true,
9794 value: Ast.SyntaxKind.ForInStatement
9795 }), _temp;
9796 }
9797
9798 visitNode(sb, node, options) {
9799 sb.reportUnsupported(node);
9800 }
9801
9802}
9803
9804class ForOfStatementCompiler extends NodeCompiler {
9805 constructor(...args) {
9806 var _temp;
9807
9808 return _temp = super(...args), Object.defineProperty(this, "kind", {
9809 configurable: true,
9810 enumerable: true,
9811 writable: true,
9812 value: Ast.SyntaxKind.ForOfStatement
9813 }), _temp;
9814 }
9815
9816 visitNode(sb, node, options) {
9817 sb.reportUnsupported(node);
9818 }
9819
9820}
9821
9822class ForStatementCompiler extends NodeCompiler {
9823 constructor(...args) {
9824 var _temp;
9825
9826 return _temp = super(...args), Object.defineProperty(this, "kind", {
9827 configurable: true,
9828 enumerable: true,
9829 writable: true,
9830 value: Ast.SyntaxKind.ForStatement
9831 }), _temp;
9832 }
9833
9834 visitNode(sb, node, options) {
9835 let initializer;
9836 const exprInitializer = node.getInitializer();
9837
9838 if (exprInitializer != null) {
9839 initializer = () => {
9840 sb.visit(exprInitializer, sb.noPushValueOptions(options));
9841 };
9842 }
9843
9844 let condition;
9845 const exprCondition = node.getCondition();
9846
9847 if (exprCondition != null) {
9848 condition = () => {
9849 sb.visit(exprCondition, sb.pushValueOptions(options));
9850 sb.emitHelper(exprCondition, sb.pushValueOptions(options), sb.helpers.toBoolean({
9851 type: sb.getType(exprCondition)
9852 }));
9853 };
9854 }
9855
9856 let incrementor;
9857 const exprIncrementor = node.getIncrementor();
9858
9859 if (exprIncrementor != null) {
9860 incrementor = () => {
9861 sb.visit(exprIncrementor, sb.noPushValueOptions(options));
9862 };
9863 }
9864
9865 sb.emitHelper(node, options, sb.helpers.forLoop({
9866 initializer,
9867 condition,
9868 incrementor,
9869 each: innerOptions => {
9870 sb.visit(node.getStatement(), sb.noPushValueOptions(innerOptions));
9871 }
9872 }));
9873 }
9874
9875}
9876
9877class IfStatementCompiler extends NodeCompiler {
9878 constructor(...args) {
9879 var _temp;
9880
9881 return _temp = super(...args), Object.defineProperty(this, "kind", {
9882 configurable: true,
9883 enumerable: true,
9884 writable: true,
9885 value: Ast.SyntaxKind.IfStatement
9886 }), _temp;
9887 }
9888
9889 visitNode(sb, node, options) {
9890 const condition = () => {
9891 const cond = node.getExpression();
9892 sb.visit(cond, sb.pushValueOptions(options));
9893 sb.emitHelper(cond, sb.pushValueOptions(options), sb.helpers.toBoolean({
9894 type: sb.getType(cond)
9895 }));
9896 };
9897
9898 const whenTrue = () => {
9899 sb.visit(node.getThenStatement(), options);
9900 };
9901
9902 let whenFalse;
9903 const nodeWhenFalse = node.getElseStatement();
9904
9905 if (nodeWhenFalse != null) {
9906 whenFalse = () => {
9907 sb.visit(nodeWhenFalse, options);
9908 };
9909 }
9910
9911 sb.emitHelper(node, options, sb.helpers.if({
9912 condition,
9913 whenTrue,
9914 whenFalse
9915 }));
9916 }
9917
9918}
9919
9920class LabeledStatementCompiler extends NodeCompiler {
9921 constructor(...args) {
9922 var _temp;
9923
9924 return _temp = super(...args), Object.defineProperty(this, "kind", {
9925 configurable: true,
9926 enumerable: true,
9927 writable: true,
9928 value: Ast.SyntaxKind.LabeledStatement
9929 }), _temp;
9930 }
9931
9932 visitNode(sb, node, options) {
9933 sb.reportUnsupported(node);
9934 }
9935
9936}
9937
9938class NotEmittedStatementCompiler extends NodeCompiler {
9939 constructor(...args) {
9940 var _temp;
9941
9942 return _temp = super(...args), Object.defineProperty(this, "kind", {
9943 configurable: true,
9944 enumerable: true,
9945 writable: true,
9946 value: Ast.SyntaxKind.NotEmittedStatement
9947 }), _temp;
9948 }
9949
9950 visitNode(sb, node, options) {
9951 sb.reportUnsupported(node);
9952 }
9953
9954}
9955
9956class ReturnStatementCompiler extends NodeCompiler {
9957 constructor(...args) {
9958 var _temp;
9959
9960 return _temp = super(...args), Object.defineProperty(this, "kind", {
9961 configurable: true,
9962 enumerable: true,
9963 writable: true,
9964 value: Ast.SyntaxKind.ReturnStatement
9965 }), _temp;
9966 }
9967
9968 visitNode(sb, node, options) {
9969 const expr = node.getExpression();
9970
9971 if (expr == null) {
9972 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createUndefined);
9973 } else {
9974 sb.visit(expr, sb.pushValueOptions(options));
9975 }
9976
9977 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createNormalCompletion);
9978 sb.emitOp(node, 'RET');
9979 }
9980
9981}
9982
9983class SwitchStatementCompiler extends NodeCompiler {
9984 constructor(...args) {
9985 var _temp;
9986
9987 return _temp = super(...args), Object.defineProperty(this, "kind", {
9988 configurable: true,
9989 enumerable: true,
9990 writable: true,
9991 value: Ast.SyntaxKind.SwitchStatement
9992 }), _temp;
9993 }
9994
9995 visitNode(sb, node, options) {
9996 sb.withProgramCounter(pc => {
9997 sb.visit(node.getExpression(), sb.pushValueOptions(options));
9998 sb.visit(node.getCaseBlock(), sb.breakPCOptions(options, pc.getLast()));
9999 });
10000 }
10001
10002}
10003
10004class ThrowStatementCompiler extends NodeCompiler {
10005 constructor(...args) {
10006 var _temp;
10007
10008 return _temp = super(...args), Object.defineProperty(this, "kind", {
10009 configurable: true,
10010 enumerable: true,
10011 writable: true,
10012 value: Ast.SyntaxKind.ThrowStatement
10013 }), _temp;
10014 }
10015
10016 visitNode(sb, node, options) {
10017 const expr = node.getExpression();
10018 sb.visit(expr, sb.pushValueOptions(options));
10019 sb.emitHelper(node, options, sb.helpers.throw);
10020 }
10021
10022}
10023
10024class TryStatementCompiler extends NodeCompiler {
10025 constructor(...args) {
10026 var _temp;
10027
10028 return _temp = super(...args), Object.defineProperty(this, "kind", {
10029 configurable: true,
10030 enumerable: true,
10031 writable: true,
10032 value: Ast.SyntaxKind.TryStatement
10033 }), _temp;
10034 }
10035
10036 visitNode(sb, node, options) {
10037 const catchClause = node.getCatchClause();
10038
10039 if (catchClause == null) {
10040 sb.visit(node.getTryBlock(), options);
10041 } else {
10042 sb.withProgramCounter(pc => {
10043 sb.withProgramCounter(innerPC => {
10044 sb.visit(node.getTryBlock(), sb.catchPCOptions(options, innerPC.getLast()));
10045 sb.emitJmp(node, 'JMP', pc.getLast());
10046 });
10047 sb.visit(catchClause, options);
10048 });
10049 }
10050
10051 const finallyBlock = node.getFinallyBlock();
10052
10053 if (finallyBlock != null) {
10054 sb.reportUnsupported(finallyBlock);
10055 }
10056 }
10057
10058}
10059
10060class VariableStatementCompiler extends NodeCompiler {
10061 constructor(...args) {
10062 var _temp;
10063
10064 return _temp = super(...args), Object.defineProperty(this, "kind", {
10065 configurable: true,
10066 enumerable: true,
10067 writable: true,
10068 value: Ast.SyntaxKind.VariableStatement
10069 }), _temp;
10070 }
10071
10072 visitNode(sb, node, optionsIn) {
10073 sb.visit(node.getDeclarationList(), optionsIn);
10074
10075 if (node.isNamedExport()) {
10076 const options = sb.pushValueOptions(optionsIn); // [exports]
10077
10078 sb.emitHelper(node, options, sb.helpers.getCurrentModule);
10079 node.getDeclarationList().getDeclarations().forEach(decl => {
10080 // [exports, exports]
10081 sb.emitOp(node, 'DUP'); // [val, exports, exports]
10082
10083 sb.scope.get(sb, node, options, decl.getName()); // [exports]
10084
10085 sb.emitHelper(node, options, sb.helpers.export({
10086 name: decl.getName()
10087 }));
10088 }); // []
10089
10090 sb.emitOp(node, 'DROP');
10091 }
10092 }
10093
10094}
10095
10096class WhileStatementCompiler extends NodeCompiler {
10097 constructor(...args) {
10098 var _temp;
10099
10100 return _temp = super(...args), Object.defineProperty(this, "kind", {
10101 configurable: true,
10102 enumerable: true,
10103 writable: true,
10104 value: Ast.SyntaxKind.WhileStatement
10105 }), _temp;
10106 }
10107
10108 visitNode(sb, node, options) {
10109 sb.withProgramCounter(pc => {
10110 sb.visit(node.getExpression(), sb.pushValueOptions(options));
10111 sb.emitJmp(node, 'JMPIFNOT', pc.getLast());
10112 sb.visit(node.getStatement(), sb.breakPCOptions(sb.continuePCOptions(options, pc.getFirst()), pc.getLast()));
10113 sb.emitJmp(node, 'JMP', pc.getFirst());
10114 });
10115 }
10116
10117}
10118
10119class WithStatementCompiler extends NodeCompiler {
10120 constructor(...args) {
10121 var _temp;
10122
10123 return _temp = super(...args), Object.defineProperty(this, "kind", {
10124 configurable: true,
10125 enumerable: true,
10126 writable: true,
10127 value: Ast.SyntaxKind.WithStatement
10128 }), _temp;
10129 }
10130
10131 visitNode(sb, node, options) {
10132 sb.reportUnsupported(node);
10133 }
10134
10135}
10136
10137var statement = [BlockCompiler, BreakStatementCompiler, CaseBlockCompiler, CaseClauseCompiler, CatchClauseCompiler, ContinueStatementCompiler, DebuggerStatementCompiler, DefaultClauseCompiler, DoStatementCompiler, EmptyStatementCompiler, ExpressionStatementCompiler, ForInStatementCompiler, ForOfStatementCompiler, ForStatementCompiler, IfStatementCompiler, LabeledStatementCompiler, NotEmittedStatementCompiler, ReturnStatementCompiler, SwitchStatementCompiler, ThrowStatementCompiler, TryStatementCompiler, VariableStatementCompiler, WhileStatementCompiler, WithStatementCompiler];
10138
10139const MAX_JUMP = 32767;
10140const JUMP_OFFSET = 20000;
10141
10142class CodePoint {
10143 constructor() {
10144 Object.defineProperty(this, "length", {
10145 configurable: true,
10146 enumerable: true,
10147 writable: true,
10148 value: void 0
10149 });
10150 Object.defineProperty(this, "sources", {
10151 configurable: true,
10152 enumerable: true,
10153 writable: true,
10154 value: new Set()
10155 });
10156 Object.defineProperty(this, "pcInternal", {
10157 configurable: true,
10158 enumerable: true,
10159 writable: true,
10160 value: void 0
10161 });
10162 Object.defineProperty(this, "prevInternal", {
10163 configurable: true,
10164 enumerable: true,
10165 writable: true,
10166 value: void 0
10167 });
10168 Object.defineProperty(this, "nextInternal", {
10169 configurable: true,
10170 enumerable: true,
10171 writable: true,
10172 value: void 0
10173 });
10174 }
10175
10176 get pc() {
10177 return this.resolvePC();
10178 }
10179
10180 resolvePC() {
10181 if (this.pcInternal == null) {
10182 this.pcInternal = 0;
10183
10184 if (this.prev == null) {
10185 this.pcInternal = 0;
10186 } else {
10187 this.pcInternal = this.prev.pc + this.prev.length;
10188 }
10189 }
10190
10191 return this.pcInternal;
10192 }
10193
10194 resetPC() {
10195 if (this.pcInternal != null) {
10196 this.pcInternal = undefined;
10197 let next = this.next;
10198
10199 while (next != null) {
10200 next.pcInternal = undefined;
10201 next = next.next;
10202 }
10203 }
10204 }
10205
10206 get totalLength() {
10207 let length = this.length;
10208 let next = this.next;
10209
10210 while (next != null) {
10211 length += next.length;
10212 next = next.next;
10213 }
10214
10215 return length;
10216 }
10217
10218 get prev() {
10219 return this.prevInternal;
10220 }
10221
10222 set prev(prev) {
10223 this.resetPC();
10224 this.prevInternal = prev;
10225 }
10226
10227 get next() {
10228 return this.nextInternal;
10229 }
10230
10231 set next(next) {
10232 this.nextInternal = next;
10233 }
10234
10235 insertJumps(targets) {
10236 let self = this;
10237 let skipJump = false;
10238 let ret = this;
10239
10240 while (self != null) {
10241 const target = targets[0];
10242
10243 if (target == null) {
10244 return ret;
10245 }
10246
10247 let length = 0;
10248
10249 if (self.next != null && !skipJump) {
10250 length = 3;
10251 }
10252
10253 let next = self.next;
10254 let nextSkipJump = false;
10255
10256 if (target.isMax && self.pc + self.length + length > target.pc + target.getPostOffset() || !target.isMax && self.pc >= target.pc + target.getPostOffset() - length) {
10257 next = self;
10258
10259 if (skipJump) {
10260 const resolved = target.resolve();
10261 self.insertBefore(resolved);
10262
10263 if (self === this) {
10264 ret = resolved;
10265 }
10266 } else {
10267 const resolved = target.resolve();
10268 const jump = new JumpCodePoint('JMP', self);
10269 self.insertBefore(jump);
10270 jump.insertAfter(resolved);
10271
10272 if (self === this) {
10273 ret = resolved;
10274 }
10275 }
10276
10277 nextSkipJump = true;
10278 targets.shift();
10279 }
10280
10281 self = next;
10282 skipJump = nextSkipJump;
10283 }
10284
10285 if (targets.length > 0) {
10286 throw new Error(`Failed to insert all targets. Something went wrong. Remaining: ${targets.length}`);
10287 }
10288
10289 return ret;
10290 }
10291
10292 insertBefore(point) {
10293 if (this.prev != null) {
10294 this.prev.next = point;
10295 point.prev = this.prev;
10296 }
10297
10298 this.prev = point;
10299 point.next = this;
10300 }
10301
10302 insertAfter(point) {
10303 if (this.next != null) {
10304 this.next.prev = point;
10305 point.next = this.next;
10306 }
10307
10308 this.next = point;
10309 point.prev = this;
10310 }
10311
10312 replace(point) {
10313 if (this.prev != null) {
10314 this.prev.next = point;
10315 point.prevInternal = this.prev;
10316 }
10317
10318 if (this.next != null) {
10319 if (point.length === this.length) {
10320 this.next.prevInternal = point;
10321 } else {
10322 this.next.prev = point;
10323 }
10324
10325 point.next = this.next;
10326 }
10327 }
10328
10329}
10330
10331class JumpCodePoint extends CodePoint {
10332 constructor(type, targetInternal) {
10333 super();
10334 this.type = type;
10335 this.targetInternal = targetInternal;
10336 Object.defineProperty(this, "length", {
10337 configurable: true,
10338 enumerable: true,
10339 writable: true,
10340 value: 3
10341 });
10342 }
10343
10344 get target() {
10345 if (this.targetInternal == null) {
10346 throw new Error('Target not set');
10347 }
10348
10349 return this.targetInternal;
10350 }
10351
10352 set target(target) {
10353 this.targetInternal = target;
10354 }
10355
10356 get isForwardJump() {
10357 return this.target.pc > this.pc;
10358 }
10359
10360 get isReverseJump() {
10361 return this.target.pc < this.pc;
10362 }
10363
10364 get offset() {
10365 if (this.target.pc === this.pc) {
10366 throw new Error('Something went wrong. Found equal target pc and current pc.');
10367 }
10368
10369 return this.target.pc - this.pc;
10370 }
10371
10372}
10373
10374class BufferCodePoint extends CodePoint {
10375 constructor(value) {
10376 super();
10377 this.value = value;
10378 Object.defineProperty(this, "length", {
10379 configurable: true,
10380 enumerable: true,
10381 writable: true,
10382 value: void 0
10383 });
10384 this.length = value.length;
10385 }
10386
10387}
10388
10389class NewJump {
10390 constructor(pc, isMax, target) {
10391 this.pc = pc;
10392 this.isMax = isMax;
10393 this.target = target;
10394 Object.defineProperty(this, "length", {
10395 configurable: true,
10396 enumerable: true,
10397 writable: true,
10398 value: 3
10399 });
10400 Object.defineProperty(this, "sourceInternal", {
10401 configurable: true,
10402 enumerable: true,
10403 writable: true,
10404 value: void 0
10405 });
10406 Object.defineProperty(this, "internalPostOffset", {
10407 configurable: true,
10408 enumerable: true,
10409 writable: true,
10410 value: void 0
10411 });
10412 }
10413
10414 get source() {
10415 if (this.sourceInternal == null) {
10416 throw new Error('NewJump source is not set');
10417 }
10418
10419 return this.sourceInternal;
10420 }
10421
10422 set source(source) {
10423 this.sourceInternal = source;
10424 }
10425
10426 resolve() {
10427 const jump = new JumpCodePoint('JMP', this.target);
10428 this.source.target = jump;
10429
10430 if (this.target instanceof NewJump) {
10431 this.target.source = jump;
10432 } else {
10433 this.target.sources.add(jump);
10434 }
10435
10436 if (this.source instanceof JumpCodePoint) {
10437 jump.sources.add(this.source);
10438 }
10439
10440 return jump;
10441 }
10442
10443 get isForwardJump() {
10444 return this.isMax;
10445 }
10446
10447 get isReverseJump() {
10448 return !this.isMax;
10449 }
10450
10451 get offset() {
10452 if (this.target.pc === this.pc) {
10453 throw new Error('Something went wrong. Found equal target pc and current pc.');
10454 }
10455
10456 return this.target.pc - this.pc;
10457 }
10458
10459 getPostOffset() {
10460 if (this.internalPostOffset == null) {
10461 throw new Error('Not resolved');
10462 }
10463
10464 return this.internalPostOffset;
10465 }
10466
10467 resolvePostOffset(targets) {
10468 const sourcePC = this.source.pc;
10469
10470 if (this.isMax) {
10471 this.internalPostOffset = targets.filter(target => sourcePC < target.pc && target.pc < this.pc).reduce(acc => acc - 6, 0);
10472 } else {
10473 this.internalPostOffset = targets.filter(target => this.pc < target.pc && target.pc < sourcePC).reduce(acc => acc + 6, 0);
10474 }
10475 }
10476
10477}
10478
10479class JumpResolver {
10480 process(bytecode) {
10481 let first = this.getCodePoint(bytecode);
10482 let newTargets = []; // TODO: We do this in a loop in case there's a math problem in inserting
10483 // new jumps, might not be necessary.
10484 // TODO: Optimize and fix this crazy logic.
10485
10486 do {
10487 this.resolvePC(first);
10488 const result = this.processOne(first);
10489 first = result[0];
10490 newTargets = result[1];
10491
10492 const sortedNewTargets = _.sortBy(newTargets, target => target.pc);
10493
10494 sortedNewTargets.forEach(target => target.resolvePostOffset(sortedNewTargets));
10495 first = first.insertJumps(sortedNewTargets);
10496 } while (newTargets.length > 0);
10497
10498 this.resolvePC(first);
10499 let current = first;
10500 const out = [];
10501
10502 while (current != null) {
10503 if (current instanceof JumpCodePoint) {
10504 const pc = new KnownProgramCounter(current.target.pc);
10505
10506 if (current.type === 'CALL') {
10507 out.push(new Call(pc));
10508 } else {
10509 out.push(new Jmp(current.type, pc));
10510 }
10511 } else if (current instanceof BufferCodePoint) {
10512 out.push(current.value);
10513 } else {
10514 throw new Error('Something went wrong.');
10515 }
10516
10517 current = current.next;
10518 }
10519
10520 return out;
10521 }
10522
10523 processOne(codePoint) {
10524 const newTargets = [];
10525 let ret = codePoint;
10526 let value = codePoint;
10527
10528 while (value != null) {
10529 if (value instanceof JumpCodePoint) {
10530 const result = this.getTarget(value);
10531
10532 if (result == null) {
10533 value = value.next;
10534 } else {
10535 const [newValue, newValueTargets] = result;
10536 value.replace(newValue);
10537
10538 if (value === codePoint) {
10539 ret = newValue;
10540 }
10541
10542 newTargets.push(...newValueTargets);
10543 value = newValue.next;
10544 }
10545 } else {
10546 value = value.next;
10547 }
10548 }
10549
10550 return [ret, newTargets];
10551 }
10552
10553 getTarget(value) {
10554 if (value.isForwardJump && value.offset > MAX_JUMP || value.isReverseJump && value.offset < -MAX_JUMP) {
10555 const isMax = value.isForwardJump;
10556 const newOffset = isMax ? JUMP_OFFSET : -JUMP_OFFSET;
10557
10558 if (value.target instanceof NewJump) {
10559 throw new Error('Something went wrong. Unexpected jump target.');
10560 }
10561
10562 const newValueTargets = this.getNewTarget(new NewJump(value.pc + newOffset, isMax, value.target));
10563 const newValueTarget = newValueTargets[0];
10564 const newValue = new JumpCodePoint(value.type, newValueTarget);
10565 newValueTarget.source = newValue;
10566 value.target.sources.delete(value);
10567 [...value.sources].forEach(source => {
10568 source.target = newValue;
10569 newValue.sources.add(source);
10570 });
10571 return [newValue, newValueTargets];
10572 }
10573
10574 return undefined;
10575 }
10576
10577 getNewTarget(value) {
10578 if (value.isForwardJump && value.offset > MAX_JUMP || value.isReverseJump && value.offset < -MAX_JUMP) {
10579 const isMax = value.isForwardJump;
10580 const newOffset = isMax ? JUMP_OFFSET : -JUMP_OFFSET;
10581
10582 if (value.target instanceof NewJump) {
10583 throw new Error('Something went wrong. Unexpected jump target.');
10584 }
10585
10586 const newValueTarget = new NewJump(value.pc + newOffset, isMax, value.target);
10587 value.target = newValueTarget;
10588 newValueTarget.source = value;
10589 const newTargets = this.getNewTarget(newValueTarget);
10590 return [value].concat(newTargets);
10591 }
10592
10593 return [value];
10594 }
10595
10596 getCodePoint(bytecode) {
10597 const sources = {};
10598 const codePoints = {};
10599 const firstBytecode = bytecode[0];
10600 let first;
10601
10602 if (firstBytecode instanceof Jump) {
10603 const jumpCodePoint = new JumpCodePoint(firstBytecode.op);
10604 sources[firstBytecode.pc.getPC()] = [jumpCodePoint];
10605 first = jumpCodePoint;
10606 } else {
10607 first = new BufferCodePoint(firstBytecode);
10608 }
10609
10610 codePoints[0] = first;
10611 let pc = first.length;
10612 let prev = first;
10613
10614 for (const value of bytecode.slice(1)) {
10615 let codePoint;
10616
10617 if (value instanceof Jump) {
10618 const targetPC = value.pc.getPC();
10619 let jumpCodePoint;
10620
10621 if (targetPC < pc) {
10622 jumpCodePoint = new JumpCodePoint(value.op, codePoints[targetPC]);
10623 codePoints[targetPC].sources.add(jumpCodePoint);
10624 } else {
10625 jumpCodePoint = new JumpCodePoint(value.op);
10626
10627 if (sources[targetPC] == null) {
10628 sources[targetPC] = [];
10629 }
10630
10631 sources[targetPC].push(jumpCodePoint);
10632 }
10633
10634 codePoint = jumpCodePoint;
10635 } else {
10636 codePoint = new BufferCodePoint(value);
10637 }
10638
10639 const pcSources = sources[pc];
10640
10641 if (pcSources != null) {
10642 delete sources[pc];
10643 pcSources.forEach(source => {
10644 source.target = codePoint;
10645 codePoint.sources.add(source);
10646 });
10647 }
10648
10649 codePoints[pc] = codePoint;
10650 pc += codePoint.length;
10651 codePoint.prev = prev;
10652 prev.next = codePoint;
10653 prev = codePoint;
10654 }
10655
10656 return first;
10657 }
10658
10659 resolvePC(codePoint) {
10660 codePoint.resetPC();
10661 let current = codePoint;
10662
10663 while (current != null) {
10664 current.resolvePC();
10665 current = current.next;
10666 }
10667 }
10668
10669}
10670
10671const compilers = [declarations, decorator, expression, file, statement];
10672class BaseScriptBuilder {
10673 constructor(context, helpers, ast, sourceFile, allHelpers = []) {
10674 this.context = context;
10675 this.helpers = helpers;
10676 this.ast = ast;
10677 this.sourceFile = sourceFile;
10678 this.allHelpers = allHelpers;
10679 Object.defineProperty(this, "jumpTable", {
10680 configurable: true,
10681 enumerable: true,
10682 writable: true,
10683 value: new JumpTable()
10684 });
10685 Object.defineProperty(this, "currentScope", {
10686 configurable: true,
10687 enumerable: true,
10688 writable: true,
10689 value: void 0
10690 });
10691 Object.defineProperty(this, "compilers", {
10692 configurable: true,
10693 enumerable: true,
10694 writable: true,
10695 value: void 0
10696 });
10697 Object.defineProperty(this, "bytecode", {
10698 configurable: true,
10699 enumerable: true,
10700 writable: true,
10701 value: void 0
10702 });
10703 Object.defineProperty(this, "pc", {
10704 configurable: true,
10705 enumerable: true,
10706 writable: true,
10707 value: void 0
10708 });
10709 Object.defineProperty(this, "jumpTablePC", {
10710 configurable: true,
10711 enumerable: true,
10712 writable: true,
10713 value: new DeferredProgramCounter()
10714 });
10715 Object.defineProperty(this, "capturedBytecode", {
10716 configurable: true,
10717 enumerable: true,
10718 writable: true,
10719 value: undefined
10720 });
10721 Object.defineProperty(this, "nodes", {
10722 configurable: true,
10723 enumerable: true,
10724 writable: true,
10725 value: new Map()
10726 });
10727 Object.defineProperty(this, "moduleMap", {
10728 configurable: true,
10729 enumerable: true,
10730 writable: true,
10731 value: {}
10732 });
10733 Object.defineProperty(this, "reverseModuleMap", {
10734 configurable: true,
10735 enumerable: true,
10736 writable: true,
10737 value: {}
10738 });
10739 Object.defineProperty(this, "exportMap", {
10740 configurable: true,
10741 enumerable: true,
10742 writable: true,
10743 value: {}
10744 });
10745 Object.defineProperty(this, "nextModuleIndex", {
10746 configurable: true,
10747 enumerable: true,
10748 writable: true,
10749 value: 0
10750 });
10751 Object.defineProperty(this, "currentModuleIndex", {
10752 configurable: true,
10753 enumerable: true,
10754 writable: true,
10755 value: 0
10756 });
10757 this.bytecode = [];
10758 this.pc = 0;
10759 this.currentScope = undefined;
10760 this.compilers = compilers.reduce((acc, kindCompilers) => acc.concat(kindCompilers), []).reduce((acc, KindCompiler) => {
10761 const kindCompiler = new KindCompiler();
10762
10763 if (acc[kindCompiler.kind] != null) {
10764 throw new Error(`Found duplicate compiler for kind ${kindCompiler.kind}`);
10765 }
10766
10767 acc[kindCompiler.kind] = kindCompiler;
10768 return acc;
10769 }, {});
10770 }
10771
10772 get scope() {
10773 if (this.currentScope == null) {
10774 throw new Error('Scope has not been set');
10775 }
10776
10777 return this.currentScope;
10778 }
10779
10780 get moduleIndex() {
10781 return this.currentModuleIndex;
10782 }
10783
10784 process() {
10785 const sourceFile = this.sourceFile;
10786 const {
10787 bytecode
10788 } = this.capture(() => {
10789 this.moduleMap[sourceFile.getFilePath()] = this.nextModuleIndex;
10790 this.reverseModuleMap[this.nextModuleIndex] = sourceFile.getFilePath();
10791 this.currentModuleIndex = this.nextModuleIndex;
10792 this.nextModuleIndex += 1;
10793 this.currentScope = this.createScope(sourceFile, 0, undefined);
10794 this.nodes.set(sourceFile, 0);
10795 const options = {};
10796 this.currentScope.emit(this, sourceFile, options, innerOptions => {
10797 // []
10798 this.emitHelper(sourceFile, this.pushValueOptions(options), this.helpers.setGlobalObject); // [globalObjectVal]
10799
10800 this.scope.getGlobal(this, sourceFile, this.pushValueOptions(options)); // []
10801
10802 this.emitHelper(sourceFile, this.pushValueOptions(options), this.helpers.addEmptyModule); // []
10803
10804 this.allHelpers.forEach(helper => {
10805 helper.emitGlobal(this, sourceFile, innerOptions);
10806 });
10807 this.visit(sourceFile, innerOptions);
10808 });
10809 });
10810 this.withProgramCounter(pc => {
10811 this.emitJmp(sourceFile, 'JMP', pc.getLast());
10812 this.jumpTablePC.setPC(pc.getCurrent());
10813 this.jumpTable.emitTable(this, sourceFile);
10814 });
10815 this.emitBytecode(bytecode);
10816 }
10817
10818 getFinalBytecode() {
10819 const bytecode = new JumpResolver().process(this.bytecode.map(([_$$1, value]) => value));
10820 let pc = 0;
10821 const buffers = bytecode.map(valueIn => {
10822 let value = valueIn;
10823
10824 if (value instanceof Jump) {
10825 const offsetPC = new BN(value.pc.getPC()).sub(new BN(pc)); // @ts-ignore
10826
10827 const jumpPC = offsetPC.toTwos(16);
10828 const byteCodeBuffer = clientCore.BYTECODE_TO_BYTECODE_BUFFER[clientCore.OPCODE_TO_BYTECODE[value.op]];
10829
10830 if (byteCodeBuffer == null) {
10831 throw new Error('Something went wrong, could not find bytecode buffer');
10832 }
10833
10834 value = Buffer.concat([byteCodeBuffer, jumpPC.toArrayLike(Buffer, 'le', 2)]);
10835 }
10836
10837 pc += value.length;
10838 return value;
10839 });
10840 return Buffer.concat(buffers);
10841 }
10842
10843 visit(node, options) {
10844 const compiler = this.compilers[node.compilerNode.kind];
10845
10846 if (compiler == null) {
10847 this.reportUnsupported(node);
10848 } else {
10849 compiler.visitNode(this, node, options);
10850 }
10851 }
10852
10853 withScope(node, options, func) {
10854 let index = this.nodes.get(node);
10855
10856 if (index == null) {
10857 index = 0;
10858 } else {
10859 index += 1;
10860 }
10861
10862 this.nodes.set(node, index);
10863 const currentScope = this.currentScope;
10864 this.currentScope = this.createScope(node, index, currentScope);
10865 this.currentScope.emit(this, node, options, func);
10866 this.currentScope = currentScope;
10867 }
10868
10869 withProgramCounter(func) {
10870 const pc = new ProgramCounterHelper(() => this.pc);
10871 func(pc);
10872 pc.setLast();
10873 }
10874
10875 emitOp(node, code, buffer) {
10876 const bytecode = clientCore.OPCODE_TO_BYTECODE[code];
10877
10878 if (bytecode == null) {
10879 throw new clientCore.UnknownOpError(code);
10880 }
10881
10882 this.emitOpByte(node, bytecode, buffer);
10883 }
10884
10885 emitPushInt(node, valueIn) {
10886 const value = new BN(valueIn);
10887
10888 if (value.eq(clientCore.utils.NEGATIVE_ONE)) {
10889 return this.emitOp(node, 'PUSHM1');
10890 } else if (value.eq(clientCore.utils.ZERO)) {
10891 // TODO: Empty byte breaks equality with 0. Not sure if it's a bug in the vm or
10892 // we need to explicitly push a buffer with one 0 byte rather than PUSH0
10893 // this.emitOp(node, 'PUSH0');
10894 return this.emitPush(node, clientCore.utils.toSignedBuffer(value));
10895 } else if (value.gt(clientCore.utils.ZERO) && value.lt(clientCore.utils.SIXTEEN)) {
10896 return this.emitOpByte(node, clientCore.OPCODE_TO_BYTECODE.PUSH1 - 1 + value.toNumber());
10897 }
10898
10899 return this.emitPush(node, clientCore.utils.toSignedBuffer(value));
10900 }
10901
10902 emitPushBoolean(node, value) {
10903 this.emitOp(node, value ? 'PUSH1' : 'PUSH0');
10904 }
10905
10906 emitPushString(node, value) {
10907 return this.emitPush(node, this.toBuffer(value));
10908 }
10909
10910 emitJmp(node, code, pc) {
10911 this.emitJump(node, new Jmp(code, pc));
10912 }
10913
10914 emitHelper(node, options, helper) {
10915 helper.emit(this, node, options);
10916 }
10917
10918 emitBytecode(bytecode) {
10919 const pc = this.pc;
10920 bytecode.forEach(([node, code]) => {
10921 if (code instanceof Call) {
10922 this.emitJump(node, code);
10923 } else if (code instanceof Jmp) {
10924 this.emitJump(node, code.plus(pc));
10925 } else if (code instanceof Jump) {
10926 throw new Error('Something went wrong.');
10927 } else {
10928 this.emitRaw(node, code);
10929 }
10930 });
10931 }
10932
10933 emitCall(node) {
10934 this.emitJump(node, new Call(this.jumpTablePC));
10935 }
10936
10937 emitSysCall(node, name) {
10938 const sysCallBuffer = Buffer.from(name, 'ascii');
10939 const writer = new clientCore.BinaryWriter();
10940 writer.writeVarBytesLE(sysCallBuffer);
10941 this.emitOp(node, 'SYSCALL', writer.toBuffer());
10942 }
10943
10944 loadModule(sourceFile) {
10945 const options = {};
10946 let moduleIndex = this.moduleMap[sourceFile.getFilePath()];
10947
10948 if (moduleIndex == null) {
10949 moduleIndex = this.nextModuleIndex;
10950 this.nextModuleIndex += 1;
10951 this.moduleMap[sourceFile.getFilePath()] = moduleIndex;
10952 this.reverseModuleMap[moduleIndex] = sourceFile.getFilePath();
10953 const currentScope = this.currentScope;
10954 this.currentScope = this.createScope(sourceFile, 0, undefined);
10955 const currentModuleIndex = this.currentModuleIndex;
10956 this.currentModuleIndex = moduleIndex; // [globalObjectVal]
10957
10958 this.scope.getGlobal(this, sourceFile, this.pushValueOptions(options)); // [globalObjectVal, globalObjectVal]
10959
10960 this.emitOp(sourceFile, 'DUP'); // [globalObjectVal]
10961
10962 this.emitHelper(sourceFile, this.pushValueOptions(options), this.helpers.addEmptyModule);
10963 this.currentScope.emit(this, sourceFile, options, innerOptions => {
10964 // []
10965 this.scope.setGlobal(this, sourceFile, options);
10966 this.visit(sourceFile, innerOptions);
10967 });
10968 this.currentScope = currentScope;
10969 this.currentModuleIndex = currentModuleIndex;
10970 } // [globalObjectVal]
10971
10972
10973 this.scope.getGlobal(this, sourceFile, this.pushValueOptions(options)); // [exports]
10974
10975 this.emitHelper(sourceFile, this.pushValueOptions(options), this.helpers.getModule({
10976 moduleIndex
10977 }));
10978 }
10979
10980 capture(func) {
10981 const originalCapturedBytecode = this.capturedBytecode;
10982 this.capturedBytecode = [];
10983 const originalPC = this.pc;
10984 this.pc = 0;
10985 func();
10986 const capturedBytecode = this.capturedBytecode;
10987 this.capturedBytecode = originalCapturedBytecode;
10988 const capturedLength = this.pc;
10989 this.pc = originalPC;
10990 return {
10991 length: capturedLength,
10992 bytecode: capturedBytecode
10993 };
10994 }
10995
10996 toBuffer(value) {
10997 return Buffer.from(value, 'utf8');
10998 }
10999
11000 plainOptions(options) {
11001 return _objectSpread({}, options, {
11002 pushValue: false,
11003 setValue: false,
11004 catchPC: undefined
11005 });
11006 }
11007
11008 pushValueOptions(options) {
11009 return _objectSpread({}, options, {
11010 pushValue: true
11011 });
11012 }
11013
11014 noPushValueOptions(options) {
11015 return _objectSpread({}, options, {
11016 pushValue: false
11017 });
11018 }
11019
11020 setValueOptions(options) {
11021 return _objectSpread({}, options, {
11022 setValue: true
11023 });
11024 }
11025
11026 noSetValueOptions(options) {
11027 return _objectSpread({}, options, {
11028 setValue: false
11029 });
11030 }
11031
11032 noValueOptions(options) {
11033 return _objectSpread({}, options, {
11034 pushValue: false,
11035 setValue: false
11036 });
11037 }
11038
11039 breakPCOptions(options, pc) {
11040 return _objectSpread({}, options, {
11041 breakPC: pc
11042 });
11043 }
11044
11045 continuePCOptions(options, pc) {
11046 return _objectSpread({}, options, {
11047 continuePC: pc
11048 });
11049 }
11050
11051 catchPCOptions(options, pc) {
11052 return _objectSpread({}, options, {
11053 catchPC: pc
11054 });
11055 }
11056
11057 castOptions(options, cast) {
11058 return _objectSpread({}, options, {
11059 cast
11060 });
11061 }
11062
11063 noCastOptions(options) {
11064 return _objectSpread({}, options, {
11065 cast: undefined
11066 });
11067 }
11068
11069 superClassOptions(options, superClass) {
11070 return _objectSpread({}, options, {
11071 superClass
11072 });
11073 }
11074
11075 noSuperClassOptions(options) {
11076 return _objectSpread({}, options, {
11077 superClass: undefined
11078 });
11079 }
11080
11081 reportError(node, message, code) {
11082 this.context.reportError(node, message, code);
11083 }
11084
11085 reportUnsupported(node) {
11086 this.context.reportUnsupported(node);
11087 }
11088
11089 getType(node, required = false) {
11090 return this.context.getType(node, required);
11091 }
11092
11093 getSymbol(node, required = false) {
11094 return this.context.getSymbol(node, required);
11095 }
11096
11097 isOnlyGlobal(node, type, name) {
11098 return this.context.isOnlyGlobal(node, type, name);
11099 }
11100
11101 isGlobal(node, type, name) {
11102 return this.context.isGlobal(node, type, name);
11103 }
11104
11105 isGlobalSymbol(node, symbol, name) {
11106 return this.context.isGlobalSymbol(node, symbol, name);
11107 }
11108
11109 hasExport(sourceFile, name) {
11110 return (this.exportMap[sourceFile.getFilePath()] || new Set()).has(name);
11111 }
11112
11113 addExport(name) {
11114 const filePath = this.assertNotNull(this.reverseModuleMap[this.currentModuleIndex]);
11115 let fileExports = this.exportMap[filePath];
11116
11117 if (fileExports == null) {
11118 fileExports = new Set();
11119 this.exportMap[filePath] = fileExports;
11120 }
11121
11122 fileExports.add(name);
11123 }
11124
11125 assertUnreachable(value) {
11126 throw new Error('Should not be reached.');
11127 }
11128
11129 assertNotNull(value) {
11130 return this.context.assertNotNull(value);
11131 }
11132
11133 filterNotNull(value) {
11134 return value != null;
11135 }
11136
11137 emitPush(node, value) {
11138 if (value.length <= clientCore.OPCODE_TO_BYTECODE.PUSHBYTES75) {
11139 this.emitOpByte(node, value.length, value);
11140 } else if (value.length < 0x100) {
11141 this.emitOp(node, 'PUSHDATA1', new clientCore.ScriptBuilder().emitUInt8(value.length).emit(value).build());
11142 } else if (value.length < 0x10000) {
11143 this.emitOp(node, 'PUSHDATA2', new clientCore.ScriptBuilder().emitUInt16LE(value.length).emit(value).build()); // TODO: Check this condition if (data.Length < 0x100000000L)
11144 } else {
11145 this.emitOp(node, 'PUSHDATA4', new clientCore.ScriptBuilder().emitUInt32LE(value.length).emit(value).build());
11146 }
11147 }
11148
11149 emitOpByte(node, byteCodeIn, buffer) {
11150 const byteCode = `${byteCodeIn == null ? '' : byteCodeIn}`;
11151 const byteCodeBuffer = clientCore.BYTECODE_TO_BYTECODE_BUFFER[byteCode];
11152
11153 if (byteCodeBuffer == null) {
11154 throw new clientCore.UnknownOpError(byteCode);
11155 }
11156
11157 let value = byteCodeBuffer;
11158
11159 if (buffer != null) {
11160 value = Buffer.concat([byteCodeBuffer, buffer]);
11161 }
11162
11163 this.emitRaw(node, value);
11164 }
11165
11166 emitRaw(node, value) {
11167 this.push(node, value);
11168 this.pc += value.length;
11169 }
11170
11171 emitJump(node, jump) {
11172 this.push(node, jump);
11173 this.pc += 3;
11174 }
11175
11176 push(node, value) {
11177 if (this.capturedBytecode != null) {
11178 this.capturedBytecode.push([node, value]);
11179 } else {
11180 this.bytecode.push([node, value]);
11181 }
11182 }
11183
11184}
11185
11186class IdentifierName {
11187 constructor(value) {
11188 this.value = value;
11189 Object.defineProperty(this, "nameBrand", {
11190 configurable: true,
11191 enumerable: true,
11192 writable: true,
11193 value: 0
11194 });
11195 }
11196
11197}
11198
11199class ResolvedScope {
11200 constructor(variableCount, parent) {
11201 this.variableCount = variableCount;
11202 this.parent = parent;
11203 Object.defineProperty(this, "position", {
11204 configurable: true,
11205 enumerable: true,
11206 writable: true,
11207 value: 0
11208 });
11209 Object.defineProperty(this, "variables", {
11210 configurable: true,
11211 enumerable: true,
11212 writable: true,
11213 value: {}
11214 });
11215 Object.defineProperty(this, "uniqueVariables", {
11216 configurable: true,
11217 enumerable: true,
11218 writable: true,
11219 value: new Map()
11220 });
11221 Object.defineProperty(this, "scopeLength", {
11222 configurable: true,
11223 enumerable: true,
11224 writable: true,
11225 value: void 0
11226 });
11227 Object.defineProperty(this, "addScope", {
11228 configurable: true,
11229 enumerable: true,
11230 writable: true,
11231 value: void 0
11232 });
11233 Object.defineProperty(this, "scopeCount", {
11234 configurable: true,
11235 enumerable: true,
11236 writable: true,
11237 value: void 0
11238 });
11239
11240 if (this.parent == null) {
11241 this.addScope = true;
11242 this.scopeCount = 1;
11243 this.scopeLength = 1;
11244 } else {
11245 this.addScope = variableCount > 0;
11246 this.scopeCount = this.addScope ? 1 : 0;
11247 this.scopeLength = this.parent.scopeLength + this.scopeCount;
11248 }
11249 }
11250
11251 add(name) {
11252 const identifier = new IdentifierName(name);
11253 const existing = this.variables[name];
11254
11255 if (existing != null) {
11256 return identifier;
11257 }
11258
11259 this.variables[identifier.value] = this.position;
11260 this.position += 1;
11261
11262 if (this.position > this.variableCount) {
11263 throw new Error(`Something went wrong. Name: ${name} Position: ${this.position} Count: ${this.variableCount}`);
11264 }
11265
11266 return identifier;
11267 }
11268
11269 addUnique() {
11270 const name = {
11271 nameBrand: 0
11272 };
11273 this.uniqueVariables.set(name, this.position);
11274 this.position += 1;
11275
11276 if (this.position > this.variableCount) {
11277 throw new Error(`Something went wrong. Position: ${this.position} Count: ${this.variableCount}`);
11278 }
11279
11280 return name;
11281 } // [value]
11282
11283
11284 set(sb, node, optionsIn, name, scopeLength = this.scopeLength, scopePosition = 0) {
11285 const options = sb.pushValueOptions(optionsIn);
11286 const position = this.getPosition(name);
11287
11288 if (position == null) {
11289 if (this.parent == null) {
11290 sb.reportError(node, `Unknown reference: ${name}`, DiagnosticCode.REFERENCE_ERROR);
11291 } else {
11292 this.parent.set(sb, node, options, name, scopeLength, scopePosition + this.scopeCount);
11293 }
11294 } else {
11295 // [normal]
11296 sb.emitHelper(node, options, sb.helpers.createNormalCompletion); // [scope, normal]
11297
11298 this.loadScope(sb, node, scopeLength, scopePosition); // [position, scope, normal]
11299
11300 sb.emitPushInt(node, position); // [normal, position, scope]
11301
11302 sb.emitOp(node, 'ROT'); // []
11303
11304 sb.emitOp(node, 'SETITEM');
11305 }
11306 }
11307
11308 get(sb, node, options, name, scopeLength = this.scopeLength, scopePosition = 0) {
11309 const position = this.getPosition(name);
11310
11311 if (position == null) {
11312 if (this.parent == null) {
11313 if (typeof name === 'string' && sb.helpers.globalProperties.has(name)) {
11314 // [val]
11315 sb.emitHelper(node, options, sb.helpers.getGlobalProperty({
11316 property: name
11317 }));
11318 } else {
11319 sb.reportError(node, `Unknown reference: ${name}`, DiagnosticCode.REFERENCE_ERROR);
11320 }
11321 } else {
11322 this.parent.get(sb, node, options, name, scopeLength, scopePosition + this.scopeCount);
11323 }
11324 } else {
11325 this.loadScope(sb, node, scopeLength, scopePosition);
11326 sb.emitPushInt(node, position);
11327 sb.emitOp(node, 'PICKITEM');
11328 sb.emitHelper(node, options, sb.helpers.pickCompletionVal);
11329 }
11330 }
11331
11332 getThis(sb, node, options) {
11333 // [[scopes, this]]
11334 this.loadAll(sb, node); // [1, [scopes, this]]
11335
11336 sb.emitPushInt(node, 1); // [this]
11337
11338 sb.emitOp(node, 'PICKITEM');
11339 }
11340
11341 setThis(sb, node, options) {
11342 // [[scopes, this], val]
11343 this.loadAll(sb, node); // [1, [scopes, this], val]
11344
11345 sb.emitPushInt(node, 1); // [val, 1, [scopes, this]]
11346
11347 sb.emitOp(node, 'ROT'); // []
11348
11349 sb.emitOp(node, 'SETITEM');
11350 }
11351
11352 getGlobal(sb, node, options) {
11353 if (this.parent == null) {
11354 // [[scopes, this, global]]
11355 this.loadAll(sb, node); // [2, [scopes, this, global]]
11356
11357 sb.emitPushInt(node, 2); // [this]
11358
11359 sb.emitOp(node, 'PICKITEM');
11360 } else {
11361 this.parent.getGlobal(sb, node, options);
11362 }
11363 }
11364
11365 setGlobal(sb, node, options) {
11366 if (this.parent == null) {
11367 // [[scopes, this, global], val]
11368 this.loadAll(sb, node); // [[scopes, this, global], val, [scopes, this, global]]
11369
11370 sb.emitOp(node, 'TUCK'); // [val, [scopes, this, global], val, [scopes, this, global]]
11371
11372 sb.emitOp(node, 'OVER'); // [2, val, [scopes, this, global], val, [scopes, this, global]]
11373
11374 sb.emitPushInt(node, 2); // [val, 2, [scopes, this, global], val, [scopes, this, global]]
11375
11376 sb.emitOp(node, 'SWAP'); // [val, [scopes, this, global]]
11377
11378 sb.emitOp(node, 'SETITEM'); // [1, val, [scopes, this, global]]
11379
11380 sb.emitPushInt(node, 1); // [val, 1, [scopes, this, global]]
11381
11382 sb.emitOp(node, 'SWAP'); // []
11383
11384 sb.emitOp(node, 'SETITEM');
11385 } else {
11386 this.parent.setGlobal(sb, node, options);
11387 }
11388 }
11389
11390 hasBinding(name) {
11391 return this.variables[name] != null || this.parent != null && this.parent.hasBinding(name);
11392 }
11393
11394 pushAll(sb, node, options) {
11395 sb.emitOp(node, 'DUPFROMALTSTACK');
11396 }
11397
11398 emit(sb, node, options, func) {
11399 if (this.addScope) {
11400 this.surround(sb, node, options, func);
11401 } else {
11402 func(options);
11403 }
11404 }
11405
11406 surround(sb, node, options, func) {
11407 if (this.parent == null) {
11408 // [global]
11409 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createUndefined); // [this, global]
11410
11411 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createUndefined); // [0, this, global]
11412
11413 sb.emitPushInt(node, 0); // [scopes, this, global]
11414
11415 sb.emitOp(node, 'NEWSTRUCT'); // [3, scopes, this, global]
11416
11417 sb.emitPushInt(node, 3); // [[scopes, this, global]]
11418
11419 sb.emitOp(node, 'PACK'); // [[scopes, this, global], [scopes, this, global]]
11420
11421 sb.emitOp(node, 'DUP'); // [[scopes, this, global]]
11422
11423 sb.emitOp(node, 'TOALTSTACK');
11424 } else {
11425 // [[scopes, this]]
11426 sb.emitOp(node, 'DUPFROMALTSTACK');
11427 } // [0, [scopes, this]]
11428
11429
11430 sb.emitPushInt(node, 0); // [scopes]
11431
11432 sb.emitOp(node, 'PICKITEM'); // [0, scopes]
11433
11434 sb.emitPushInt(node, 0); // [scope, scopes]
11435
11436 sb.emitOp(node, 'NEWARRAY'); // [idx, scope, scopes]
11437
11438 sb.emitPushInt(node, 0); // TODO: Should we just loop at compile time?
11439
11440 sb.withProgramCounter(loopPC => {
11441 // [idx, idx, scope, scopes]
11442 sb.emitOp(node, 'DUP'); // [count, idx, idx, scope, scopes]
11443
11444 sb.emitPushInt(node, this.variableCount); // [idx < count, idx, scope, scopes]
11445
11446 sb.emitOp(node, 'LT'); // [idx, scope, scopes]
11447
11448 sb.emitJmp(node, 'JMPIFNOT', loopPC.getLast()); // [scope, idx, scope, scopes]
11449
11450 sb.emitOp(node, 'OVER'); // TODO: throw ReferenceError once it's defined on global
11451
11452 sb.emitPushString(node, 'Referenced variable before it was defined'); // [error, scope, idx, scope, scopes]
11453
11454 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createString); // [throw, scope, idx, scope, scopes]
11455
11456 sb.emitHelper(node, sb.pushValueOptions(options), sb.helpers.createThrowCompletion); // [idx, scope, scopes]
11457
11458 sb.emitOp(node, 'APPEND'); // [idx, scope, scopes]
11459
11460 sb.emitOp(node, 'INC'); // [idx, scope, scopes]
11461
11462 sb.emitJmp(node, 'JMP', loopPC.getFirst());
11463 }); // [scope, scopes]
11464
11465 sb.emitOp(node, 'DROP'); // []
11466
11467 sb.emitOp(node, 'APPEND');
11468 const {
11469 breakPC,
11470 continuePC,
11471 catchPC
11472 } = options;
11473 const nonLocal = breakPC != null || continuePC != null || catchPC != null;
11474 sb.withProgramCounter(pc => {
11475 let innerOptions = options;
11476
11477 if (breakPC != null) {
11478 innerOptions = sb.breakPCOptions(innerOptions, pc.getLast());
11479 }
11480
11481 if (continuePC != null) {
11482 innerOptions = sb.continuePCOptions(innerOptions, pc.getLast());
11483 }
11484
11485 if (catchPC != null) {
11486 innerOptions = sb.catchPCOptions(innerOptions, pc.getLast());
11487 }
11488
11489 func(innerOptions);
11490
11491 if (nonLocal) {
11492 sb.emitPushInt(node, NORMAL_COMPLETION);
11493 }
11494 });
11495
11496 if (this.parent == null) {
11497 // [[scopes, undefined]]
11498 sb.emitOp(node, 'FROMALTSTACK');
11499 sb.emitOp(node, 'DROP');
11500 } else {
11501 // [[scopes, undefined]]
11502 sb.emitOp(node, 'DUPFROMALTSTACK'); // [0, [scopes, undefined]]
11503
11504 sb.emitPushInt(node, 0); // [scopes]
11505
11506 sb.emitOp(node, 'PICKITEM'); // [scopes, scopes]
11507
11508 sb.emitOp(node, 'DUP'); // [size, scopes]
11509
11510 sb.emitOp(node, 'ARRAYSIZE'); // [size - 1, scopes]
11511
11512 sb.emitOp(node, 'DEC'); // []
11513
11514 sb.emitOp(node, 'REMOVE');
11515 }
11516
11517 this.emitNonLocal(sb, node, BREAK_COMPLETION, breakPC);
11518 this.emitNonLocal(sb, node, CONTINUE_COMPLETION, continuePC);
11519 this.emitNonLocal(sb, node, CATCH_COMPLETION, catchPC);
11520
11521 if (nonLocal) {
11522 sb.emitOp(node, 'DROP');
11523 }
11524 }
11525
11526 emitNonLocal(sb, node, completion, pc) {
11527 if (pc != null) {
11528 sb.withProgramCounter(innerPC => {
11529 sb.emitOp(node, 'DUP');
11530 sb.emitPushInt(node, completion);
11531 sb.emitOp(node, 'NUMEQUAL');
11532 sb.emitJmp(node, 'JMPIF', pc);
11533 });
11534 }
11535 }
11536
11537 getPosition(name) {
11538 if (typeof name === 'string') {
11539 return this.variables[name];
11540 } else if (name instanceof IdentifierName) {
11541 return this.variables[name.value];
11542 }
11543
11544 return this.uniqueVariables.get(name);
11545 }
11546
11547 loadScope(sb, node, scopeLength, scopePosition) {
11548 this.loadAll(sb, node); // [0,[scopes, this]]
11549
11550 sb.emitPushInt(node, 0); // [scopes]
11551
11552 sb.emitOp(node, 'PICKITEM'); // [scopeIndex, scopes]
11553
11554 sb.emitPushInt(node, scopeLength - scopePosition - 1); // [scope]
11555
11556 sb.emitOp(node, 'PICKITEM');
11557 }
11558
11559 loadAll(sb, node) {
11560 // [[scopes, this]]
11561 sb.emitOp(node, 'DUPFROMALTSTACK');
11562 }
11563
11564}
11565
11566class CapturingScope {
11567 constructor(node, index, parent) {
11568 this.node = node;
11569 this.index = index;
11570 this.parent = parent;
11571 Object.defineProperty(this, "variableCount", {
11572 configurable: true,
11573 enumerable: true,
11574 writable: true,
11575 value: 0
11576 });
11577 Object.defineProperty(this, "bindings", {
11578 configurable: true,
11579 enumerable: true,
11580 writable: true,
11581 value: new Set()
11582 });
11583 }
11584
11585 add(name) {
11586 this.variableCount += 1;
11587 this.bindings.add(name);
11588 return {
11589 nameBrand: 0
11590 };
11591 }
11592
11593 addUnique() {
11594 this.variableCount += 1;
11595 return {
11596 nameBrand: 0
11597 };
11598 }
11599
11600 set(sb, node) {
11601 sb.emitOp(node, 'NOP');
11602 }
11603
11604 get(sb, node) {
11605 sb.emitOp(node, 'NOP');
11606 }
11607
11608 getThis(sb, node) {
11609 sb.emitOp(node, 'NOP');
11610 }
11611
11612 setThis(sb, node) {
11613 sb.emitOp(node, 'NOP');
11614 }
11615
11616 getGlobal(sb, node) {
11617 sb.emitOp(node, 'NOP');
11618 }
11619
11620 setGlobal(sb, node) {
11621 sb.emitOp(node, 'NOP');
11622 }
11623
11624 hasBinding(name) {
11625 return this.bindings.has(name) || this.parent != null && this.parent.hasBinding(name);
11626 }
11627
11628 pushAll(sb, node) {
11629 sb.emitOp(node, 'NOP');
11630 }
11631
11632 emit(sb, node, options, func) {
11633 sb.emitOp(node, 'NOP');
11634 func(options);
11635 sb.emitOp(node, 'NOP');
11636 }
11637
11638 resolve(parent) {
11639 return new ResolvedScope(this.variableCount, parent);
11640 }
11641
11642}
11643
11644class ScopeCapturingScriptBuilder extends BaseScriptBuilder {
11645 constructor(...args) {
11646 var _temp;
11647
11648 return _temp = super(...args), Object.defineProperty(this, "scopes", {
11649 configurable: true,
11650 enumerable: true,
11651 writable: true,
11652 value: []
11653 }), Object.defineProperty(this, "resolvedScopes", {
11654 configurable: true,
11655 enumerable: true,
11656 writable: true,
11657 value: new Map()
11658 }), _temp;
11659 }
11660
11661 process() {
11662 super.process();
11663 this.resolveScopes();
11664 }
11665
11666 getScopes() {
11667 return this.resolvedScopes;
11668 }
11669
11670 createScope(node, index, parent) {
11671 const scope = new CapturingScope(node, index, parent);
11672 this.scopes.push(scope);
11673 return scope;
11674 }
11675
11676 resolveScopes() {
11677 this.scopes.forEach(scope => {
11678 this.resolveScope(scope);
11679 });
11680 }
11681
11682 resolveScope(scope) {
11683 let forNode = this.resolvedScopes.get(scope.node);
11684
11685 if (forNode == null) {
11686 forNode = new Map();
11687 this.resolvedScopes.set(scope.node, forNode);
11688 }
11689
11690 let resolved = forNode.get(scope.index);
11691
11692 if (resolved == null) {
11693 const parent = scope.parent;
11694
11695 if (parent == null) {
11696 resolved = scope.resolve();
11697 } else {
11698 resolved = scope.resolve(this.resolveScope(parent));
11699 }
11700
11701 forNode.set(scope.index, resolved);
11702 }
11703
11704 return resolved;
11705 }
11706
11707}
11708
11709class EmittingScriptBuilder extends BaseScriptBuilder {
11710 constructor({
11711 context,
11712 scopes,
11713 helpers,
11714 ast,
11715 sourceFile,
11716 allHelpers
11717 }) {
11718 super(context, helpers, ast, sourceFile, allHelpers);
11719 Object.defineProperty(this, "scopes", {
11720 configurable: true,
11721 enumerable: true,
11722 writable: true,
11723 value: void 0
11724 });
11725 this.scopes = scopes;
11726 }
11727
11728 createScope(node, index) {
11729 return this.assertNotNull(this.assertNotNull(this.scopes.get(node)).get(index));
11730 }
11731
11732}
11733
11734class HelperCapturingScriptBuilder extends ScopeCapturingScriptBuilder {
11735 constructor(...args) {
11736 var _temp;
11737
11738 return _temp = super(...args), Object.defineProperty(this, "capturedHelpersSet", {
11739 configurable: true,
11740 enumerable: true,
11741 writable: true,
11742 value: new Set()
11743 }), Object.defineProperty(this, "capturedHelpers", {
11744 configurable: true,
11745 enumerable: true,
11746 writable: true,
11747 value: []
11748 }), _temp;
11749 }
11750
11751 getHelpers() {
11752 return [...this.capturedHelpers];
11753 }
11754
11755 emitHelper(node, options, helper) {
11756 if (!this.capturedHelpersSet.has(helper)) {
11757 this.capturedHelpersSet.add(helper);
11758 this.capturedHelpers.push(helper);
11759 helper.emitGlobal(this, node, options);
11760 }
11761
11762 helper.emit(this, node, options);
11763 }
11764
11765}
11766
11767class CompilerDiagnostic {
11768 constructor(node, messageText, code, category) {
11769 this.node = node;
11770 this.messageText = messageText;
11771 this.code = code;
11772 this.category = category;
11773 }
11774
11775 get file() {
11776 return this.node.getSourceFile().compilerNode;
11777 }
11778
11779 get start() {
11780 return this.node.getStart();
11781 }
11782
11783 get length() {
11784 return this.node.getWidth();
11785 }
11786
11787 get source() {
11788 return this.node.getText();
11789 }
11790
11791}
11792
11793// tslint:disable ban-types
11794class Context {
11795 constructor(globals, libs, libAliases) {
11796 this.globals = globals;
11797 this.libs = libs;
11798 this.libAliases = libAliases;
11799 Object.defineProperty(this, "diagnostics", {
11800 configurable: true,
11801 enumerable: true,
11802 writable: true,
11803 value: []
11804 });
11805 }
11806
11807 reportError(node, message, code) {
11808 this.diagnostics.push(new CompilerDiagnostic(node, message, code, Ast.DiagnosticCategory.Error));
11809 }
11810
11811 reportWarning(node, message, code) {
11812 this.diagnostics.push(new CompilerDiagnostic(node, message, code, Ast.DiagnosticCategory.Warning));
11813 }
11814
11815 reportUnsupported(node) {
11816 this.reportError(node, 'Unsupported syntax', DiagnosticCode.UNSUPPORTED_SYNTAX);
11817 }
11818
11819 reportTypeError(node) {
11820 this.reportError(node, 'Could not infer type. Please add an explicit type annotation.', DiagnosticCode.UNKNOWN_TYPE);
11821 }
11822
11823 reportTypeWarning(node) {
11824 this.reportWarning(node, 'Could not infer type. Deoptimized implementation will be used. Add an explicit type annotation ' + 'to optimize the output.', DiagnosticCode.UNKNOWN_TYPE);
11825 }
11826
11827 getType(node, required = false) {
11828 let type = this.getNotAnyType(node.getType());
11829
11830 if (type == null && Ast.TypeGuards.isExpression(node)) {
11831 type = this.getNotAnyType(node.getContextualType());
11832 }
11833
11834 if (type == null) {
11835 if (required) {
11836 this.reportTypeError(node);
11837 } else {
11838 this.reportTypeWarning(node);
11839 }
11840 }
11841
11842 return type;
11843 }
11844
11845 getTypeOfSymbol(symbol, node, required = false) {
11846 if (symbol == null) {
11847 return undefined;
11848 }
11849
11850 const type = this.getNotAnyType(symbol.getTypeAtLocation(node));
11851
11852 if (type == null) {
11853 if (required) {
11854 this.reportTypeError(node);
11855 } else {
11856 this.reportTypeWarning(node);
11857 }
11858 }
11859
11860 return type;
11861 }
11862
11863 getSymbol(node, required = false) {
11864 const symbol = node.getSymbol();
11865
11866 if (symbol == null) {
11867 const message = 'Could not determine source symbol.';
11868
11869 if (required) {
11870 this.reportError(node, message, DiagnosticCode.UNKNOWN_SYMBOL);
11871 } else {
11872 this.reportWarning(node, message, DiagnosticCode.UNKNOWN_SYMBOL);
11873 }
11874
11875 return undefined;
11876 }
11877
11878 const aliased = symbol.getAliasedSymbol();
11879
11880 if (aliased != null) {
11881 return aliased;
11882 }
11883
11884 return symbol;
11885 }
11886
11887 getSymbolForType(node, type, required = false) {
11888 if (type == null) {
11889 return undefined;
11890 }
11891
11892 const symbol = type.getSymbol();
11893
11894 if (symbol == null) {
11895 const message = `Could not determine source symbol for type: ${type.getText()}.`;
11896
11897 if (required) {
11898 this.reportError(node, message, DiagnosticCode.UNKNOWN_SYMBOL);
11899 } else {
11900 this.reportWarning(node, message, DiagnosticCode.UNKNOWN_SYMBOL);
11901 }
11902
11903 return undefined;
11904 }
11905
11906 const aliased = symbol.getAliasedSymbol();
11907
11908 if (aliased != null) {
11909 return aliased;
11910 }
11911
11912 return symbol;
11913 }
11914
11915 assertUnreachable(value) {
11916 throw new Error('Should not be reached.');
11917 }
11918
11919 assertNotNull(value) {
11920 if (value == null) {
11921 throw new Error('Something went wrong. Unexpected null.');
11922 }
11923
11924 return value;
11925 }
11926
11927 isOnlyGlobal(node, type, name) {
11928 return this.isSymbolic(type) && this.isGlobalSymbol(node, this.getSymbolForType(node, type), name);
11929 } // TODO: This should check unions
11930
11931
11932 isGlobal(node, type, name) {
11933 return this.isSymbolic(type) && this.isGlobalSymbol(node, this.getSymbolForType(node, type), name);
11934 }
11935
11936 isGlobalSymbol(node, symbol, name) {
11937 return symbol === this.globals[name];
11938 }
11939
11940 isOnlyLib(node, type, name) {
11941 return this.isSymbolic(type) && this.isLibSymbol(node, this.getSymbolForType(node, type), name);
11942 }
11943
11944 isLibSymbol(node, symbol, name) {
11945 return symbol === this.libs[name];
11946 }
11947
11948 isLibAlias(identifier, name) {
11949 if (identifier == null) {
11950 return false;
11951 }
11952
11953 return this.libAliases[name].has(identifier);
11954 }
11955
11956 isSymbolic(type) {
11957 return type == null || !isLiteral(type) && !isPrimitive(type) && !isTuple(type) && !isUnion(type) && !isIntersection(type);
11958 }
11959
11960 getNotAnyType(type) {
11961 // tslint:disable-next-line no-bitwise
11962 if (type == null || (type.getFlags() & Ast.TypeFlags.Any) !== 0) {
11963 return undefined;
11964 }
11965
11966 return type;
11967 }
11968
11969}
11970
11971// tslint:disable ban-types no-bitwise
11972
11973const findInterfaceFile = (ast, name) => {
11974 const files = ast.getSourceFiles();
11975 return files.find(file => {
11976 if (!file.isDeclarationFile()) {
11977 return false;
11978 }
11979
11980 let bufferInterface = file.getInterface(name);
11981 const globalNamespace = file.getNamespace('global');
11982 let isGlobalAugmentation = false;
11983
11984 if (bufferInterface == null && globalNamespace != null) {
11985 bufferInterface = globalNamespace.getInterface(name);
11986 isGlobalAugmentation = true;
11987 }
11988
11989 if (bufferInterface == null) {
11990 return false;
11991 }
11992
11993 return isGlobalAugmentation || (bufferInterface.compilerNode.flags & Ast.ts.NodeFlags.GlobalAugmentation) !== 0;
11994 });
11995};
11996
11997const getGlobals = ast => {
11998 let bufferFile = findInterfaceFile(ast, 'Buffer');
11999
12000 if (bufferFile == null) {
12001 bufferFile = ast.addExistingSourceFileIfExists(require.resolve('@types/node/index.d.ts'));
12002 }
12003
12004 if (bufferFile == null) {
12005 throw new Error('Could not find Buffer');
12006 }
12007
12008 const buffer = bufferFile.getInterfaceOrThrow('Buffer');
12009 const typeChecker = ast.getTypeChecker().compilerObject; // @ts-ignore
12010
12011 const array = new Ast.Symbol( // @ts-ignore
12012 ast.global, typeChecker.createArrayType(typeChecker.getAnyType()).symbol).getDeclaredType();
12013 let neoFile = findInterfaceFile(ast, 'AccountBase');
12014
12015 if (neoFile == null) {
12016 ast.addExistingSourceFiles(path__default.join(path__default.dirname(require.resolve('@neo-one/smart-contract')), '**', '*.ts'));
12017 }
12018
12019 neoFile = findInterfaceFile(ast, 'AccountBase');
12020
12021 if (neoFile == null) {
12022 throw new Error('Could not find NEO type definition file');
12023 }
12024
12025 const neoGlobal = neoFile.getNamespaceOrThrow('global');
12026 return {
12027 Array: array.getSymbolOrThrow(),
12028 Buffer: buffer.getSymbolOrThrow(),
12029 process: bufferFile.getVariableDeclarationOrThrow('process').getSymbolOrThrow(),
12030 AccountBase: neoGlobal.getInterfaceOrThrow('AccountBase').getSymbolOrThrow(),
12031 AssetBase: neoGlobal.getInterfaceOrThrow('AssetBase').getSymbolOrThrow(),
12032 AttributeBase: neoGlobal.getInterfaceOrThrow('AttributeBase').getSymbolOrThrow(),
12033 BlockBase: neoGlobal.getInterfaceOrThrow('BlockBase').getSymbolOrThrow(),
12034 ContractBase: neoGlobal.getInterfaceOrThrow('ContractBase').getSymbolOrThrow(),
12035 HeaderBase: neoGlobal.getInterfaceOrThrow('HeaderBase').getSymbolOrThrow(),
12036 InputBase: neoGlobal.getInterfaceOrThrow('InputBase').getSymbolOrThrow(),
12037 OutputBase: neoGlobal.getInterfaceOrThrow('OutputBase').getSymbolOrThrow(),
12038 TransactionBase: neoGlobal.getInterfaceOrThrow('TransactionBase').getSymbolOrThrow(),
12039 ValidatorBase: neoGlobal.getInterfaceOrThrow('ValidatorBase').getSymbolOrThrow(),
12040 StorageContextBase: neoGlobal.getInterfaceOrThrow('StorageContextBase').getSymbolOrThrow(),
12041 StorageIteratorBase: neoGlobal.getInterfaceOrThrow('StorageIteratorBase').getSymbolOrThrow(),
12042 syscall: neoGlobal.getFunctionOrThrow('syscall').getSymbolOrThrow()
12043 };
12044};
12045
12046const findLibFile = ast => {
12047 const files = ast.getSourceFiles();
12048 return files.find(file => file.getClass('MapStorage') != null);
12049};
12050
12051const getLibs = ast => {
12052 let libFileIn = findLibFile(ast);
12053
12054 if (libFileIn == null) {
12055 ast.addExistingSourceFiles(path__default.join(path__default.dirname(require.resolve('@neo-one/smart-contract')), '**', '*.ts'));
12056 }
12057
12058 libFileIn = findLibFile(ast);
12059
12060 if (libFileIn == null) {
12061 throw new Error('Could not find NEO lib file');
12062 }
12063
12064 const libFile = libFileIn;
12065 return {
12066 get SmartContract() {
12067 return libFile.getClassOrThrow('SmartContract').getSymbolOrThrow();
12068 },
12069
12070 get MapStorage() {
12071 return libFile.getClassOrThrow('MapStorage').getSymbolOrThrow();
12072 },
12073
12074 get SetStorage() {
12075 return libFile.getClassOrThrow('SetStorage').getSymbolOrThrow();
12076 },
12077
12078 get Fixed() {
12079 return libFile.getTypeAliasOrThrow('Fixed').getSymbolOrThrow();
12080 },
12081
12082 get constant() {
12083 return libFile.getFunctionOrThrow('constant').getSymbolOrThrow();
12084 },
12085
12086 get verify() {
12087 return libFile.getFunctionOrThrow('verify').getSymbolOrThrow();
12088 }
12089
12090 };
12091};
12092const getLibAliases = ast => {
12093 let libFileIn = findLibFile(ast);
12094
12095 if (libFileIn == null) {
12096 ast.addExistingSourceFiles(path__default.join(path__default.dirname(require.resolve('@neo-one/smart-contract')), '**', '*.ts'));
12097 }
12098
12099 libFileIn = findLibFile(ast);
12100
12101 if (libFileIn == null) {
12102 throw new Error('Could not find NEO lib file');
12103 }
12104
12105 const libFile = libFileIn;
12106 return {
12107 get Address() {
12108 return new Set(libFile.getTypeAliasOrThrow('Address').getReferencingNodes());
12109 },
12110
12111 get Hash256() {
12112 return new Set(libFile.getTypeAliasOrThrow('Hash256').getReferencingNodes());
12113 },
12114
12115 get Signature() {
12116 return new Set(libFile.getTypeAliasOrThrow('Signature').getReferencingNodes());
12117 },
12118
12119 get PublicKey() {
12120 return new Set(libFile.getTypeAliasOrThrow('PublicKey').getReferencingNodes());
12121 }
12122
12123 };
12124};
12125
12126const compile = ({
12127 ast,
12128 sourceFile,
12129 context: contextIn
12130}) => {
12131 const context = contextIn || new Context(getGlobals(ast), getLibs(ast), getLibAliases(ast));
12132 const helpers = createHelpers();
12133 const helperScriptBuilder = new HelperCapturingScriptBuilder(context, helpers, ast, sourceFile);
12134 helperScriptBuilder.process();
12135 const scopeScriptBuilder = new ScopeCapturingScriptBuilder(context, helpers, ast, sourceFile, helperScriptBuilder.getHelpers());
12136 scopeScriptBuilder.process();
12137 const emittingScriptBuilder = new EmittingScriptBuilder({
12138 context,
12139 scopes: scopeScriptBuilder.getScopes(),
12140 ast,
12141 sourceFile,
12142 helpers,
12143 allHelpers: helperScriptBuilder.getHelpers()
12144 });
12145 emittingScriptBuilder.process();
12146 return {
12147 code: emittingScriptBuilder.getFinalBytecode(),
12148 context
12149 };
12150};
12151
12152// tslint:disable ban-types
12153
12154const findRoot = async (dir, filename) => {
12155 let start = dir;
12156
12157 if (typeof start === 'string') {
12158 if (start[start.length - 1] !== path.sep) {
12159 start += path.sep;
12160 }
12161
12162 start = start.split(path.sep);
12163 }
12164
12165 if (!start.length) {
12166 throw new Error('tsconfig.json not found in path');
12167 }
12168
12169 start.pop();
12170 const currentDir = start.join(path.sep);
12171 const file = path.join(currentDir, filename);
12172 const exists = await fs.pathExists(file);
12173
12174 if (exists) {
12175 return file;
12176 }
12177
12178 return findRoot(start, filename);
12179};
12180
12181const makeAst = async dir => {
12182 const tsConfigFilePath = await findRoot(dir, 'tsconfig.json');
12183 const res = Ast.ts.readConfigFile(tsConfigFilePath, value => fs.readFileSync(value, 'utf8'));
12184 const parseConfigHost = {
12185 fileExists: fs.existsSync,
12186 readDirectory: Ast.ts.sys.readDirectory,
12187 readFile: Ast.ts.sys.readFile,
12188 useCaseSensitiveFileNames: true
12189 };
12190 const parsed = Ast.ts.parseJsonConfigFileContent(res.config, parseConfigHost, path.dirname(tsConfigFilePath));
12191 return new Ast__default({
12192 compilerOptions: parsed.options
12193 });
12194};
12195const getAst = async dir => {
12196 const ast = await makeAst(dir);
12197 ast.addExistingSourceFiles(path.join(dir, '**', '*.ts')); // For some reason this forces Ast to resolve references. Do not remove.
12198
12199 ast.getPreEmitDiagnostics();
12200 return ast;
12201};
12202
12203const compileScript = async scriptPath => {
12204 const ast = await getAst(path__default.dirname(scriptPath));
12205 const sourceFile = ast.getSourceFileOrThrow(scriptPath);
12206 return compile({
12207 ast,
12208 sourceFile
12209 });
12210};
12211
12212class NodeTranspiler {
12213 constructor() {
12214 Object.defineProperty(this, "kind", {
12215 configurable: true,
12216 enumerable: true,
12217 writable: true,
12218 value: void 0
12219 });
12220 }
12221
12222}
12223
12224const DEPLOY_METHOD = 'deploy';
12225class ClassDeclarationTranspiler extends NodeTranspiler {
12226 constructor(...args) {
12227 var _temp;
12228
12229 return _temp = super(...args), Object.defineProperty(this, "kind", {
12230 configurable: true,
12231 enumerable: true,
12232 writable: true,
12233 value: Ast.SyntaxKind.ClassDeclaration
12234 }), _temp;
12235 }
12236
12237 visitNode(transpiler, node) {
12238 if (transpiler.isSmartContract(node)) {
12239 this.transpileSmartContract(transpiler, node);
12240 }
12241 }
12242
12243 transpileSmartContract(transpiler, node) {
12244 transpiler.visit(node.getBaseClass());
12245 this.transpileDeploy(transpiler, node);
12246 } // TODO: Lots of edge cases to handle here. E.g. readonly constructor properties
12247
12248
12249 transpileDeploy(transpiler, node) {
12250 const existingDeploy = node.getMethod(DEPLOY_METHOD);
12251
12252 if (existingDeploy != null) {
12253 transpiler.reportError(existingDeploy, 'The deploy method is reserved in SmartContract instances.', DiagnosticCode.UNSUPPORTED_SYNTAX);
12254 return;
12255 }
12256
12257 const ctor = node.getConstructors().find(ctorDecl => ctorDecl.isImplementation());
12258 let bodyText = '';
12259 let parameters = [];
12260
12261 if (ctor == null) {
12262 const baseDeploy = this.getBaseDeploy(transpiler, node);
12263
12264 if (baseDeploy != null) {
12265 bodyText = `
12266 super.deploy(${baseDeploy.getParameters().map(param => param.getName()).join(', ')});
12267 `;
12268 parameters = baseDeploy.getParameters();
12269 }
12270 } else {
12271 const firstStatement = ctor.getStatements()[0];
12272
12273 if (firstStatement != null && Ast.TypeGuards.isExpressionStatement(firstStatement)) {
12274 const callExpr = firstStatement.getExpression();
12275
12276 if (Ast.TypeGuards.isCallExpression(callExpr)) {
12277 const lhsrExpr = callExpr.getExpression();
12278
12279 if (Ast.TypeGuards.isSuperExpression(lhsrExpr)) {
12280 // TODO: Handle case where constructor needs keep some statements
12281 firstStatement.replaceWithText(`super.deploy(${callExpr.getArguments().map(arg => arg.getText()).join(', ')});`);
12282 }
12283 }
12284 }
12285
12286 bodyText = ctor.getStatements().map(statement => statement.getText()).join('\n');
12287 parameters = ctor.getParameters();
12288 }
12289
12290 const deploy = node.addMethod({
12291 name: DEPLOY_METHOD,
12292 returnType: 'boolean',
12293 bodyText,
12294 parameters: parameters.map(param => {
12295 const initializer = param.getInitializer();
12296 let type = param.getType().getText();
12297 const typeNode = param.getTypeNode();
12298
12299 if (typeNode != null) {
12300 type = typeNode.getText();
12301 }
12302
12303 return {
12304 name: param.getNameOrThrow(),
12305 type,
12306 initializer: initializer == null ? undefined : initializer.getText(),
12307 hasQuestionToken: param.hasQuestionToken(),
12308 isRestParameter: param.isRestParameter()
12309 };
12310 }),
12311 scope: Ast.Scope.Public
12312 });
12313 node.getInstanceProperties().forEach(property => {
12314 if (Ast.TypeGuards.isPropertyDeclaration(property) && !property.isAbstract() || Ast.TypeGuards.isParameterDeclaration(property)) {
12315 const name = Ast.TypeGuards.isPropertyDeclaration(property) ? property.getName() : property.getNameOrThrow();
12316 const type = property.getType();
12317 const typeNode = property.getTypeNode();
12318
12319 if (type == null || typeNode == null) {
12320 transpiler.reportError(property, 'Could not determine type of property.', DiagnosticCode.UNKNOWN_TYPE);
12321 } else if (isOnlyPrimitive(type) || transpiler.isFixedType(property, type) || transpiler.isOnlyGlobal(property, type, 'Buffer')) {
12322 if (Ast.TypeGuards.isParameterDeclaration(property)) {
12323 deploy.addStatements(`
12324 this.${property.getName()} = ${property.getName()};
12325 `);
12326 }
12327
12328 const init = property.getInitializer();
12329 let addAccessors = true;
12330
12331 if (Ast.TypeGuards.isPropertyDeclaration(property) && init != null) {
12332 if (property.isReadonly()) {
12333 addAccessors = false;
12334 } else {
12335 deploy.addStatements(`
12336 this.${property.getName()} = ${init.getText()};
12337 `);
12338 }
12339 }
12340
12341 if (addAccessors) {
12342 node.addGetAccessor({
12343 name,
12344 returnType: typeNode.getText(),
12345 bodyText: `
12346 return syscall('Neo.Storage.Get', syscall('Neo.Storage.GetContext'), '${name}') as ${typeNode.getText()};
12347 `,
12348 scope: property.getScope()
12349 });
12350 node.addSetAccessor({
12351 name,
12352 parameters: [{
12353 name,
12354 type: typeNode.getText()
12355 }],
12356 bodyText: `
12357 syscall('Neo.Storage.Put', syscall('Neo.Storage.GetContext'), '${name}', ${name});
12358 `,
12359 scope: property.getScope()
12360 });
12361 property.remove();
12362 }
12363 } else if (transpiler.isOnlyLib(property, type, 'MapStorage')) {
12364 property.setInitializer(`new MapStorage(syscall('Neo.Runtime.Serialize', '${name}'))`);
12365 } else if (transpiler.isOnlyLib(property, type, 'SetStorage')) {
12366 property.setInitializer(`new SetStorage(syscall('Neo.Runtime.Serialize', '${name}'))`);
12367 } else {
12368 transpiler.reportError(property, 'Unsupported SmartContract property.', DiagnosticCode.UNSUPPORTED_SYNTAX);
12369 }
12370 }
12371 });
12372 deploy.addStatements(`
12373 return true;
12374 `);
12375
12376 if (ctor != null) {
12377 // TODO: Handle case where constructor needs keep some statements
12378 ctor.remove();
12379 }
12380 }
12381
12382 getBaseDeploy(transpiler, node) {
12383 const baseClass = node.getBaseClass();
12384
12385 if (baseClass == null) {
12386 return undefined;
12387 }
12388
12389 const deploy = baseClass.getInstanceMethod('deploy');
12390
12391 if (deploy == null) {
12392 return this.getBaseDeploy(transpiler, baseClass);
12393 }
12394
12395 return deploy;
12396 }
12397
12398}
12399
12400var declarations$1 = [ClassDeclarationTranspiler];
12401
12402const isPublic = (node // tslint:disable-next-line no-bitwise
12403) => (node.getCombinedModifierFlags() & Ast.ts.ModifierFlags.Public) !== 0;
12404
12405const transpilers = [declarations$1];
12406class NEOTranspiler {
12407 constructor(context, ast, smartContract) {
12408 this.context = context;
12409 this.ast = ast;
12410 this.smartContract = smartContract;
12411 Object.defineProperty(this, "transpilers", {
12412 configurable: true,
12413 enumerable: true,
12414 writable: true,
12415 value: void 0
12416 });
12417 this.transpilers = transpilers.reduce((acc, kindCompilers) => acc.concat(kindCompilers), []).reduce((acc, KindCompiler) => {
12418 const kindCompiler = new KindCompiler();
12419
12420 if (acc[kindCompiler.kind] != null) {
12421 throw new Error(`Found duplicate compiler for kind ${kindCompiler.kind}`);
12422 }
12423
12424 acc[kindCompiler.kind] = kindCompiler;
12425 return acc;
12426 }, {});
12427 }
12428
12429 process() {
12430 const file = this.smartContract.getSourceFile();
12431 this.visit(file);
12432 const smartContract = file.getClassOrThrow(this.smartContract.getNameOrThrow());
12433 const methods = smartContract.getType().getProperties().map(symbol => this.processProperty(symbol)).reduce((acc, values) => acc.concat(values), []);
12434 const verifySwitches = [];
12435 const applicationSwitches = [];
12436 const functions = [];
12437
12438 for (const [method, func] of methods) {
12439 const name = Ast.TypeGuards.isParameterDeclaration(method) ? method.getNameOrThrow() : method.getName();
12440 let methodSwitch;
12441
12442 if (Ast.TypeGuards.isMethodDeclaration(method)) {
12443 let argsStatement = '';
12444 let args = '';
12445
12446 if (method.getParameters().length > 0) {
12447 const argsTypes = method.getParameters().map(param => this.getTypeText(param, this.getType(param))).join(',');
12448 argsStatement = `const args = syscall('Neo.Runtime.GetArgument', 1) as [${argsTypes}];\n`;
12449 args = method.getParameters().map((param, idx) => `args[${idx}]`).join(', ');
12450 }
12451
12452 let call = `contract.${name}(${args})`;
12453
12454 if (!isVoid(method.getReturnType())) {
12455 call = `syscall('Neo.Runtime.Return', ${call})`;
12456 }
12457
12458 methodSwitch = `
12459 if (method === '${name}') {
12460 ${argsStatement}${call};
12461 }
12462 `;
12463 } else if (Ast.TypeGuards.isGetAccessorDeclaration(method) || Ast.TypeGuards.isPropertyDeclaration(method) || Ast.TypeGuards.isParameterDeclaration(method)) {
12464 methodSwitch = `
12465 if (method === '${name}') {
12466 syscall('Neo.Runtime.Return', contract.${name});
12467 }
12468 `;
12469 } else {
12470 const param = method.getParameters()[0];
12471 const typeText = this.getTypeText(param, this.getType(param));
12472 methodSwitch = `
12473 if (method === 'set${name[0].toUpperCase()}${name.slice(1)}') {
12474 contract.${name} = (syscall('Neo.Runtime.GetArgument', 1) as [${typeText}])[0];
12475 }
12476 `;
12477 }
12478
12479 applicationSwitches.push(methodSwitch);
12480
12481 if (func.verify) {
12482 verifySwitches.push(methodSwitch);
12483 }
12484
12485 functions.push(func);
12486 }
12487
12488 const applicationFallback = applicationSwitches.length === 0 ? 'throw new Error(' : ` else {
12489 throw new Error('Unknown method');
12490 }`;
12491 let verifyFallback = `
12492 if (!syscall('Neo.Runtime.CheckWitness', contract.owner)) {
12493 throw new Error('Invalid witness');
12494 }
12495 `;
12496
12497 if (verifySwitches.length > 0) {
12498 verifyFallback = `else {
12499 ${verifyFallback}
12500 }`;
12501 }
12502
12503 const statements = `
12504 const contract = new ${this.smartContract.getName()}();
12505 const method = syscall('Neo.Runtime.GetArgument', 0) as string;
12506 if (syscall('Neo.Runtime.GetTrigger') === 0x10) {
12507 ${applicationSwitches.join(' else ')}
12508 ${applicationFallback}
12509 } else if (syscall('Neo.Runtime.GetTrigger') === 0x00) {
12510 ${verifySwitches.join(' else ')}
12511 ${verifyFallback}
12512 } else {
12513 throw new Error('Unsupported trigger');
12514 }
12515 `;
12516 file.addStatements(statements);
12517 return {
12518 ast: this.ast,
12519 sourceFile: file,
12520 abi: {
12521 functions
12522 },
12523 context: this.context
12524 };
12525 }
12526
12527 visit(node) {
12528 if (node == null) {
12529 return;
12530 }
12531
12532 const transpiler = this.transpilers[node.compilerNode.kind];
12533
12534 if (transpiler == null) {
12535 node.getChildren().forEach(child => {
12536 this.visit(child);
12537 });
12538 } else {
12539 transpiler.visitNode(this, node);
12540 }
12541 }
12542
12543 addEvent(node, name, parameters) {// TODO: Change how events work.
12544 // if (this.events[name] != null) {
12545 // this.reportError(node, 'Duplicate event.', DiagnosticCode.UNSUPPORTED_SYNTAX);
12546 // }
12547 // this.events[name] = parameters;
12548 }
12549
12550 isSmartContract(node) {
12551 return node === this.smartContract || node.getDerivedClasses().some(derived => this.isSmartContract(derived));
12552 }
12553
12554 getType(node) {
12555 return this.context.getType(node);
12556 }
12557
12558 getTypeOfSymbol(symbol, node) {
12559 return this.context.getTypeOfSymbol(symbol, node);
12560 }
12561
12562 getSymbol(node) {
12563 return this.context.getSymbol(node);
12564 }
12565
12566 isOnlyGlobal(node, type, name) {
12567 return this.context.isOnlyGlobal(node, type, name);
12568 }
12569
12570 isLibSymbol(node, symbol, name) {
12571 return this.context.isLibSymbol(node, symbol, name);
12572 }
12573
12574 isOnlyLib(node, type, name) {
12575 return this.context.isOnlyLib(node, type, name);
12576 }
12577
12578 isLibAlias(identifier, name) {
12579 return this.context.isLibAlias(identifier, name);
12580 }
12581
12582 isFixedType(node, type) {
12583 if (type == null) {
12584 return false;
12585 }
12586
12587 return this.isLibSymbol(node, type.getAliasSymbol() || type.getSymbol(), 'Fixed');
12588 }
12589
12590 reportError(node, message, code) {
12591 this.context.reportError(node, message, code);
12592 }
12593
12594 reportUnsupported(node) {
12595 this.context.reportUnsupported(node);
12596 }
12597
12598 assertNotNull(value) {
12599 return this.context.assertNotNull(value);
12600 }
12601
12602 filterNotNull(value) {
12603 return value != null;
12604 }
12605
12606 processProperty(symbol) {
12607 const decls = symbol.getDeclarations().filter(symbolDecl => !Ast.TypeGuards.isMethodDeclaration(symbolDecl) || symbolDecl.isImplementation());
12608
12609 if (!(decls.length === 1 || decls.length === 2 && decls.some(accessor => Ast.TypeGuards.isGetAccessorDeclaration(accessor)) && decls.some(accessor => Ast.TypeGuards.isSetAccessorDeclaration(accessor)))) {
12610 this.reportError(symbol.getDeclarations()[0], 'Invalid contract function. Resolved to multiple implementation declarations.', DiagnosticCode.INVALID_CONTRACT_METHOD);
12611 return [];
12612 }
12613
12614 const decl = decls[0];
12615
12616 if (!(Ast.TypeGuards.isMethodDeclaration(decl) || Ast.TypeGuards.isPropertyDeclaration(decl) || Ast.TypeGuards.isGetAccessorDeclaration(decl) || Ast.TypeGuards.isSetAccessorDeclaration(decl) || Ast.TypeGuards.isParameterDeclaration(decl))) {
12617 return [];
12618 }
12619
12620 const name = symbol.getName();
12621 const type = this.getTypeOfSymbol(symbol, decl);
12622
12623 if (type == null) {
12624 return [];
12625 }
12626
12627 if (Ast.TypeGuards.isGetAccessorDeclaration(decl) || Ast.TypeGuards.isSetAccessorDeclaration(decl)) {
12628 const getDecl = Ast.TypeGuards.isGetAccessorDeclaration(decl) ? decl : decl.getGetAccessor();
12629 const setDecl = Ast.TypeGuards.isSetAccessorDeclaration(decl) ? decl : decl.getSetAccessor();
12630 const result = [];
12631
12632 if (getDecl != null && isPublic(getDecl)) {
12633 result.push([getDecl, {
12634 name,
12635 constant: true,
12636 verify: this.hasVerify(getDecl),
12637 returnType: this.toABIReturn(getDecl, type, this.getIdentifier(getDecl.getReturnTypeNode())) || {
12638 type: 'ByteArray'
12639 }
12640 }]);
12641 }
12642
12643 if (setDecl != null && isPublic(setDecl)) {
12644 result.push([setDecl, {
12645 name,
12646 constant: false,
12647 verify: this.hasVerify(setDecl),
12648 parameters: [_objectSpread({
12649 name: setDecl.getParameters()[0].getNameOrThrow()
12650 }, this.toABIReturn(setDecl, type, this.getIdentifier(setDecl.getParameters()[0].getTypeNode())) || {
12651 type: 'ByteArray'
12652 })],
12653 returnType: {
12654 type: 'Void'
12655 }
12656 }]);
12657 }
12658
12659 return result;
12660 }
12661
12662 if (!isPublic(decl)) {
12663 return [];
12664 }
12665
12666 const verify = this.hasVerify(decl);
12667
12668 if (Ast.TypeGuards.isMethodDeclaration(decl)) {
12669 const callSignatures = type.getCallSignatures();
12670
12671 if (callSignatures.length !== 1) {
12672 this.reportError(decl, 'Invalid contract function. Resolved to multiple call signatures.', DiagnosticCode.INVALID_CONTRACT_METHOD);
12673 return [];
12674 }
12675
12676 const callSignature = callSignatures[0];
12677 const parameters = callSignature.getParameters().map(parameter => this.toABIParameter(parameter)).filter(this.filterNotNull);
12678 const returnType = this.toABIReturn(decl, callSignature.getReturnType(), this.getIdentifier(decl.getReturnTypeNode()));
12679 const constant = this.hasDecorator(decl, 'constant');
12680 const func = {
12681 name,
12682 constant,
12683 verify,
12684 parameters,
12685 returnType: returnType || {
12686 type: 'ByteArray'
12687 }
12688 };
12689 return [[decl, func]];
12690 } else {
12691 const returnType = this.toABIReturn(decl, type, this.getIdentifier(decl.getTypeNode()));
12692 const func = {
12693 name,
12694 constant: true,
12695 verify,
12696 returnType: returnType || {
12697 type: 'ByteArray'
12698 }
12699 };
12700 return [[decl, func]];
12701 }
12702 }
12703
12704 hasVerify(decl) {
12705 return this.hasDecorator(decl, 'verify');
12706 }
12707
12708 hasDecorator(decl, name) {
12709 return decl.getDecorators().some(decorator => this.isOnlyLib(decorator.getExpression(), this.getType(decorator.getExpression()), name));
12710 }
12711
12712 toABIParameter(param) {
12713 const decl = this.assertNotNull(param.getDeclarations()[0]);
12714 const id = Ast.TypeGuards.isParameterDeclaration(decl) ? this.getIdentifier(decl.getTypeNode()) : undefined;
12715 const type = this.toABIReturn(decl, this.getTypeOfSymbol(param, decl), id);
12716
12717 if (type == null) {
12718 return undefined;
12719 }
12720
12721 return _objectSpread({}, type, {
12722 name: param.getName()
12723 });
12724 }
12725
12726 toABIReturn(node, resolvedType, typeIdentifier) {
12727 if (resolvedType == null && typeIdentifier == null) {
12728 this.reportError(node, 'Could not detect ABI, unknown type.', DiagnosticCode.UNKNOWN_TYPE);
12729 return undefined;
12730 }
12731
12732 if (isOnlyBoolean(resolvedType)) {
12733 return {
12734 type: 'Boolean'
12735 };
12736 } else if (this.isLibAlias(typeIdentifier, 'Address')) {
12737 return {
12738 type: 'Hash160'
12739 };
12740 } else if (this.isLibAlias(typeIdentifier, 'Hash256')) {
12741 return {
12742 type: 'Hash256'
12743 };
12744 } else if (this.isLibAlias(typeIdentifier, 'Signature')) {
12745 return {
12746 type: 'Signature'
12747 };
12748 } else if (this.isLibAlias(typeIdentifier, 'PublicKey')) {
12749 return {
12750 type: 'PublicKey'
12751 };
12752 } else if (isVoid(resolvedType)) {
12753 return {
12754 type: 'Void'
12755 };
12756 } else if (isOnlyString(resolvedType)) {
12757 return {
12758 type: 'String'
12759 };
12760 } else if (isOnlyNumberLiteral(resolvedType)) {
12761 return {
12762 type: 'Integer',
12763 decimals: 0
12764 };
12765 } else if (this.isFixedType(node, resolvedType) && resolvedType != null) {
12766 const decimals = this.getFixedDecimals(resolvedType);
12767 return {
12768 type: 'Integer',
12769 decimals
12770 };
12771 } else if (isOnlyNumber(resolvedType)) {
12772 return {
12773 type: 'Integer',
12774 decimals: 0
12775 };
12776 } else if (isOnlyArray(resolvedType) && resolvedType != null) {
12777 const value = this.toABIReturn(node, resolvedType.getTypeArguments()[0]);
12778
12779 if (value != null) {
12780 return {
12781 type: 'Array',
12782 value
12783 };
12784 }
12785 } else if (this.isOnlyGlobal(node, resolvedType, 'Buffer')) {
12786 return {
12787 type: 'ByteArray'
12788 };
12789 } else {
12790 this.reportError(node, 'Invalid contract type.', DiagnosticCode.INVALID_CONTRACT_TYPE);
12791 }
12792
12793 return undefined;
12794 }
12795
12796 getFixedDecimals(type) {
12797 return type.getUnionTypes()[1].getIntersectionTypes()[1].compilerType.value;
12798 }
12799
12800 getIdentifier(node) {
12801 return node == null ? node : node.getFirstChildByKind(Ast.SyntaxKind.Identifier);
12802 }
12803
12804 getTypeText(node, type) {
12805 let typeText = 'any';
12806
12807 if (type == null) {
12808 this.reportError(node, 'Unknown type', DiagnosticCode.UNKNOWN_TYPE);
12809 } else if (this.isFixedType(node, type)) {
12810 typeText = 'number';
12811 } else {
12812 typeText = type.getText();
12813 }
12814
12815 return typeText;
12816 }
12817
12818}
12819
12820const transpile = ({
12821 ast,
12822 smartContract,
12823 context: contextIn
12824}) => {
12825 const context = contextIn || new Context(getGlobals(ast), getLibs(ast), getLibAliases(ast));
12826 const transpiler = new NEOTranspiler(context, ast, smartContract);
12827 return transpiler.process();
12828};
12829
12830const compileContract = async ({
12831 dir,
12832 filePath,
12833 name
12834}) => {
12835 const ast = await getAst(dir);
12836 const smartContract = ast.getSourceFileOrThrow(filePath).getClassOrThrow(name);
12837 const {
12838 ast: transpiledAst,
12839 sourceFile,
12840 abi,
12841 context
12842 } = transpile({
12843 ast,
12844 smartContract
12845 });
12846 const {
12847 code,
12848 context: finalContext
12849 } = compile({
12850 ast: transpiledAst,
12851 sourceFile,
12852 context
12853 });
12854 return {
12855 code,
12856 diagnostics: finalContext.diagnostics,
12857 abi
12858 };
12859};
12860
12861const executeScript = async (monitor, ast, sourceFile, prelude = Buffer.alloc(0, 0)) => {
12862 const blockchain = await Blockchain.create({
12863 log: () => {// tslint:disable-next-line
12864 },
12865 settings: nodeNeoSettings.test,
12866 storage: levelUpStorage({
12867 context: {
12868 messageMagic: nodeNeoSettings.test.messageMagic
12869 },
12870 db: levelup( // @ts-ignore
12871 memdown())
12872 }),
12873 vm,
12874 monitor
12875 });
12876 const {
12877 code: compiledCode,
12878 context
12879 } = compile({
12880 ast,
12881 sourceFile
12882 });
12883 const error = context.diagnostics.filter(diagnostic => diagnostic.category === Ast.DiagnosticCategory.Error)[0];
12884
12885 if (error != null) {
12886 throw new Error(`Compilation error: ${error.messageText} at ${error.source}`);
12887 }
12888
12889 const result = await blockchain.invokeScript(Buffer.concat([prelude, compiledCode]), monitor);
12890 return result;
12891};
12892
12893const scan = async dir => {
12894 const ast = await getAst(dir);
12895 const libs = getLibs(ast);
12896 const smartContract = libs.SmartContract.getDeclarations()[0];
12897 return smartContract.getDerivedClasses().reduce((acc, derived) => {
12898 if (!derived.isAbstract()) {
12899 const file = derived.getSourceFile().getFilePath();
12900
12901 if (acc[file] == null) {
12902 acc[file] = [];
12903 }
12904
12905 acc[file].push(derived.getNameOrThrow());
12906 }
12907
12908 return acc;
12909 }, {});
12910};
12911
12912const findContract = async (dir, name) => {
12913 const contracts = await scan(dir);
12914 const found = Object.entries(contracts).map(([path$$1, contractNames]) => ({
12915 path: path$$1,
12916 contractNames: contractNames.filter(contractName => name === contractName)
12917 })).filter(({
12918 contractNames
12919 }) => contractNames.length > 0);
12920
12921 if (found.length > 1) {
12922 throw new Error(`Found multiple contracts with name ${name}`);
12923 } else if (found.length === 0) {
12924 throw new Error(`Cound not find contract with name ${name}`);
12925 }
12926
12927 return {
12928 filePath: found[0].path,
12929 name
12930 };
12931};
12932
12933exports.compile = compile;
12934exports.compileScript = compileScript;
12935exports.compileContract = compileContract;
12936exports.executeScript = executeScript;
12937exports.findContract = findContract;
12938exports.scan = scan;
12939//# sourceMappingURL=index.js.map