40 #include "muParserTemplateMagic.h"
44 #pragma warning(disable : 26812)
55 , m_bEnableOptimizer(true)
82 void ParserByteCode::EnableOptimizer(
bool bStat)
84 m_bEnableOptimizer = bStat;
94 if (
this == &a_ByteCode)
97 m_iStackPos = a_ByteCode.m_iStackPos;
98 m_vRPN = a_ByteCode.m_vRPN;
99 m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
100 m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
111 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
116 tok.Val.ptr = a_pVar;
119 m_vRPN.push_back(tok);
138 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
143 tok.Val.ptr =
nullptr;
145 tok.Val.data2 = a_fVal;
146 m_vRPN.push_back(tok);
150 void ParserByteCode::ConstantFolding(
ECmdCode a_Oprt)
152 std::size_t sz = m_vRPN.size();
158 case cmLAND: x = (int)x && (
int)y; m_vRPN.pop_back();
break;
159 case cmLOR: x = (int)x || (
int)y; m_vRPN.pop_back();
break;
160 case cmLT: x = x < y; m_vRPN.pop_back();
break;
161 case cmGT: x = x > y; m_vRPN.pop_back();
break;
162 case cmLE: x = x <= y; m_vRPN.pop_back();
break;
163 case cmGE: x = x >= y; m_vRPN.pop_back();
break;
164 case cmNEQ: x = x != y; m_vRPN.pop_back();
break;
165 case cmEQ: x = x == y; m_vRPN.pop_back();
break;
166 case cmADD: x = x + y; m_vRPN.pop_back();
break;
167 case cmSUB: x = x - y; m_vRPN.pop_back();
break;
168 case cmMUL: x = x * y; m_vRPN.pop_back();
break;
196 bool bOptimized =
false;
198 if (m_bEnableOptimizer)
200 std::size_t sz = m_vRPN.size();
206 if (sz >= 2 && m_vRPN[sz - 2].Cmd ==
cmVAL && m_vRPN[sz - 1].Cmd ==
cmVAL)
208 ConstantFolding(a_Oprt);
217 if (m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 1].Cmd ==
cmVAL)
219 if (m_vRPN[sz - 1].Val.data2 == 0)
221 m_vRPN[sz - 2].Cmd =
cmVAL;
222 m_vRPN[sz - 2].Val.ptr =
nullptr;
223 m_vRPN[sz - 2].Val.data = 0;
224 m_vRPN[sz - 2].Val.data2 = 1;
226 else if (m_vRPN[sz - 1].Val.data2 == 1)
227 m_vRPN[sz - 2].Cmd =
cmVAR;
228 else if (m_vRPN[sz - 1].Val.data2 == 2)
229 m_vRPN[sz - 2].Cmd = cmVARPOW2;
230 else if (m_vRPN[sz - 1].Val.data2 == 3)
231 m_vRPN[sz - 2].Cmd = cmVARPOW3;
232 else if (m_vRPN[sz - 1].Val.data2 == 4)
233 m_vRPN[sz - 2].Cmd = cmVARPOW4;
246 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
247 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR) ||
248 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
249 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
250 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
251 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
252 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
253 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr))
256 (m_vRPN[sz - 2].Val.ptr ==
nullptr && m_vRPN[sz - 1].Val.ptr !=
nullptr) ||
257 (m_vRPN[sz - 2].Val.ptr !=
nullptr && m_vRPN[sz - 1].Val.ptr ==
nullptr) ||
258 (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr));
260 m_vRPN[sz - 2].Cmd = cmVARMUL;
261 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
262 m_vRPN[sz - 2].Val.data2 += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2;
263 m_vRPN[sz - 2].Val.data += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data;
270 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
271 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR))
273 m_vRPN[sz - 2].Cmd = cmVARMUL;
274 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
275 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2;
276 m_vRPN[sz - 2].Val.data2 = 0;
281 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
282 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL))
285 m_vRPN[sz - 2].Cmd = cmVARMUL;
286 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
287 if (m_vRPN[sz - 1].Cmd ==
cmVAL)
289 m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2;
290 m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2;
294 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2;
295 m_vRPN[sz - 2].Val.data2 = m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2;
301 m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR &&
302 m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr)
305 m_vRPN[sz - 2].Cmd = cmVARPOW2;
312 if (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 1].Val.data2 != 0)
315 m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
316 m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
335 m_vRPN.push_back(tok);
340 void ParserByteCode::AddIfElse(
ECmdCode a_Oprt)
344 m_vRPN.push_back(tok);
364 tok.Oprt.ptr = a_pVar;
365 m_vRPN.push_back(tok);
376 std::size_t sz = m_vRPN.size();
377 bool optimize =
false;
380 if (isFunctionOptimizable && m_bEnableOptimizer && a_iArgc > 0)
388 for (
int i = 0; i < std::abs(a_iArgc); ++i)
390 if (m_vRPN[sz - i - 1].Cmd !=
cmVAL)
403 case 1: val = a_pFun.call_fun<1>(m_vRPN[sz - 1].Val.data2);
break;
404 case 2: val = a_pFun.call_fun<2>(m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
405 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;
406 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;
407 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;
408 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;
409 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;
410 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;
411 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;
412 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;
419 m_vRPN.erase(m_vRPN.end() - a_iArgc, m_vRPN.end());
425 tok.Val.ptr =
nullptr;
426 m_vRPN.push_back(tok);
432 tok.Fun.argc = a_iArgc;
434 m_vRPN.push_back(tok);
437 m_iStackPos = m_iStackPos - std::abs(a_iArgc) + 1;
438 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
450 m_iStackPos = m_iStackPos - a_iArgc + 1;
451 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
455 tok.Fun.argc = a_iArgc;
457 m_vRPN.push_back(tok);
470 m_iStackPos = m_iStackPos - a_iArgc + 1;
474 tok.Fun.argc = a_iArgc;
475 tok.Fun.idx = a_iIdx;
477 m_vRPN.push_back(tok);
479 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
491 m_vRPN.push_back(tok);
492 rpn_type(m_vRPN).swap(m_vRPN);
495 std::stack<int> stIf, stElse;
497 for (
int i = 0; i < (int)m_vRPN.size(); ++i)
499 switch (m_vRPN[i].Cmd)
509 m_vRPN[idx].Oprt.offset = i - idx;
515 m_vRPN[idx].Oprt.offset = i - idx;
525 std::size_t ParserByteCode::GetMaxStackSize()
const
527 return m_iMaxStackSize + 1;
556 mu::console() <<
_T(
"Number of RPN tokens:") << (int)m_vRPN.size() <<
_T(
"\n");
557 for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd !=
cmEND; ++i)
560 switch (m_vRPN[i].Cmd)
567 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
571 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
575 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
579 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
583 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]");
589 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
590 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) <<
_T(
"]");
591 mu::console() <<
_T(
"[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) <<
_T(
"]");
597 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
598 mu::console() <<
_T(
"[IDX:") << std::dec << m_vRPN[i].Fun.idx <<
_T(
"]");
599 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pRawFun) <<
_T(
"]");
600 mu::console() <<
_T(
"[USERDATA: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.cb._pUserData) <<
_T(
"]");
619 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
623 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
633 default:
mu::console() <<
_T(
"(unknown code: ") << m_vRPN[i].Cmd <<
_T(
")\n");
642 #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.
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.
void AsciiDump()
Dump bytecode (for debugging only!).
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.