@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
113 lines (111 loc) • 5.34 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TryStatementCompiler = void 0;
const tslib_1 = require("tslib");
const ts_utils_1 = require("@neo-one/ts-utils");
const utils_1 = require("@neo-one/utils");
const typescript_1 = tslib_1.__importDefault(require("typescript"));
const constants = tslib_1.__importStar(require("../../constants"));
const NodeCompiler_1 = require("../NodeCompiler");
class TryStatementCompiler extends NodeCompiler_1.NodeCompiler {
constructor() {
super(...arguments);
this.kind = typescript_1.default.SyntaxKind.TryStatement;
}
visitNode(sb, node, options) {
const catchClause = ts_utils_1.tsUtils.statement.getCatchClause(node);
const finallyBlock = ts_utils_1.tsUtils.statement.getFinallyBlock(node);
const pushFinally = () => {
if (finallyBlock !== undefined) {
sb.emitPushInt(node, constants.FINALLY_COMPLETION);
sb.emitPushInt(node, constants.FINALLY_COMPLETION);
sb.emitPushInt(node, constants.FINALLY_COMPLETION);
}
};
sb.withProgramCounter((finallyPC) => {
sb.withProgramCounter((catchPC) => {
let pcOptions = catchClause === undefined ? sb.noCatchPCOptions(options) : sb.catchPCOptions(options, catchPC.getLast());
pcOptions = finallyBlock === undefined ? pcOptions : sb.finallyPCOptions(pcOptions, finallyPC.getLast());
sb.visit(ts_utils_1.tsUtils.statement.getTryBlock(node), pcOptions);
pushFinally();
sb.emitJmp(node, 'JMP', finallyPC.getLast());
});
const finallyOptions = finallyBlock === undefined ? options : sb.finallyPCOptions(options, finallyPC.getLast());
if (catchClause !== undefined) {
const variable = ts_utils_1.tsUtils.statement.getOnlyVariableDeclaration(catchClause);
sb.emitOp(node, 'DROP');
if (variable === undefined) {
sb.emitOp(node, 'DROP');
sb.visit(ts_utils_1.tsUtils.statement.getBlock(catchClause), finallyOptions);
}
else {
sb.withScope(node, finallyOptions, (innerOptions) => {
sb.visit(variable, sb.setValueOptions(innerOptions));
sb.visit(ts_utils_1.tsUtils.statement.getBlock(catchClause), innerOptions);
});
}
pushFinally();
}
});
if (finallyBlock !== undefined) {
const completion = sb.scope.addUnique();
const val = sb.scope.addUnique();
sb.emitOp(finallyBlock, 'DROP');
sb.scope.set(sb, finallyBlock, options, completion);
sb.scope.set(sb, finallyBlock, options, val);
sb.visit(finallyBlock, options);
sb.scope.get(sb, finallyBlock, options, completion);
const condition = (value) => () => {
sb.emitOp(finallyBlock, 'DUP');
sb.emitPushInt(finallyBlock, value);
sb.emitOp(finallyBlock, 'NUMEQUAL');
};
sb.emitHelper(finallyBlock, options, sb.helpers.case([
{
condition: condition(constants.FINALLY_COMPLETION),
whenTrue: () => {
sb.emitOp(finallyBlock, 'DROP');
},
},
{
condition: condition(constants.THROW_COMPLETION),
whenTrue: () => {
sb.emitOp(finallyBlock, 'DROP');
sb.scope.get(sb, finallyBlock, options, val);
sb.emitHelper(finallyBlock, options, sb.helpers.throwCompletionBase);
},
},
{
condition: condition(constants.NORMAL_COMPLETION),
whenTrue: () => {
sb.emitOp(finallyBlock, 'DROP');
sb.scope.get(sb, finallyBlock, options, val);
sb.emitHelper(finallyBlock, options, sb.helpers.return);
},
},
options.breakPC === undefined
? undefined
: {
condition: condition(constants.BREAK_COMPLETION),
whenTrue: () => {
sb.emitOp(finallyBlock, 'DROP');
sb.emitHelper(finallyBlock, options, sb.helpers.break);
},
},
options.continuePC === undefined
? undefined
: {
condition: condition(constants.CONTINUE_COMPLETION),
whenTrue: () => {
sb.emitOp(finallyBlock, 'DROP');
sb.emitHelper(finallyBlock, options, sb.helpers.continue);
},
},
].filter(utils_1.utils.notNull), () => {
sb.emitOp(finallyBlock, 'DROP');
}));
}
}
}
exports.TryStatementCompiler = TryStatementCompiler;
//# sourceMappingURL=TryStatementCompiler.js.map