UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

77 lines (75 loc) 3.52 kB
import { tsUtils } from '@neo-one/ts-utils'; import ts from 'typescript'; import * as constants from '../../constants'; import { NodeCompiler } from '../NodeCompiler'; export class SwitchStatementCompiler extends NodeCompiler { constructor() { super(...arguments); this.kind = ts.SyntaxKind.SwitchStatement; } visitNode(sb, node, optionsIn) { const options = sb.pushValueOptions(optionsIn); sb.withProgramCounter((pc) => { const switchExpr = tsUtils.expression.getExpression(node); const switchExprType = sb.context.analysis.getType(switchExpr); let breakOptions = sb.breakPCOptions(sb.noPushValueOptions(options), pc.getLast()); if (breakOptions.finallyPC !== undefined) { breakOptions = sb.finallyPCOptions(breakOptions, pc.getLast()); } const caseBlock = tsUtils.statement.getCaseBlock(node); const clauses = tsUtils.statement.getClauses(caseBlock); const { found: defaultFound, statements: defaultClauseStatements } = clauses.reduce((acc, clause) => { const { found, statements } = acc; if (found) { return { found, statements: statements.concat(tsUtils.statement.getStatements(clause)), }; } if (ts.isDefaultClause(clause)) { return { found: true, statements: tsUtils.statement.getStatements(clause) }; } return { found: false, statements }; }, { found: false, statements: [] }); const matched = sb.scope.addUnique(); const val = sb.scope.addUnique(); sb.visit(switchExpr, options); sb.scope.set(sb, node, options, val); sb.emitPushBoolean(switchExpr, false); sb.scope.set(sb, node, options, matched); clauses.forEach((clause) => { if (ts.isDefaultClause(clause)) { return; } sb.emitHelper(clause, options, sb.helpers.if({ condition: () => { const expr = tsUtils.expression.getExpression(clause); sb.scope.get(sb, node, options, val); sb.visit(expr, options); sb.emitHelper(expr, options, sb.helpers.equalsEqualsEquals({ leftType: switchExprType, rightType: sb.context.analysis.getType(expr), })); sb.scope.get(sb, node, options, matched); sb.emitOp(node, 'BOOLOR'); }, whenTrue: () => { sb.emitPushBoolean(node, true); sb.scope.set(sb, node, options, matched); tsUtils.statement.getStatements(clause).forEach((statement) => { sb.visit(statement, breakOptions); }); }, })); }); if (defaultFound) { defaultClauseStatements.forEach((statement) => { sb.visit(statement, breakOptions); }); } sb.emitPushInt(node, constants.BREAK_COMPLETION); }); sb.emitOp(node, 'DROP'); } } //# sourceMappingURL=SwitchStatementCompiler.js.map