UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

156 lines (154 loc) 7.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ArgumentsHelper = void 0; const tslib_1 = require("tslib"); const ts_utils_1 = require("@neo-one/ts-utils"); const lodash_1 = tslib_1.__importDefault(require("lodash")); const typescript_1 = tslib_1.__importDefault(require("typescript")); const DiagnosticCode_1 = require("../../../DiagnosticCode"); const DiagnosticMessage_1 = require("../../../DiagnosticMessage"); const constants_1 = require("../../constants"); const Helper_1 = require("../Helper"); const types_1 = require("../types"); class ArgumentsHelper extends Helper_1.Helper { emit(sb, node, optionsIn) { const options = sb.pushValueOptions(optionsIn); const args = typescript_1.default.isArrayLiteralExpression(node) ? ts_utils_1.tsUtils.expression.getElements(node) : ts_utils_1.tsUtils.argumented.getArgumentsArray(node); if (!typescript_1.default.isArrayLiteralExpression(node) && args.length > 0) { const signatureTypes = sb.context.analysis.extractSignaturesForCall(node, { error: true }); if (signatureTypes !== undefined) { args.forEach((arg, idx) => { const argType = sb.context.analysis.getType(arg); if (argType !== undefined) { const mismatch = signatureTypes.some(({ paramDecls, paramTypes }) => { const paramDecl = paramDecls[Math.min(idx, paramDecls.length - 1)]; let paramTypeIn = paramTypes.get(paramDecl); if (paramTypeIn !== undefined && ts_utils_1.tsUtils.parameter.isRestParameter(paramDecl)) { paramTypeIn = ts_utils_1.tsUtils.type_.getArrayType(paramTypeIn); } const paramType = paramTypeIn; const hasBuiltins = types_1.getHasBuiltins(sb.context, arg, argType); return (paramType === undefined || hasBuiltins.some((hasBuiltin) => !hasBuiltin(sb.context, paramDecl, paramType))); }); if (mismatch) { sb.context.reportError(arg, DiagnosticCode_1.DiagnosticCode.InvalidBuiltinUsage, DiagnosticMessage_1.DiagnosticMessage.InvalidBuiltinCallArgument); } } }); } } if (args.some((arg) => typescript_1.default.isSpreadElement(arg))) { sb.emitPushInt(node, 0); sb.emitOp(node, 'NEWARRAY'); args.forEach((arg) => { const handleArrayLike = () => { sb.emitOp(arg, 'TUCK'); sb.emitOp(arg, 'SWAP'); sb.emitOp(arg, 'APPEND'); }; const handleArray = (innerOptions) => { sb.emitHelper(arg, innerOptions, sb.helpers.unwrapArray); sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.arrReduce({ each: handleArrayLike, })); }; const handleMapLike = (innerOption) => { sb.emitOp(arg, 'ROT'); sb.emitOp(arg, 'ROT'); sb.emitPushInt(arg, 2); sb.emitOp(arg, 'PACK'); sb.emitHelper(arg, innerOption, sb.helpers.wrapArray); sb.emitOp(arg, 'OVER'); sb.emitOp(arg, 'SWAP'); sb.emitOp(arg, 'APPEND'); }; const handleMap = (innerOptions) => { sb.emitHelper(arg, innerOptions, sb.helpers.unwrapMap); sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.mapReduce({ deserializeKey: true, each: handleMapLike, })); }; const handleSetLike = () => { sb.emitOp(arg, 'ROT'); sb.emitOp(arg, 'DROP'); sb.emitOp(arg, 'TUCK'); sb.emitOp(arg, 'SWAP'); sb.emitOp(arg, 'APPEND'); }; const handleSet = (innerOptions) => { sb.emitHelper(arg, innerOptions, sb.helpers.unwrapSet); sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.mapReduce({ deserializeKey: true, each: handleSetLike, })); }; const handleArrayStorage = (innerOptions) => { sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.structuredStorageReduceVal({ type: constants_1.Types.ArrayStorage, each: handleArrayLike, })); }; const handleMapStorage = (innerOptions) => { sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.structuredStorageReduce({ type: constants_1.Types.MapStorage, each: handleMapLike, })); }; const handleSetStorage = (innerOptions) => { sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.structuredStorageReduce({ type: constants_1.Types.SetStorage, each: handleSetLike, })); }; const handleIterableIterator = (innerOptions) => { sb.emitOp(arg, 'SWAP'); sb.emitHelper(arg, innerOptions, sb.helpers.iterableIteratorReduce({ each: handleArrayLike, })); }; if (typescript_1.default.isSpreadElement(arg)) { const expr = ts_utils_1.tsUtils.expression.getExpression(arg); sb.visit(expr, options); sb.emitHelper(arg, options, sb.helpers.forIterableType({ type: sb.context.analysis.getType(expr), array: handleArray, map: handleMap, set: handleSet, arrayStorage: handleArrayStorage, mapStorage: handleMapStorage, setStorage: handleSetStorage, iterableIterator: handleIterableIterator, })); } else { sb.emitOp(node, 'DUP'); sb.visit(arg, options); sb.emitOp(node, 'APPEND'); } }); } else { const reversedElements = lodash_1.default.reverse([...args]); reversedElements.forEach((arg) => { sb.visit(arg, options); }); sb.emitPushInt(node, args.length); sb.emitOp(node, 'PACK'); } if (!optionsIn.pushValue) { sb.emitOp(node, 'DROP'); } } } exports.ArgumentsHelper = ArgumentsHelper; //# sourceMappingURL=ArgumentsHelper.js.map