[muparser] Continue adopting ValueOrError

This commit is contained in:
ridiculousfish 2017-11-22 12:27:10 -08:00
parent bfd70880a5
commit 9649b132bd
8 changed files with 40 additions and 49 deletions

View file

@ -97,8 +97,8 @@ class ParserBase {
virtual ~ParserBase(); virtual ~ParserBase();
value_type Eval() const; ValueOrError Eval() const;
value_type *Eval(int &nStackSize) const; void Eval(std::vector<ValueOrError> *results) const;
int GetNumResults() const; int GetNumResults() const;

View file

@ -112,7 +112,6 @@ API_EXPORT(void)
mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData); mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData);
API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser); API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser);
API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);
API_EXPORT(muFloat_t *) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);
// Defining callbacks / variables / constants // Defining callbacks / variables / constants
API_EXPORT(void) API_EXPORT(void)

View file

@ -416,7 +416,7 @@ void Calc() {
// 1.) If you know there is only a single return value or in case you only need the last // 1.) If you know there is only a single return value or in case you only need the last
// result of an expression consisting of comma separated subexpressions you can // result of an expression consisting of comma separated subexpressions you can
// simply use: // simply use:
mu::console() << _T("ans=") << parser.Eval() << _T("\n"); mu::console() << _T("ans=") << *parser.Eval() << _T("\n");
// 2.) As an alternative you can also retrieve multiple return values using this API: // 2.) As an alternative you can also retrieve multiple return values using this API:
int nNum = parser.GetNumResults(); int nNum = parser.GetNumResults();
@ -425,10 +425,11 @@ void Calc() {
// this is the hard way if you need to retrieve multiple subexpression // this is the hard way if you need to retrieve multiple subexpression
// results // results
value_type *v = parser.Eval(nNum); std::vector<ValueOrError> vs;
parser.Eval(&vs);
mu::console() << std::setprecision(12); mu::console() << std::setprecision(12);
for (int i = 0; i < nNum; ++i) { for (const ValueOrError &v : vs) {
mu::console() << v[i] << _T("\n"); mu::console() << *v << _T("\n");
} }
} }
} catch (mu::Parser::exception_type &e) { } catch (mu::Parser::exception_type &e) {
@ -446,8 +447,8 @@ void Calc() {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int main(int, char **) { int main(int, char **) {
Splash(); Splash();
SelfTest(); (void)SelfTest();
Help(); (void)Help();
// CheckLocale(); // CheckLocale();
// CheckDiff(); // CheckDiff();

View file

@ -331,9 +331,10 @@ void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd
http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
*/ */
ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const {
value_type fRes(0), fBuf(*a_Var), f[4] = {0, 0, 0, 0}, fEpsilon(a_fEpsilon); value_type fRes(0), fBuf(*a_Var), fEpsilon(a_fEpsilon);
ValueOrError f[4] = {0, 0, 0, 0};
// Backwards compatible calculation of epsilon inc case the user doesn't provide // Backwards compatible calculation of epsilon in case the user doesn't provide
// his own epsilon // his own epsilon
if (fEpsilon == 0) fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; if (fEpsilon == 0) fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;
@ -347,7 +348,10 @@ ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEp
f[3] = Eval(); f[3] = Eval();
*a_Var = fBuf; // restore variable *a_Var = fBuf; // restore variable
fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon); for (ValueOrError &v : f) {
if (!v) return std::move(v);
}
fRes = (-*f[0] + 8 * *f[1] - 8 * *f[2] + *f[3]) / (12 * fEpsilon);
return fRes; return fRes;
} }
} // namespace mu } // namespace mu

View file

@ -1552,12 +1552,12 @@ void ParserBase::StackDump(const ParserStack<token_type> &a_stVal,
This member function can be used to retrieve all results of an expression This member function can be used to retrieve all results of an expression
made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)")
*/ */
value_type *ParserBase::Eval(int &nStackSize) const { void ParserBase::Eval(std::vector<ValueOrError> *outResult) const {
(this->*m_pParseFormula)(); (this->*m_pParseFormula)();
nStackSize = m_nFinalResultIdx; int stackSize = m_nFinalResultIdx;
// (for historic reasons the stack starts at position 1) // (for historic reasons the stack starts at position 1)
return &m_vStackBuffer[1]; outResult->assign(&m_vStackBuffer[1], &m_vStackBuffer[1 + stackSize]);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -1585,6 +1585,6 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; }
\return The evaluation result \return The evaluation result
\throw ParseException if no Formula is set or in case of any other error related to the formula. \throw ParseException if no Formula is set or in case of any other error related to the formula.
*/ */
value_type ParserBase::Eval() const { return (this->*m_pParseFormula)().getOrThrow(); } ValueOrError ParserBase::Eval() const { return (this->*m_pParseFormula)(); }
} // namespace mu } // namespace mu

View file

@ -195,19 +195,7 @@ API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) {
API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) {
MU_TRY MU_TRY
muParser_t* const p(AsParser(a_hParser)); muParser_t* const p(AsParser(a_hParser));
return p->Eval(); return *p->Eval();
MU_CATCH
return 0;
}
//---------------------------------------------------------------------------
API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) {
MU_TRY
assert(nNum != NULL);
muParser_t* const p(AsParser(a_hParser));
return p->Eval(*nNum);
MU_CATCH MU_CATCH
return 0; return 0;

View file

@ -94,14 +94,14 @@ int ParserTester::TestInterface() {
p.DefineVar(_T("b"), &afVal[1]); p.DefineVar(_T("b"), &afVal[1]);
p.DefineVar(_T("c"), &afVal[2]); p.DefineVar(_T("c"), &afVal[2]);
p.SetExpr(_T("a+b+c")); p.SetExpr(_T("a+b+c"));
p.Eval(); (void)p.Eval();
} catch (...) { } catch (...) {
iStat += 1; // this is not supposed to happen iStat += 1; // this is not supposed to happen
} }
try { try {
p.RemoveVar(_T("c")); p.RemoveVar(_T("c"));
p.Eval(); (void)p.Eval();
iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...
} catch (...) { } catch (...) {
// failure is expected... // failure is expected...
@ -1075,7 +1075,7 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
p.DefineFun(_T("strfun2"), StrFun2); p.DefineFun(_T("strfun2"), StrFun2);
p.DefineFun(_T("strfun3"), StrFun3); p.DefineFun(_T("strfun3"), StrFun3);
p.SetExpr(a_str); p.SetExpr(a_str);
p.Eval(); (void)p.Eval();
} catch (ParserError &e) { } catch (ParserError &e) {
// output the formula in case of an failed test // output the formula in case of an failed test
if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) { if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) {
@ -1119,10 +1119,10 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1,
p.SetExpr(a_str); p.SetExpr(a_str);
var = a_fVar1; var = a_fVar1;
fVal[0] = p.Eval(); fVal[0] = *p.Eval();
var = a_fVar2; var = a_fVar2;
fVal[1] = p.Eval(); fVal[1] = *p.Eval();
if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) if (fabs(a_fRes1 - fVal[0]) > 0.0000000001)
throw std::runtime_error("incorrect result (first pass)"); throw std::runtime_error("incorrect result (first pass)");
@ -1234,8 +1234,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
// Test bytecode integrity // Test bytecode integrity
// String parsing and bytecode parsing must yield the same result // String parsing and bytecode parsing must yield the same result
fVal[0] = p1->Eval(); // result from stringparsing fVal[0] = *p1->Eval(); // result from stringparsing
fVal[1] = p1->Eval(); // result from bytecode fVal[1] = *p1->Eval(); // result from bytecode
if (fVal[0] != fVal[1]) if (fVal[0] != fVal[1])
throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); throw Parser::exception_type(_T("Bytecode / string parsing mismatch."));
@ -1250,18 +1250,17 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
vParser.clear(); // delete the vector vParser.clear(); // delete the vector
p1.reset(0); p1.reset(0);
fVal[2] = p2.Eval(); fVal[2] = *p2.Eval();
// Test assignment operator // Test assignment operator
mu::Parser p3; mu::Parser p3;
p3 = p2; p3 = p2;
fVal[3] = p3.Eval(); fVal[3] = *p3.Eval();
// Test Eval function for multiple return values // Test Eval function for multiple return values
// use p2 since it has the optimizer enabled! std::vector<ValueOrError> v;
int nNum; p2.Eval(&v);
value_type *v = p2.Eval(nNum); fVal[4] = *v.back();
fVal[4] = v[nNum - 1];
} catch (std::exception &e) { } catch (std::exception &e) {
mu::console() << _T("\n ") << e.what() << _T("\n"); mu::console() << _T("\n ") << e.what() << _T("\n");
} }
@ -1328,8 +1327,8 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa
p.DefineVar(_T("c"), &vVarVal[2]); p.DefineVar(_T("c"), &vVarVal[2]);
p.SetExpr(a_str); p.SetExpr(a_str);
fVal[0] = p.Eval(); // result from stringparsing fVal[0] = *p.Eval(); // result from stringparsing
fVal[1] = p.Eval(); // result from bytecode fVal[1] = *p.Eval(); // result from bytecode
if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt.")); if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt."));

View file

@ -131,13 +131,13 @@ static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &str
p.DefineOprt(L"%", moduloOperator, mu::prINFIX); p.DefineOprt(L"%", moduloOperator, mu::prINFIX);
p.SetExpr(expression); p.SetExpr(expression);
int nNum; std::vector<mu::ValueOrError> vs;
mu::value_type *v = p.Eval(nNum); p.Eval(&vs);
for (int i = 0; i < nNum; ++i) { for (const mu::ValueOrError &v : vs) {
if (opts.scale == 0) { if (opts.scale == 0) {
streams.out.append_format(L"%ld\n", static_cast<long>(v[i])); streams.out.append_format(L"%ld\n", static_cast<long>(*v));
} else { } else {
streams.out.append_format(L"%.*lf\n", opts.scale, v[i]); streams.out.append_format(L"%.*lf\n", opts.scale, *v);
} }
} }
return STATUS_CMD_OK; return STATUS_CMD_OK;