40 #include "muParserTemplateMagic.h"
44 #pragma warning(disable : 26812)
57 , m_bEnableOptimizer(true)
84 void ParserByteCode::EnableOptimizer(
bool bStat)
86 m_bEnableOptimizer = bStat;
96 if (
this == &a_ByteCode)
99 m_iStackPos = a_ByteCode.m_iStackPos;
100 m_vRPN = a_ByteCode.m_vRPN;
101 m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
102 m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
104 m_stringBuffer = a_ByteCode.m_stringBuffer;
105 m_expr = a_ByteCode.m_expr;
116 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
121 tok.Val.ptr = a_pVar;
124 m_vRPN.push_back(tok);
143 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
148 tok.Val.ptr =
nullptr;
150 tok.Val.data2 = a_fVal;
151 m_vRPN.push_back(tok);
155 void ParserByteCode::ConstantFolding(
ECmdCode a_Oprt)
157 std::size_t sz = m_vRPN.size();
163 case cmLAND: x = (int)x && (
int)y; m_vRPN.pop_back();
break;
164 case cmLOR: x = (int)x || (
int)y; m_vRPN.pop_back();
break;
165 case cmLT: x = x < y; m_vRPN.pop_back();
break;
166 case cmGT: x = x > y; m_vRPN.pop_back();
break;
167 case cmLE: x = x <= y; m_vRPN.pop_back();
break;
168 case cmGE: x = x >= y; m_vRPN.pop_back();
break;
169 case cmNEQ: x = x != y; m_vRPN.pop_back();
break;
170 case cmEQ: x = x == y; m_vRPN.pop_back();
break;
171 case cmADD: x = x + y; m_vRPN.pop_back();
break;
172 case cmSUB: x = x - y; m_vRPN.pop_back();
break;
173 case cmMUL: x = x * y; m_vRPN.pop_back();
break;
201 bool bOptimized =
false;
203 if (m_bEnableOptimizer)
205 std::size_t sz = m_vRPN.size();
211 if (sz >= 2 && m_vRPN[sz - 2].Cmd ==
cmVAL && m_vRPN[sz - 1].Cmd ==
cmVAL)
213 ConstantFolding(a_Oprt);
222 if (m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 1].Cmd ==
cmVAL)
224 if (m_vRPN[sz - 1].Val.data2 == 0)
226 m_vRPN[sz - 2].Cmd =
cmVAL;
227 m_vRPN[sz - 2].Val.ptr =
nullptr;
228 m_vRPN[sz - 2].Val.data = 0;
229 m_vRPN[sz - 2].Val.data2 = 1;
231 else if (m_vRPN[sz - 1].Val.data2 == 1)
232 m_vRPN[sz - 2].Cmd =
cmVAR;
233 else if (m_vRPN[sz - 1].Val.data2 == 2)
234 m_vRPN[sz - 2].Cmd = cmVARPOW2;
235 else if (m_vRPN[sz - 1].Val.data2 == 3)
236 m_vRPN[sz - 2].Cmd = cmVARPOW3;
237 else if (m_vRPN[sz - 1].Val.data2 == 4)
238 m_vRPN[sz - 2].Cmd = cmVARPOW4;
251 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
252 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR) ||
253 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
254 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
255 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
256 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
257 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
258 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr))
261 (m_vRPN[sz - 2].Val.ptr ==
nullptr && m_vRPN[sz - 1].Val.ptr !=
nullptr) ||
262 (m_vRPN[sz - 2].Val.ptr !=
nullptr && m_vRPN[sz - 1].Val.ptr ==
nullptr) ||
263 (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr));
265 m_vRPN[sz - 2].Cmd = cmVARMUL;
266 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
267 m_vRPN[sz - 2].Val.data2 += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2;
268 m_vRPN[sz - 2].Val.data += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data;
275 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
276 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR))
278 m_vRPN[sz - 2].Cmd = cmVARMUL;
279 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
280 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2;
281 m_vRPN[sz - 2].Val.data2 = 0;
286 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
287 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL))
290 m_vRPN[sz - 2].Cmd = cmVARMUL;
291 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
292 if (m_vRPN[sz - 1].Cmd ==
cmVAL)
294 m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2;
295 m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2;
299 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2;
300 m_vRPN[sz - 2].Val.data2 = m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2;
306 m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR &&
307 m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr)
310 m_vRPN[sz - 2].Cmd = cmVARPOW2;
317 if (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 1].Val.data2 != 0)
320 m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
321 m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
340 m_vRPN.push_back(tok);
345 void ParserByteCode::AddIfElse(
ECmdCode a_Oprt)
349 m_vRPN.push_back(tok);
369 tok.Oprt.ptr = a_pVar;
370 m_vRPN.push_back(tok);
381 std::size_t sz = m_vRPN.size();
382 bool optimize =
false;
385 if (isFunctionOptimizable && m_bEnableOptimizer && a_iArgc > 0)
393 for (
int i = 0; i < std::abs(a_iArgc); ++i)
395 if (m_vRPN[sz - i - 1].Cmd !=
cmVAL)
408 case 1: val = a_pFun.call_fun<1>(m_vRPN[sz - 1].Val.data2);
break;
409 case 2: val = a_pFun.call_fun<2>(m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
410 case 3: val = a_pFun.call_fun<3>(m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
411 case 4: val = a_pFun.call_fun<4>(m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
412 case 5: val = a_pFun.call_fun<5>(m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
413 case 6: val = a_pFun.call_fun<6>(m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
414 case 7: val = a_pFun.call_fun<7>(m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
415 case 8: val = a_pFun.call_fun<8>(m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
416 case 9: val = a_pFun.call_fun<9>(m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
417 case 10: val = a_pFun.call_fun<10>(m_vRPN[sz - 10].Val.data2, m_vRPN[sz - 9].Val.data2, m_vRPN[sz - 8].Val.data2, m_vRPN[sz - 7].Val.data2, m_vRPN[sz - 6].Val.data2, m_vRPN[sz - 5].Val.data2, m_vRPN[sz - 4].Val.data2, m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
424 m_vRPN.erase(m_vRPN.end() - a_iArgc, m_vRPN.end());
430 tok.Val.ptr =
nullptr;
431 m_vRPN.push_back(tok);
437 tok.Fun.argc = a_iArgc;
439 m_vRPN.push_back(tok);
442 m_iStackPos = m_iStackPos - std::abs(a_iArgc) + 1;
443 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
455 m_iStackPos = m_iStackPos - a_iArgc + 1;
456 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
460 tok.Fun.argc = a_iArgc;
462 m_vRPN.push_back(tok);
475 m_iStackPos = m_iStackPos - a_iArgc + 1;
479 tok.Fun.argc = a_iArgc;
480 tok.Fun.idx = a_iIdx;
482 m_vRPN.push_back(tok);
484 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
496 m_vRPN.push_back(tok);
497 rpn_type(m_vRPN).swap(m_vRPN);
500 std::stack<int> stIf, stElse;
502 for (
int i = 0; i < (int)m_vRPN.size(); ++i)
504 switch (m_vRPN[i].Cmd)
514 m_vRPN[idx].Oprt.offset = i - idx;
520 m_vRPN[idx].Oprt.offset = i - idx;
530 std::size_t ParserByteCode::GetMaxStackSize()
const
532 return m_iMaxStackSize + 1;
561 mu::console() <<
_T(
"Number of RPN tokens:") << (int)m_vRPN.size() <<
_T(
"\n");
562 for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd !=
cmEND; ++i)
565 switch (m_vRPN[i].Cmd)
572 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
576 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
580 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
584 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
588 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]");
594 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
595 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) <<
_T(
"]");
596 mu::console() <<
_T(
"[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) <<
_T(
"]");
602 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
603 mu::console() <<
_T(
"[IDX:") << std::dec << m_vRPN[i].Fun.idx <<
_T(
"=\"") << m_stringBuffer[m_vRPN[i].Fun.idx] << (
"\"]");
604 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) <<
_T(
"]");
605 mu::console() <<
_T(
"[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) <<
_T(
"]");
624 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
628 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
638 default:
mu::console() <<
_T(
"(unknown code: ") << m_vRPN[i].Cmd <<
_T(
")\n");
647 #if defined(_MSC_VER)
Definition of the parser bytecode class.
#define _T(x)
Activate this option in order to compile with OpenMP support.
void AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
void AsciiDump() const
Dump bytecode (for debugging only!).
std::ostream & console()
Encapsulate cout.
Operator item: y to the power of ...
Internal error of any kind.
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
Operator item: not equal.
For use in the ternary if-then-else operator.
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.
Code for a generic function item.
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
ParserByteCode()
Bytecode default constructor.
For use in the ternary if-then-else operator.
void AddBulkFun(generic_callable_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
Error class of the parser.
For use in the ternary if-then-else operator.
void AddFun(generic_callable_type a_pFun, int a_iArgc, bool isOptimizable)
Add function to bytecode.
#define MUP_ASSERT(COND)
An assertion that does not kill the program.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
A template class for providing wrappers for essential math functions.
Namespace for mathematical applications.
Operator item: less than.
Operator item: greater than.
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Code for a function with a string parameter.
Operator item: Assignment operator.
void(* erased_fun_type)()
Function type used to erase type. Voluntarily needs explicit cast with all other fun_type.
Bytecode implementation of the Math Parser.
This file contains the parser token definition.
void clear()
Delete the bytecode.
void AddVar(value_type *a_pVar)
Add a Variable pointer to bytecode.
Operator item: less or equal.
Operator item: greater or equal.
ParserByteCode & operator=(const ParserByteCode &a_ByteCode)
Assignment operator.
void Finalize()
Add end marker to bytecode.
This file defines the error class used by the parser.
This file contains standard definitions used by the parser.