@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
72 lines (70 loc) • 3.11 kB
JavaScript
import { tsUtils } from '@neo-one/ts-utils';
import ts from 'typescript';
import { NodeCompiler } from '../NodeCompiler';
export class ForInStatementCompiler extends NodeCompiler {
constructor() {
super(...arguments);
this.kind = ts.SyntaxKind.ForInStatement;
}
visitNode(sb, node, optionsIn) {
const options = sb.pushValueOptions(optionsIn);
const initializer = tsUtils.statement.getInitializer(node);
if (!ts.isVariableDeclarationList(initializer)) {
sb.context.reportUnsupported(initializer);
return;
}
const variables = tsUtils.variable.getDeclarations(initializer);
if (variables.length !== 1) {
sb.context.reportUnsupported(initializer);
return;
}
const variable = variables[0];
const expression = tsUtils.expression.getExpression(node);
const statement = tsUtils.statement.getStatement(node);
const expressionType = sb.context.analysis.getType(expression);
const handleArray = () => {
sb.emitHelper(expression, options, sb.helpers.unwrapArray);
sb.emitHelper(node, options, sb.helpers.arrForEach({
withIndex: true,
each: (innerOptions) => {
sb.emitOp(variable, 'DROP');
sb.emitHelper(variable, options, sb.helpers.wrapNumber);
sb.emitHelper(variable, options, sb.helpers.toString({ type: undefined }));
sb.emitHelper(variable, options, sb.helpers.wrapString);
sb.visit(variable, sb.setValueOptions(innerOptions));
sb.visit(statement, sb.noPushValueOptions(innerOptions));
},
}));
};
const handleObject = () => {
sb.emitHelper(node, options, sb.helpers.getPropertyObjectKeys);
sb.emitHelper(node, options, sb.helpers.arrForEach({
withIndex: false,
each: (innerOptions) => {
sb.emitHelper(variable, sb.pushValueOptions(innerOptions), sb.helpers.wrapString);
sb.visit(variable, sb.setValueOptions(sb.noPushValueOptions(innerOptions)));
sb.visit(statement, sb.noPushValueOptions(innerOptions));
},
}));
};
sb.visit(expression, options);
if (expressionType === undefined ||
(tsUtils.type_.hasArrayish(expressionType) && !tsUtils.type_.isOnlyArrayish(expressionType))) {
sb.emitHelper(expression, options, sb.helpers.if({
condition: () => {
sb.emitOp(expression, 'DUP');
sb.emitHelper(expression, options, sb.helpers.isArray);
},
whenTrue: handleArray,
whenFalse: handleObject,
}));
}
else if (tsUtils.type_.isOnlyArrayish(expressionType)) {
handleArray();
}
else {
handleObject();
}
}
}
//# sourceMappingURL=ForInStatementCompiler.js.map