@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
144 lines (142 loc) • 6.34 kB
JavaScript
import { tsUtils } from '@neo-one/ts-utils';
import ts from 'typescript';
import { Helper } from '../Helper';
export class ParametersHelper extends Helper {
constructor(options) {
super();
this.params = options.params;
this.asArgsArr = options.asArgsArr === undefined ? false : options.asArgsArr;
this.map = options.map;
this.mapParam = options.mapParam;
}
emit(sb, node, optionsIn) {
const options = sb.pushValueOptions(optionsIn);
const params = this.params;
const restElement = params.find((param) => tsUtils.parameter.isRestParameter(param));
let parameters = restElement === undefined ? [...params] : params.slice(0, -1);
parameters =
parameters.length > 0 && tsUtils.node.getName(parameters[0]) === 'this' ? parameters.slice(1) : parameters;
if (this.asArgsArr) {
sb.emitPushInt(node, 0);
sb.emitOp(node, 'NEWARRAY');
sb.emitOp(node, 'SWAP');
}
parameters.forEach((param, idx) => {
const nameNode = tsUtils.node.getNameNode(param);
const initializer = tsUtils.initializer.getInitializer(param);
if (initializer !== undefined) {
sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
condition: () => {
sb.emitOp(param, 'DUP');
sb.emitOp(param, 'ARRAYSIZE');
sb.emitPushInt(param, idx);
sb.emitOp(param, 'LTE');
},
whenTrue: () => {
sb.visit(initializer, sb.pushValueOptions(options));
},
whenFalse: () => {
sb.emitOp(param, 'DUP');
sb.emitPushInt(param, idx);
sb.emitOp(param, 'PICKITEM');
if (this.mapParam !== undefined) {
this.mapParam(param, options);
}
sb.emitOp(param, 'DUP');
sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
condition: () => {
sb.emitHelper(param, sb.pushValueOptions(options), sb.helpers.isUndefined);
},
whenTrue: () => {
sb.emitOp(param, 'DROP');
sb.visit(initializer, sb.pushValueOptions(options));
},
}));
},
}));
}
else if (tsUtils.parameter.isOptional(param)) {
sb.emitHelper(param, sb.noPushValueOptions(options), sb.helpers.if({
condition: () => {
sb.emitOp(param, 'DUP');
sb.emitOp(param, 'ARRAYSIZE');
sb.emitPushInt(param, idx);
sb.emitOp(param, 'LTE');
},
whenTrue: () => {
sb.emitHelper(param, sb.pushValueOptions(options), sb.helpers.wrapUndefined);
},
whenFalse: () => {
sb.emitOp(param, 'DUP');
sb.emitPushInt(param, idx);
sb.emitOp(param, 'PICKITEM');
if (this.mapParam !== undefined) {
this.mapParam(param, options);
}
},
}));
}
else {
sb.emitOp(param, 'DUP');
sb.emitPushInt(param, idx);
sb.emitOp(param, 'PICKITEM');
if (this.mapParam !== undefined) {
this.mapParam(param, options);
}
}
if (this.map !== undefined) {
this.map(param, options);
}
if (this.asArgsArr) {
sb.emitOp(node, 'ROT');
sb.emitOp(node, 'TUCK');
sb.emitOp(node, 'SWAP');
sb.emitOp(node, 'APPEND');
sb.emitOp(node, 'SWAP');
}
else if (ts.isIdentifier(nameNode)) {
sb.scope.add(tsUtils.node.getText(nameNode));
sb.scope.set(sb, node, options, tsUtils.node.getText(nameNode));
}
else if (ts.isArrayBindingPattern(nameNode)) {
const paramType = sb.context.analysis.getType(param);
sb.emitHelper(nameNode, options, sb.helpers.arrayBinding({ type: paramType }));
}
else {
const paramType = sb.context.analysis.getType(param);
sb.emitHelper(nameNode, options, sb.helpers.objectBinding({ type: paramType }));
}
});
if (restElement === undefined) {
sb.emitOp(node, 'DROP');
}
else {
sb.emitPushInt(restElement, parameters.length);
sb.emitHelper(restElement, options, sb.helpers.arrSlice({ hasEnd: false }));
const mapParam = this.mapParam;
if (mapParam !== undefined) {
sb.emitHelper(restElement, options, sb.helpers.arrMap({
map: (innerOptions) => mapParam(restElement, innerOptions),
}));
}
if (this.asArgsArr) {
const map = this.map;
if (map !== undefined) {
sb.emitHelper(restElement, options, sb.helpers.arrMap({
map: (innerOptions) => map(restElement, innerOptions, true),
}));
}
sb.emitHelper(node, options, sb.helpers.arrConcat);
}
else {
sb.emitHelper(restElement, options, sb.helpers.wrapArray);
if (this.map !== undefined) {
this.map(restElement, options);
}
sb.scope.add(tsUtils.node.getNameOrThrow(restElement));
sb.scope.set(sb, restElement, options, tsUtils.node.getNameOrThrow(restElement));
}
}
}
}
//# sourceMappingURL=ParametersHelper.js.map