[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();
value_type Eval() const;
value_type *Eval(int &nStackSize) const;
ValueOrError Eval() const;
void Eval(std::vector<ValueOrError> *results) const;
int GetNumResults() const;

View file

@ -112,7 +112,6 @@ API_EXPORT(void)
mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData);
API_EXPORT(const muChar_t *) mupGetVersion(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
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
// result of an expression consisting of comma separated subexpressions you can
// 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:
int nNum = parser.GetNumResults();
@ -425,10 +425,11 @@ void Calc() {
// this is the hard way if you need to retrieve multiple subexpression
// results
value_type *v = parser.Eval(nNum);
std::vector<ValueOrError> vs;
parser.Eval(&vs);
mu::console() << std::setprecision(12);
for (int i = 0; i < nNum; ++i) {
mu::console() << v[i] << _T("\n");
for (const ValueOrError &v : vs) {
mu::console() << *v << _T("\n");
}
}
} catch (mu::Parser::exception_type &e) {
@ -446,8 +447,8 @@ void Calc() {
//---------------------------------------------------------------------------
int main(int, char **) {
Splash();
SelfTest();
Help();
(void)SelfTest();
(void)Help();
// CheckLocale();
// 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
*/
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
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();
*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;
}
} // 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
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)();
nStackSize = m_nFinalResultIdx;
int stackSize = m_nFinalResultIdx;
// (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
\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

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) {
MU_TRY
muParser_t* const p(AsParser(a_hParser));
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);
return *p->Eval();
MU_CATCH
return 0;

View file

@ -94,14 +94,14 @@ int ParserTester::TestInterface() {
p.DefineVar(_T("b"), &afVal[1]);
p.DefineVar(_T("c"), &afVal[2]);
p.SetExpr(_T("a+b+c"));
p.Eval();
(void)p.Eval();
} catch (...) {
iStat += 1; // this is not supposed to happen
}
try {
p.RemoveVar(_T("c"));
p.Eval();
(void)p.Eval();
iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...
} catch (...) {
// 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("strfun3"), StrFun3);
p.SetExpr(a_str);
p.Eval();
(void)p.Eval();
} catch (ParserError &e) {
// output the formula in case of an failed test
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);
var = a_fVar1;
fVal[0] = p.Eval();
fVal[0] = *p.Eval();
var = a_fVar2;
fVal[1] = p.Eval();
fVal[1] = *p.Eval();
if (fabs(a_fRes1 - fVal[0]) > 0.0000000001)
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
// String parsing and bytecode parsing must yield the same result
fVal[0] = p1->Eval(); // result from stringparsing
fVal[1] = p1->Eval(); // result from bytecode
fVal[0] = *p1->Eval(); // result from stringparsing
fVal[1] = *p1->Eval(); // result from bytecode
if (fVal[0] != fVal[1])
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
p1.reset(0);
fVal[2] = p2.Eval();
fVal[2] = *p2.Eval();
// Test assignment operator
mu::Parser p3;
p3 = p2;
fVal[3] = p3.Eval();
fVal[3] = *p3.Eval();
// Test Eval function for multiple return values
// use p2 since it has the optimizer enabled!
int nNum;
value_type *v = p2.Eval(nNum);
fVal[4] = v[nNum - 1];
std::vector<ValueOrError> v;
p2.Eval(&v);
fVal[4] = *v.back();
} catch (std::exception &e) {
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.SetExpr(a_str);
fVal[0] = p.Eval(); // result from stringparsing
fVal[1] = p.Eval(); // result from bytecode
fVal[0] = *p.Eval(); // result from stringparsing
fVal[1] = *p.Eval(); // result from bytecode
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.SetExpr(expression);
int nNum;
mu::value_type *v = p.Eval(nNum);
for (int i = 0; i < nNum; ++i) {
std::vector<mu::ValueOrError> vs;
p.Eval(&vs);
for (const mu::ValueOrError &v : vs) {
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 {
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;