@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
156 lines (154 loc) • 7.49 kB
JavaScript
;
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