UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

150 lines (148 loc) 6.79 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ArrayBindingHelper = void 0; const tslib_1 = require("tslib"); const ts_utils_1 = require("@neo-one/ts-utils"); const typescript_1 = tslib_1.__importDefault(require("typescript")); const types_1 = require("../types"); class ArrayBindingHelper extends types_1.TypedHelper { constructor(options) { super(options); this.value = options.value; } emit(sb, node, optionsIn) { const options = sb.pushValueOptions(optionsIn); const restElement = node.elements.find((element) => ts_utils_1.tsUtils.node.getDotDotDotToken(element) !== undefined); const elements = restElement === undefined ? [...node.elements] : node.elements.slice(0, -1); const handleCommon = (setup, getNext, getRemaining) => (innerOptions) => { setup(innerOptions); elements.forEach((element, idx) => { if (typescript_1.default.isOmittedExpression(element)) { return; } const name = ts_utils_1.tsUtils.node.getNameNode(element); const initializer = ts_utils_1.tsUtils.initializer.getInitializer(element); const elementType = sb.context.analysis.getType(name); if (typescript_1.default.isIdentifier(name)) { sb.scope.add(ts_utils_1.tsUtils.node.getText(name)); } sb.emitOp(element, 'DUP'); getNext(element, innerOptions, idx); if (initializer !== undefined) { sb.emitHelper(node, options, sb.helpers.if({ condition: () => { sb.emitOp(node, 'DUP'); sb.emitHelper(node, options, sb.helpers.isUndefined); }, whenTrue: () => { sb.emitOp(node, 'DROP'); sb.visit(initializer, options); }, })); } if (typescript_1.default.isIdentifier(name)) { sb.scope.set(sb, node, options, ts_utils_1.tsUtils.node.getText(name)); } else if (typescript_1.default.isArrayBindingPattern(name)) { sb.emitHelper(name, options, sb.helpers.arrayBinding({ type: elementType })); } else { sb.emitHelper(name, options, sb.helpers.objectBinding({ type: elementType })); } }); if (restElement === undefined) { sb.emitOp(node, 'DROP'); } else { sb.scope.add(ts_utils_1.tsUtils.node.getNameOrThrow(restElement)); getRemaining(restElement, innerOptions); sb.emitHelper(node, options, sb.helpers.wrapArray); sb.scope.set(sb, node, options, ts_utils_1.tsUtils.node.getNameOrThrow(restElement)); } }; const handleArray = handleCommon(() => { }, (element, innerOptions, idx) => { sb.emitPushInt(element, idx); sb.emitHelper(element, innerOptions, sb.helpers.getArrayIndex); }, (element, innerOptions) => { sb.emitHelper(element, innerOptions, sb.helpers.unwrapArray); sb.emitPushInt(element, elements.length); sb.emitHelper(element, innerOptions, sb.helpers.arrSlice({ hasEnd: false })); }); const handleMapLike = (element) => (innerOption) => { sb.emitOp(element, 'ROT'); sb.emitOp(element, 'ROT'); sb.emitPushInt(element, 2); sb.emitOp(element, 'PACK'); sb.emitHelper(element, innerOption, sb.helpers.wrapArray); sb.emitOp(element, 'OVER'); sb.emitOp(element, 'SWAP'); sb.emitOp(element, 'APPEND'); }; const handleMap = handleCommon((innerOptions) => { sb.emitHelper(node, innerOptions, sb.helpers.unwrapMap); sb.emitSysCall(node, 'Neo.Iterator.Create'); }, (element, innerOptions) => { sb.emitOp(element, 'DUP'); sb.emitSysCall(element, 'Neo.Enumerator.Next'); sb.emitOp(element, 'DROP'); sb.emitOp(element, 'DUP'); sb.emitSysCall(element, 'Neo.Enumerator.Value'); sb.emitOp(element, 'SWAP'); sb.emitSysCall(element, 'Neo.Iterator.Key'); sb.emitSysCall(element, 'Neo.Runtime.Deserialize'); sb.emitPushInt(element, 2); sb.emitOp(element, 'PACK'); sb.emitHelper(element, innerOptions, sb.helpers.wrapArray); }, (element, innerOptions) => { sb.emitPushInt(element, 0); sb.emitOp(element, 'NEWARRAY'); sb.emitHelper(element, innerOptions, sb.helpers.rawIteratorReduce({ deserializeKey: true, each: handleMapLike(element), })); }); const handleSetLike = (element) => () => { sb.emitOp(element, 'ROT'); sb.emitOp(element, 'DROP'); sb.emitOp(element, 'TUCK'); sb.emitOp(element, 'SWAP'); sb.emitOp(element, 'APPEND'); }; const handleSet = handleCommon((innerOptions) => { sb.emitHelper(node, innerOptions, sb.helpers.unwrapSet); sb.emitSysCall(node, 'Neo.Iterator.Create'); }, (element) => { sb.emitOp(element, 'DUP'); sb.emitSysCall(element, 'Neo.Enumerator.Next'); sb.emitOp(element, 'DROP'); sb.emitSysCall(element, 'Neo.Iterator.Key'); sb.emitSysCall(element, 'Neo.Runtime.Deserialize'); }, (element, innerOptions) => { sb.emitPushInt(element, 0); sb.emitOp(element, 'NEWARRAY'); sb.emitHelper(element, innerOptions, sb.helpers.rawIteratorReduce({ deserializeKey: true, each: handleSetLike(element), })); }); const handleUnsupported = () => { sb.context.reportUnsupported(node); }; if (this.value !== undefined) { sb.visit(this.value, options); } sb.emitHelper(node, options, sb.helpers.forIterableType({ type: this.type, array: handleArray, map: handleMap, set: handleSet, arrayStorage: handleUnsupported, mapStorage: handleUnsupported, setStorage: handleUnsupported, iterableIterator: handleUnsupported, })); } } exports.ArrayBindingHelper = ArrayBindingHelper; //# sourceMappingURL=ArrayBindingHelper.js.map