UNPKG

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