From 4452d9ce18b1c78fa05e52297012d46c97426f7e Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:30:18 -0800 Subject: [PATCH] [muparser] Remove m_pParseFormula function pointer This is a very strange design that determines whether initialization needs to be performed by reassigning a function pointer. A misguided optimization? Just check explicitly. --- muparser-2.2.5/include/muParserBase.h | 8 +++--- muparser-2.2.5/include/muParserBytecode.h | 1 + muparser-2.2.5/src/muParserBase.cpp | 31 ++++++++--------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 2a38a255e..c8eae0d79 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -230,10 +230,13 @@ class ParserBase { OptionalError CreateRPN() const; - ValueOrError ParseString() const; - ValueOrError ParseCmdCode() const; + ValueOrError ExecuteRPN() const; ValueOrError InvokeFunction(generic_fun_type func, const value_type *args, int argCount) const; + /// Build the RPN if necessary, and then execute it. + /// \return the result, or an error. + ValueOrError BuildAndExecuteRPN() const; + OptionalError CheckName(const string_type &a_strName, const string_type &a_CharSet) const; OptionalError CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, const string_type &a_szCharSet) const; @@ -245,7 +248,6 @@ class ParserBase { Eval() calls the function whose address is stored there. */ - mutable ParseFunction m_pParseFormula; mutable ParserByteCode m_vRPN; ///< The Bytecode class. mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index ac70842af..9d4ffc2c3 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -112,6 +112,7 @@ class ParserByteCode { void clear(); std::size_t GetMaxStackSize() const; std::size_t GetSize() const; + bool empty() const { return GetSize() == 0; } const SToken *GetBase() const; void AsciiDump(); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index f16a8bd36..495fc6e43 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -65,8 +65,7 @@ const char_type *ParserBase::c_DefaultOprt[] = { \throw ParserException if a_szFormula is null. */ ParserBase::ParserBase() - : m_pParseFormula(&ParserBase::ParseString), - m_vRPN(), + : m_vRPN(), m_vStringBuf(), m_pTokenReader(), m_FunDef(), @@ -142,7 +141,6 @@ void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type( Clear bytecode, reset the token reader. */ void ParserBase::ReInit() const { - m_pParseFormula = &ParserBase::ParseString; m_vStringBuf.clear(); m_vRPN.clear(); m_pTokenReader->ReInit(); @@ -818,14 +816,14 @@ ValueOrError ParserBase::InvokeFunction(generic_fun_type func, const value_type } //--------------------------------------------------------------------------- -/** \brief Parse the command code. - \sa ParseString(...) +/** \brief Execute the RPN. Command code contains precalculated stack positions of the values and the associated operators. The Stack is filled beginning from index one the value at index zero is not used at all. */ -ValueOrError ParserBase::ParseCmdCode() const { +ValueOrError ParserBase::ExecuteRPN() const { + assert(! m_vRPN.empty() && "Missing RPN"); value_type *Stack = &m_vStackBuffer[0]; value_type buf; int sidx(0); @@ -1220,20 +1218,13 @@ OptionalError ParserBase::CreateRPN() const { return {}; } -//--------------------------------------------------------------------------- -/** \brief One of the two main parse functions. - \sa ParseCmdCode(...) - - Parse expression from input string. Perform syntax checking and create - bytecode. After parsing the string and creating the bytecode the function - pointer #m_pParseFormula will be changed to the second parse routine the - uses bytecode instead of string parsing. -*/ -ValueOrError ParserBase::ParseString() const { +ValueOrError ParserBase::BuildAndExecuteRPN() const { + if (m_vRPN.empty()) { OptionalError oerr = CreateRPN(); if (oerr.has_error()) return oerr.error(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); + assert(! m_vRPN.empty() && "RPN should no longer be empty"); + } + return ExecuteRPN(); } //--------------------------------------------------------------------------- @@ -1449,7 +1440,7 @@ void ParserBase::StackDump(const ParserStack &a_stVal, made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") */ void ParserBase::Eval(std::vector *outResult) const { - ValueOrError v = (this->*m_pParseFormula)(); + ValueOrError v = BuildAndExecuteRPN(); if (v.has_error()) { outResult->push_back(std::move(v)); return; @@ -1484,6 +1475,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. */ -ValueOrError ParserBase::Eval() const { return (this->*m_pParseFormula)(); } +ValueOrError ParserBase::Eval() const { return BuildAndExecuteRPN(); } } // namespace mu