UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

173 lines (171 loc) 8.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ForOfStatementCompiler = 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 entries_1 = require("../builtins/array/entries"); const constants_1 = require("../constants"); const NodeCompiler_1 = require("../NodeCompiler"); class ForOfStatementCompiler extends NodeCompiler_1.NodeCompiler { constructor() { super(...arguments); this.kind = typescript_1.default.SyntaxKind.ForOfStatement; } visitNode(sb, node, optionsIn) { const options = sb.pushValueOptions(optionsIn); const initializer = ts_utils_1.tsUtils.statement.getInitializer(node); if (!typescript_1.default.isVariableDeclarationList(initializer)) { sb.context.reportUnsupported(initializer); return; } const variables = ts_utils_1.tsUtils.variable.getDeclarations(initializer); if (variables.length !== 1) { sb.context.reportUnsupported(initializer); return; } const variable = variables[0]; const nameNode = ts_utils_1.tsUtils.node.getNameNode(variable); const variableType = sb.context.analysis.getType(nameNode); const expression = ts_utils_1.tsUtils.expression.getExpression(node); const statement = ts_utils_1.tsUtils.statement.getStatement(node); const each = (innerOptions) => { if (typescript_1.default.isIdentifier(nameNode)) { sb.scope.add(ts_utils_1.tsUtils.node.getText(nameNode)); sb.scope.set(sb, nameNode, innerOptions, ts_utils_1.tsUtils.node.getText(nameNode)); } else if (typescript_1.default.isArrayBindingPattern(nameNode)) { sb.emitHelper(nameNode, innerOptions, sb.helpers.arrayBinding({ type: variableType })); } else { sb.emitHelper(nameNode, innerOptions, sb.helpers.objectBinding({ type: variableType })); } sb.visit(statement, sb.noPushValueOptions(innerOptions)); }; const handleOther = (innerOptions) => { sb.emitOp(node, 'DROP'); sb.emitHelper(node, innerOptions, sb.helpers.throwTypeError); }; const handleArray = (innerOptions, withIndex = false, arrEach = each) => { sb.emitHelper(expression, innerOptions, sb.helpers.unwrapArray); sb.emitHelper(node, innerOptions, sb.helpers.arrForEach({ withIndex, each: arrEach, })); }; const handleArrayStorage = (innerOptions) => { sb.emitHelper(node, sb.noPushValueOptions(innerOptions), sb.helpers.forEachValStructuredStorage({ type: constants_1.Types.ArrayStorage, each, })); }; const handleMap = (innerOptions) => { sb.emitHelper(expression, innerOptions, sb.helpers.unwrapMap); sb.emitSysCall(expression, 'Neo.Iterator.Create'); sb.emitHelper(node, innerOptions, sb.helpers.rawIteratorForEach({ deserializeKey: true, each: (innerInnerOptionsIn) => { const innerInnerOptions = sb.pushValueOptions(innerInnerOptionsIn); sb.emitPushInt(node, 2); sb.emitOp(node, 'PACK'); sb.emitHelper(node, innerInnerOptions, sb.helpers.wrapArray); each(innerInnerOptions); }, })); }; const handleMapStorage = (innerOptions) => { sb.emitHelper(node, sb.noPushValueOptions(innerOptions), sb.helpers.forEachStructuredStorage({ type: constants_1.Types.MapStorage, each: (innerInnerOptionsIn) => { const innerInnerOptions = sb.pushValueOptions(innerInnerOptionsIn); sb.emitPushInt(node, 2); sb.emitOp(node, 'PACK'); sb.emitHelper(node, innerInnerOptions, sb.helpers.wrapArray); each(innerInnerOptions); }, })); }; const handleSet = (innerOptions) => { sb.emitHelper(expression, innerOptions, sb.helpers.unwrapSet); sb.emitSysCall(expression, 'Neo.Iterator.Create'); sb.emitHelper(node, innerOptions, sb.helpers.rawIteratorForEachKey({ each, deserializeKey: true })); }; const handleSetStorage = (innerOptions) => { sb.emitHelper(node, sb.noPushValueOptions(innerOptions), sb.helpers.forEachKeyStructuredStorage({ type: constants_1.Types.SetStorage, each, })); }; const handleIterableIterator = (innerOptions) => { sb.emitHelper(node, sb.noPushValueOptions(innerOptions), sb.helpers.iterableIteratorForEach({ each, })); }; const handleIterable = (innerOptions) => { sb.emitHelper(node, innerOptions, sb.helpers.forIterableType({ array: handleArray, map: handleMap, set: handleSet, arrayStorage: handleArrayStorage, mapStorage: handleMapStorage, setStorage: handleSetStorage, iterableIterator: handleIterableIterator, defaultCase: handleOther, })); }; if (typescript_1.default.isCallExpression(expression)) { const valueExpression = ts_utils_1.tsUtils.expression.getExpression(expression); if (typescript_1.default.isPropertyAccessExpression(valueExpression)) { const value = ts_utils_1.tsUtils.expression.getExpression(valueExpression); const name = ts_utils_1.tsUtils.node.getNameNode(valueExpression); const builtinProp = sb.context.builtins.getMember(value, name); if (builtinProp !== undefined && builtinProp instanceof entries_1.ArrayEntries) { sb.visit(value, options); handleArray(options, true, (innerOptions) => { sb.emitOp(variable, 'SWAP'); sb.emitHelper(variable, sb.pushValueOptions(innerOptions), sb.helpers.wrapNumber); sb.emitPushInt(variable, 2); sb.emitOp(variable, 'PACK'); sb.emitHelper(variable, sb.pushValueOptions(innerOptions), sb.helpers.wrapArray); each(innerOptions); }); return; } } } sb.visit(expression, options); sb.emitHelper(node, options, sb.helpers.forBuiltinType({ type: sb.context.analysis.getType(expression), array: handleArray, arrayStorage: handleArrayStorage, boolean: handleOther, buffer: handleOther, null: handleOther, number: handleOther, object: handleOther, string: handleOther, symbol: handleOther, undefined: handleOther, map: handleMap, mapStorage: handleMapStorage, set: handleSet, setStorage: handleSetStorage, error: handleOther, forwardValue: handleOther, iteratorResult: handleOther, iterable: handleIterable, iterableIterator: handleIterableIterator, transaction: handleOther, output: handleOther, attribute: handleOther, input: handleOther, account: handleOther, asset: handleOther, contract: handleOther, header: handleOther, block: handleOther, })); } } exports.ForOfStatementCompiler = ForOfStatementCompiler; //# sourceMappingURL=ForOfStatementCompiler.js.map