mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 21:44:16 +00:00
[muparser] Remove the optimizer
The optimizer adds a fair amount of complexity in muparser with no benefit to fish, since fish is not going to use complicated expressions or cache parsed expressions.
This commit is contained in:
parent
85334432ed
commit
a7f6105497
6 changed files with 6 additions and 159 deletions
|
@ -109,7 +109,6 @@ class ParserBase {
|
|||
void SetThousandsSep(char_type cThousandsSep = 0);
|
||||
void ResetLocale();
|
||||
|
||||
void EnableOptimizer(bool a_bIsOn = true);
|
||||
void EnableBuiltInOprt(bool a_bIsOn = true);
|
||||
|
||||
bool HasBuiltInOprt() const;
|
||||
|
|
|
@ -95,8 +95,6 @@ class ParserByteCode {
|
|||
/** \brief The actual rpn storage. */
|
||||
rpn_type m_vRPN;
|
||||
|
||||
bool m_bEnableOptimizer;
|
||||
|
||||
void ConstantFolding(ECmdCode a_Oprt);
|
||||
|
||||
public:
|
||||
|
@ -113,8 +111,6 @@ class ParserByteCode {
|
|||
void AddFun(generic_fun_type a_pFun, int a_iArgc);
|
||||
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);
|
||||
|
||||
void EnableOptimizer(bool bStat);
|
||||
|
||||
void Finalize();
|
||||
void clear();
|
||||
std::size_t GetMaxStackSize() const;
|
||||
|
|
|
@ -176,8 +176,6 @@ value_type Help() {
|
|||
mu::console() << _T( " list var - list parser variables\n");
|
||||
mu::console() << _T( " list exprvar - list expression variables\n");
|
||||
mu::console() << _T( " list const - list all numeric parser constants\n");
|
||||
mu::console() << _T( " opt on - enable optimizer (default)\n");
|
||||
mu::console() << _T( " opt off - disable optimizer\n");
|
||||
mu::console() << _T( " locale de - switch to german locale\n");
|
||||
mu::console() << _T( " locale en - switch to english locale\n");
|
||||
mu::console() << _T( " locale reset - reset locale\n");
|
||||
|
@ -310,14 +308,6 @@ int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) {
|
|||
} else if (sLine == _T("list var")) {
|
||||
ListVar(a_Parser);
|
||||
return 1;
|
||||
} else if (sLine == _T("opt on")) {
|
||||
a_Parser.EnableOptimizer(true);
|
||||
mu::console() << _T("Optimizer enabled\n");
|
||||
return 1;
|
||||
} else if (sLine == _T("opt off")) {
|
||||
a_Parser.EnableOptimizer(false);
|
||||
mu::console() << _T("Optimizer disabled\n");
|
||||
return 1;
|
||||
} else if (sLine == _T("list const")) {
|
||||
ListConst(a_Parser);
|
||||
return 1;
|
||||
|
@ -382,7 +372,7 @@ void Calc() {
|
|||
parser.DefineFun(_T("strfun0"), StrFun0);
|
||||
parser.DefineFun(_T("strfun2"), StrFun2);
|
||||
parser.DefineFun(_T("ping"), Ping);
|
||||
parser.DefineFun(_T("rnd"), Rnd); // Add an unoptimizeable function
|
||||
parser.DefineFun(_T("rnd"), Rnd);
|
||||
parser.DefineFun(_T("throw"), ThrowAnException);
|
||||
|
||||
parser.DefineOprt(_T("add"), Add, 0);
|
||||
|
|
|
@ -1441,16 +1441,6 @@ void ParserBase::ClearInfixOprt() {
|
|||
ReInit();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Enable or disable the formula optimization feature.
|
||||
\post Resets the parser to string parser mode.
|
||||
\throw nothrow
|
||||
*/
|
||||
void ParserBase::EnableOptimizer(bool a_bIsOn) {
|
||||
m_vRPN.EnableOptimizer(a_bIsOn);
|
||||
ReInit();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Enable the dumping of bytecode and stack content on the console.
|
||||
\param bDumpCmd Flag to enable dumping of the current bytecode to the console.
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
namespace mu {
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Bytecode default constructor. */
|
||||
ParserByteCode::ParserByteCode()
|
||||
: m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true) {
|
||||
ParserByteCode::ParserByteCode() : m_iStackPos(0), m_iMaxStackSize(0), m_vRPN() {
|
||||
m_vRPN.reserve(50);
|
||||
}
|
||||
|
||||
|
@ -61,9 +60,6 @@ ParserByteCode &ParserByteCode::operator=(const ParserByteCode &a_ByteCode) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void ParserByteCode::EnableOptimizer(bool bStat) { m_bEnableOptimizer = bStat; }
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy state of another object to this.
|
||||
|
||||
|
@ -75,7 +71,6 @@ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) {
|
|||
m_iStackPos = a_ByteCode.m_iStackPos;
|
||||
m_vRPN = a_ByteCode.m_vRPN;
|
||||
m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
|
||||
m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -203,131 +198,10 @@ void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) {
|
|||
\sa ParserToken::ECmdCode
|
||||
*/
|
||||
void ParserByteCode::AddOp(ECmdCode a_Oprt) {
|
||||
bool bOptimized = false;
|
||||
|
||||
if (m_bEnableOptimizer) {
|
||||
std::size_t sz = m_vRPN.size();
|
||||
|
||||
// Check for foldable constants like:
|
||||
// cmVAL cmVAL cmADD
|
||||
// where cmADD can stand fopr any binary operator applied to
|
||||
// two constant values.
|
||||
if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL) {
|
||||
ConstantFolding(a_Oprt);
|
||||
bOptimized = true;
|
||||
} else {
|
||||
switch (a_Oprt) {
|
||||
case cmPOW:
|
||||
// Optimization for polynomials of low order
|
||||
if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL) {
|
||||
if (m_vRPN[sz - 1].Val.data2 == 2)
|
||||
m_vRPN[sz - 2].Cmd = cmVARPOW2;
|
||||
else if (m_vRPN[sz - 1].Val.data2 == 3)
|
||||
m_vRPN[sz - 2].Cmd = cmVARPOW3;
|
||||
else if (m_vRPN[sz - 1].Val.data2 == 4)
|
||||
m_vRPN[sz - 2].Cmd = cmVARPOW4;
|
||||
else
|
||||
break;
|
||||
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmSUB:
|
||||
case cmADD:
|
||||
// Simple optimization based on pattern recognition for a shitload of different
|
||||
// bytecode combinations of addition/subtraction
|
||||
if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR &&
|
||||
m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL &&
|
||||
m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAR &&
|
||||
m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL &&
|
||||
m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)) {
|
||||
assert((m_vRPN[sz - 2].Val.ptr == NULL && m_vRPN[sz - 1].Val.ptr != NULL) ||
|
||||
(m_vRPN[sz - 2].Val.ptr != NULL && m_vRPN[sz - 1].Val.ptr == NULL) ||
|
||||
(m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr));
|
||||
|
||||
m_vRPN[sz - 2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz - 2].Val.ptr =
|
||||
(value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) |
|
||||
(long long)(m_vRPN[sz - 1].Val.ptr)); // variable
|
||||
m_vRPN[sz - 2].Val.data2 +=
|
||||
((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2; // offset
|
||||
m_vRPN[sz - 2].Val.data +=
|
||||
((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data; // multiplicand
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmMUL:
|
||||
if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR)) {
|
||||
m_vRPN[sz - 2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz - 2].Val.ptr =
|
||||
(value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) |
|
||||
(long long)(m_vRPN[sz - 1].Val.ptr));
|
||||
m_vRPN[sz - 2].Val.data =
|
||||
m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2;
|
||||
m_vRPN[sz - 2].Val.data2 = 0;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
} else if ((m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
|
||||
(m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL)) {
|
||||
// Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
|
||||
m_vRPN[sz - 2].Cmd = cmVARMUL;
|
||||
m_vRPN[sz - 2].Val.ptr =
|
||||
(value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) |
|
||||
(long long)(m_vRPN[sz - 1].Val.ptr));
|
||||
if (m_vRPN[sz - 1].Cmd == cmVAL) {
|
||||
m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2;
|
||||
m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2;
|
||||
} else {
|
||||
m_vRPN[sz - 2].Val.data =
|
||||
m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2;
|
||||
m_vRPN[sz - 2].Val.data2 =
|
||||
m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2;
|
||||
}
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
} else if (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR &&
|
||||
m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr) {
|
||||
// Optimization: a*a -> a^2
|
||||
m_vRPN[sz - 2].Cmd = cmVARPOW2;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmDIV:
|
||||
if (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL &&
|
||||
m_vRPN[sz - 1].Val.data2 != 0) {
|
||||
// Optimization: 4*a/2 -> 2*a
|
||||
m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
|
||||
m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
} // switch a_Oprt
|
||||
}
|
||||
}
|
||||
|
||||
// If optimization can't be applied just write the value
|
||||
if (!bOptimized) {
|
||||
--m_iStackPos;
|
||||
SToken tok;
|
||||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
--m_iStackPos;
|
||||
SToken tok;
|
||||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -1253,10 +1253,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
|
|||
fVal[2] = p2.Eval();
|
||||
|
||||
// Test assignment operator
|
||||
// additionally disable Optimizer this time
|
||||
mu::Parser p3;
|
||||
p3 = p2;
|
||||
p3.EnableOptimizer(false);
|
||||
fVal[3] = p3.Eval();
|
||||
|
||||
// Test Eval function for multiple return values
|
||||
|
|
Loading…
Reference in a new issue