[math] Remove exception handling in builtin_math

This handles errors explicitly instead of catching them.
This commit is contained in:
ridiculousfish 2017-12-17 14:41:55 -08:00
parent 5d2cf3f666
commit 11e6cfeb82

View File

@ -119,36 +119,40 @@ static const wchar_t *math_get_arg(int *argidx, wchar_t **argv, wcstring *storag
static mu::ValueOrError moduloOperator(double v, double w) { return (int)v % std::max(1, (int)w); }; static mu::ValueOrError moduloOperator(double v, double w) { return (int)v % std::max(1, (int)w); };
/// Evaluate math expressions. /// Evaluate math expressions.
static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &streams, static int evaluate_expression(const wchar_t *cmd, parser_t &parser, io_streams_t &streams,
math_cmd_opts_t &opts, wcstring &expression) { math_cmd_opts_t &opts, wcstring &expression) {
UNUSED(parser); UNUSED(parser);
try { // Helper to print an error and return an error code.
mu::Parser p; auto printError = [&streams, cmd](const mu::ParserError &err) {
// MuParser doesn't implement the modulo operator so we add it ourselves since there are streams.err.append_format(_(L"%ls: Invalid expression: %ls\n"), cmd, err.GetMsg().c_str());
// likely users of our old math wrapper around bc that expect it to be available.
p.DefineOprtChars(L"%");
p.DefineOprt(L"%", moduloOperator, mu::prINFIX);
mu::OptionalError oerr = p.SetExpr(expression);
if (oerr.has_error()) throw oerr.error();
std::vector<mu::ValueOrError> vs;
p.Eval(&vs);
for (const mu::ValueOrError &v : vs) {
if (v.has_error()) throw v.error();
}
for (const mu::ValueOrError &v : vs) {
if (opts.scale == 0) {
streams.out.append_format(L"%ld\n", static_cast<long>(*v));
} else {
streams.out.append_format(L"%.*lf\n", opts.scale, *v);
}
}
return STATUS_CMD_OK;
} catch (mu::Parser::exception_type &e) {
streams.err.append_format(_(L"%ls: Invalid expression: %ls\n"), cmd, e.GetMsg().c_str());
return STATUS_CMD_ERROR; return STATUS_CMD_ERROR;
};
mu::Parser p;
// MuParser doesn't implement the modulo operator so we add it ourselves since there are
// likely users of our old math wrapper around bc that expect it to be available.
p.DefineOprtChars(L"%");
mu::OptionalError oerr = p.DefineOprt(L"%", moduloOperator, mu::prINFIX);
assert(!oerr.has_error() && "Unexpected error defining modulo operator");
(void)oerr;
oerr = p.SetExpr(expression);
if (oerr.has_error()) return printError(oerr.error());
std::vector<mu::ValueOrError> vs;
p.Eval(&vs);
for (const mu::ValueOrError &v : vs) {
if (v.has_error()) return printError(v.error());
} }
for (const mu::ValueOrError &v : vs) {
if (opts.scale == 0) {
streams.out.append_format(L"%ld\n", static_cast<long>(*v));
} else {
streams.out.append_format(L"%.*lf\n", opts.scale, *v);
}
}
return STATUS_CMD_OK;
} }
/// The math builtin evaluates math expressions. /// The math builtin evaluates math expressions.