40 #include "muParserTemplateMagic.h"
50 , m_bEnableOptimizer(true)
77 void ParserByteCode::EnableOptimizer(
bool bStat)
79 m_bEnableOptimizer = bStat;
89 if (
this == &a_ByteCode)
92 m_iStackPos = a_ByteCode.m_iStackPos;
93 m_vRPN = a_ByteCode.m_vRPN;
94 m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
95 m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
106 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
111 tok.Val.ptr = a_pVar;
114 m_vRPN.push_back(tok);
133 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
138 tok.Val.ptr =
nullptr;
140 tok.Val.data2 = a_fVal;
141 m_vRPN.push_back(tok);
145 void ParserByteCode::ConstantFolding(
ECmdCode a_Oprt)
147 std::size_t sz = m_vRPN.size();
153 case cmLAND: x = (int)x && (
int)y; m_vRPN.pop_back();
break;
154 case cmLOR: x = (int)x || (
int)y; m_vRPN.pop_back();
break;
155 case cmLT: x = x < y; m_vRPN.pop_back();
break;
156 case cmGT: x = x > y; m_vRPN.pop_back();
break;
157 case cmLE: x = x <= y; m_vRPN.pop_back();
break;
158 case cmGE: x = x >= y; m_vRPN.pop_back();
break;
159 case cmNEQ: x = x != y; m_vRPN.pop_back();
break;
160 case cmEQ: x = x == y; m_vRPN.pop_back();
break;
161 case cmADD: x = x + y; m_vRPN.pop_back();
break;
162 case cmSUB: x = x - y; m_vRPN.pop_back();
break;
163 case cmMUL: x = x * y; m_vRPN.pop_back();
break;
191 bool bOptimized =
false;
193 if (m_bEnableOptimizer)
195 std::size_t sz = m_vRPN.size();
201 if (sz >= 2 && m_vRPN[sz - 2].Cmd ==
cmVAL && m_vRPN[sz - 1].Cmd ==
cmVAL)
203 ConstantFolding(a_Oprt);
212 if (m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 1].Cmd ==
cmVAL)
214 if (m_vRPN[sz - 1].Val.data2 == 0)
216 m_vRPN[sz - 2].Cmd =
cmVAL;
217 m_vRPN[sz - 2].Val.ptr =
nullptr;
218 m_vRPN[sz - 2].Val.data = 0;
219 m_vRPN[sz - 2].Val.data2 = 1;
221 else if (m_vRPN[sz - 1].Val.data2 == 1)
222 m_vRPN[sz - 2].Cmd =
cmVAR;
223 else if (m_vRPN[sz - 1].Val.data2 == 2)
224 m_vRPN[sz - 2].Cmd = cmVARPOW2;
225 else if (m_vRPN[sz - 1].Val.data2 == 3)
226 m_vRPN[sz - 2].Cmd = cmVARPOW3;
227 else if (m_vRPN[sz - 1].Val.data2 == 4)
228 m_vRPN[sz - 2].Cmd = cmVARPOW4;
241 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
242 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR) ||
243 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
244 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
245 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
246 (m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
247 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAR && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) ||
248 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr))
251 (m_vRPN[sz - 2].Val.ptr ==
nullptr && m_vRPN[sz - 1].Val.ptr !=
nullptr) ||
252 (m_vRPN[sz - 2].Val.ptr !=
nullptr && m_vRPN[sz - 1].Val.ptr ==
nullptr) ||
253 (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr));
255 m_vRPN[sz - 2].Cmd = cmVARMUL;
256 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
257 m_vRPN[sz - 2].Val.data2 += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2;
258 m_vRPN[sz - 2].Val.data += ((a_Oprt ==
cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data;
265 if ((m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAL) ||
266 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd ==
cmVAR))
268 m_vRPN[sz - 2].Cmd = cmVARMUL;
269 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
270 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2;
271 m_vRPN[sz - 2].Val.data2 = 0;
276 (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) ||
277 (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd ==
cmVAL))
280 m_vRPN[sz - 2].Cmd = cmVARMUL;
281 m_vRPN[sz - 2].Val.ptr = (
value_type*)((
long long)(m_vRPN[sz - 2].Val.ptr) | (
long long)(m_vRPN[sz - 1].Val.ptr));
282 if (m_vRPN[sz - 1].Cmd ==
cmVAL)
284 m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2;
285 m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2;
289 m_vRPN[sz - 2].Val.data = m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2;
290 m_vRPN[sz - 2].Val.data2 = m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2;
296 m_vRPN[sz - 1].Cmd ==
cmVAR && m_vRPN[sz - 2].Cmd ==
cmVAR &&
297 m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr)
300 m_vRPN[sz - 2].Cmd = cmVARPOW2;
307 if (m_vRPN[sz - 1].Cmd ==
cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && m_vRPN[sz - 1].Val.data2 != 0)
310 m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2;
311 m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2;
330 m_vRPN.push_back(tok);
335 void ParserByteCode::AddIfElse(
ECmdCode a_Oprt)
339 m_vRPN.push_back(tok);
359 tok.Oprt.ptr = a_pVar;
360 m_vRPN.push_back(tok);
371 std::size_t sz = m_vRPN.size();
372 bool optimize =
false;
375 if (m_bEnableOptimizer && a_iArgc > 0)
383 for (
int i = 0; i < std::abs(a_iArgc); ++i)
385 if (m_vRPN[sz - i - 1].Cmd !=
cmVAL)
398 case 1: val = (*
reinterpret_cast<fun_type1>(a_pFun))(m_vRPN[sz - 1].Val.data2);
break;
399 case 2: val = (*
reinterpret_cast<fun_type2>(a_pFun))(m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
400 case 3: val = (*
reinterpret_cast<fun_type3>(a_pFun))(m_vRPN[sz - 3].Val.data2, m_vRPN[sz - 2].Val.data2, m_vRPN[sz - 1].Val.data2);
break;
401 case 4: val = (*
reinterpret_cast<fun_type4>(a_pFun))(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;
402 case 5: val = (*
reinterpret_cast<fun_type5>(a_pFun))(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;
403 case 6: val = (*
reinterpret_cast<fun_type6>(a_pFun))(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;
404 case 7: val = (*
reinterpret_cast<fun_type7>(a_pFun))(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;
405 case 8: val = (*
reinterpret_cast<fun_type8>(a_pFun))(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;
406 case 9: val = (*
reinterpret_cast<fun_type9>(a_pFun))(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;
407 case 10: val = (*
reinterpret_cast<fun_type10>(a_pFun))(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;
414 m_vRPN.erase(m_vRPN.end() - a_iArgc, m_vRPN.end());
420 tok.Val.ptr =
nullptr;
421 m_vRPN.push_back(tok);
427 tok.Fun.argc = a_iArgc;
428 tok.Fun.ptr = a_pFun;
429 m_vRPN.push_back(tok);
432 m_iStackPos = m_iStackPos - std::abs(a_iArgc) + 1;
433 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
445 m_iStackPos = m_iStackPos - a_iArgc + 1;
446 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
450 tok.Fun.argc = a_iArgc;
451 tok.Fun.ptr = a_pFun;
452 m_vRPN.push_back(tok);
465 m_iStackPos = m_iStackPos - a_iArgc + 1;
469 tok.Fun.argc = a_iArgc;
470 tok.Fun.idx = a_iIdx;
471 tok.Fun.ptr = a_pFun;
472 m_vRPN.push_back(tok);
474 m_iMaxStackSize = std::max(m_iMaxStackSize, (
size_t)m_iStackPos);
486 m_vRPN.push_back(tok);
487 rpn_type(m_vRPN).swap(m_vRPN);
490 std::stack<int> stIf, stElse;
492 for (
int i = 0; i < (int)m_vRPN.size(); ++i)
494 switch (m_vRPN[i].Cmd)
504 m_vRPN[idx].Oprt.offset = i - idx;
510 m_vRPN[idx].Oprt.offset = i - idx;
520 std::size_t ParserByteCode::GetMaxStackSize()
const
522 return m_iMaxStackSize + 1;
551 mu::console() <<
_T(
"Number of RPN tokens:") << (int)m_vRPN.size() <<
_T(
"\n");
552 for (std::size_t i = 0; i < m_vRPN.size() && m_vRPN[i].Cmd !=
cmEND; ++i)
555 switch (m_vRPN[i].Cmd)
562 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
566 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
570 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
574 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]\n");
578 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr <<
_T(
"]");
584 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
585 mu::console() <<
_T(
"[ADDR: 0x") << std::hex << reinterpret_cast<void*>(m_vRPN[i].Fun.ptr) <<
_T(
"]");
591 mu::console() <<
_T(
"[ARG:") << std::dec << m_vRPN[i].Fun.argc <<
_T(
"]");
592 mu::console() <<
_T(
"[IDX:") << std::dec << m_vRPN[i].Fun.idx <<
_T(
"]");
593 mu::console() <<
_T(
"[ADDR: 0x") <<
reinterpret_cast<void*
>(m_vRPN[i].Fun.ptr) <<
_T(
"]\n");
611 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
615 mu::console() <<
_T(
"[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset <<
_T(
"]\n");
625 default:
mu::console() <<
_T(
"(unknown code: ") << m_vRPN[i].Cmd <<
_T(
")\n");
Definition of the parser bytecode class.
#define _T(x)
Activate this option in order to compile with OpenMP support.
void AddStrFun(generic_fun_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 AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
Operator item: not equal.
For use in the ternary if-then-else operator.
value_type(* fun_type5)(value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* fun_type1)(value_type)
Callback type used for functions with a single arguments.
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.
Code for a generic function item.
value_type(* fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with eight arguments.
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.
value_type(* fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with ten arguments.
value_type(* fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with nine arguments.
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
value_type(* fun_type2)(value_type, value_type)
Callback type used for functions with two arguments.
Error class of the parser.
For use in the ternary if-then-else operator.
#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.
value_type(* fun_type3)(value_type, value_type, value_type)
Callback type used for functions with three arguments.
Operator item: greater than.
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
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.
value_type(* fun_type4)(value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
Bytecode implementation of the Math Parser.
value_type(* fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with seven arguments.
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.
value_type(* fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with six arguments.
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.