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