25 #include <QMessageLogger>
32 #include "../vmisc/vmath.h"
41 :m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true)
53 :m_iStackPos(a_ByteCode.m_iStackPos), m_iMaxStackSize(a_ByteCode.m_iMaxStackSize), m_vRPN(a_ByteCode.m_vRPN),
54 m_bEnableOptimizer(true)
67 if (
this != &a_ByteCode)
82 if (
this==&a_ByteCode)
107 tok.
Val.ptr = a_pVar;
135 tok.
Val.ptr =
nullptr;
137 tok.
Val.data2 = a_fVal;
145 qreal &x =
m_vRPN[sz-2].Val.data2,
146 &y =
m_vRPN[sz-1].Val.data2;
150 x =
static_cast<int>(x) &&
static_cast<int>(y);
154 x =
static_cast<int>(x) ||
static_cast<int>(y);
194 #if defined(MUP_MATH_EXCEPTIONS)
213 QT_WARNING_DISABLE_INTEL(1195)
214 QT_WARNING_DISABLE_MSVC(4826)
230 bool bOptimized =
false;
232 if (m_bEnableOptimizer)
234 int sz = m_vRPN.size();
240 if (sz>=2 && m_vRPN.at(sz-2).Cmd ==
cmVAL && m_vRPN.at(sz-1).Cmd ==
cmVAL)
242 ConstantFolding(a_Oprt);
251 if (m_vRPN.at(sz-2).Cmd ==
cmVAR && m_vRPN.at(sz-1).Cmd ==
cmVAL)
253 if (qFuzzyCompare(m_vRPN.at(sz-1).Val.data2, 2))
257 else if (qFuzzyCompare(m_vRPN.at(sz-1).Val.data2, 3))
261 else if (qFuzzyCompare(m_vRPN.at(sz-1).Val.data2, 4))
278 if ( (m_vRPN.at(sz-1).Cmd ==
cmVAR && m_vRPN.at(sz-2).Cmd ==
cmVAL) ||
279 (m_vRPN.at(sz-1).Cmd ==
cmVAL && m_vRPN.at(sz-2).Cmd ==
cmVAR) ||
280 (m_vRPN.at(sz-1).Cmd ==
cmVAL && m_vRPN.at(sz-2).Cmd ==
cmVARMUL) ||
281 (m_vRPN.at(sz-1).Cmd ==
cmVARMUL && m_vRPN.at(sz-2).Cmd ==
cmVAL) ||
282 (m_vRPN.at(sz-1).Cmd ==
cmVAR && m_vRPN.at(sz-2).Cmd ==
cmVAR &&
283 m_vRPN.at(sz-2).Val.ptr == m_vRPN.at(sz-1).Val.ptr) ||
284 (m_vRPN.at(sz-1).Cmd ==
cmVAR && m_vRPN.at(sz-2).Cmd ==
cmVARMUL
285 && m_vRPN.at(sz-2).Val.ptr == m_vRPN.at(sz-1).Val.ptr) ||
286 (m_vRPN.at(sz-1).Cmd ==
cmVARMUL && m_vRPN.at(sz-2).Cmd ==
cmVAR &&
287 m_vRPN.at(sz-2).Val.ptr == m_vRPN.at(sz-1).Val.ptr) ||
289 m_vRPN.at(sz-2).Val.ptr == m_vRPN.at(sz-1).Val.ptr) )
291 assert( (m_vRPN.at(sz-2).Val.ptr==
nullptr && m_vRPN.at(sz-1).Val.ptr!=
nullptr) ||
292 (m_vRPN.at(sz-2).Val.ptr!=
nullptr && m_vRPN.at(sz-1).Val.ptr==
nullptr) ||
293 (m_vRPN.at(sz-2).Val.ptr == m_vRPN.at(sz-1).Val.ptr) );
296 m_vRPN[sz-2].Val.ptr =
reinterpret_cast<qreal*
>(
297 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-2).Val.ptr) |
298 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-1).Val.ptr));
299 m_vRPN[sz-2].Val.data2 += ((a_Oprt==
cmSUB) ? -1 : 1) * m_vRPN.at(sz-1).Val.data2;
300 m_vRPN[sz-2].Val.data += ((a_Oprt==
cmSUB) ? -1 : 1) * m_vRPN.at(sz-1).Val.data;
306 if ( (m_vRPN.at(sz-1).Cmd ==
cmVAR && m_vRPN.at(sz-2).Cmd ==
cmVAL) ||
307 (m_vRPN.at(sz-1).Cmd ==
cmVAL && m_vRPN.at(sz-2).Cmd ==
cmVAR) )
310 m_vRPN[sz-2].Val.ptr =
reinterpret_cast<qreal*
>(
311 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-2).Val.ptr) |
312 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-1).Val.ptr));
313 m_vRPN[sz-2].Val.data = m_vRPN.at(sz-2).Val.data2 + m_vRPN.at(sz-1).Val.data2;
314 m_vRPN[sz-2].Val.data2 = 0;
318 else if ( (m_vRPN.at(sz-1).Cmd ==
cmVAL && m_vRPN.at(sz-2).Cmd ==
cmVARMUL) ||
319 (m_vRPN.at(sz-1).Cmd ==
cmVARMUL && m_vRPN.at(sz-2).Cmd ==
cmVAL) )
323 m_vRPN[sz-2].Val.ptr =
reinterpret_cast<qreal*
>(
324 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-2).Val.ptr) |
325 reinterpret_cast<qlonglong
>(m_vRPN.at(sz-1).Val.ptr));
326 if (m_vRPN.at(sz-1).Cmd ==
cmVAL)
328 m_vRPN[sz-2].Val.data *= m_vRPN.at(sz-1).Val.data2;
329 m_vRPN[sz-2].Val.data2 *= m_vRPN.at(sz-1).Val.data2;
333 m_vRPN[sz-2].Val.data = m_vRPN.at(sz-1).Val.data * m_vRPN.at(sz-2).Val.data2;
334 m_vRPN[sz-2].Val.data2 = m_vRPN.at(sz-1).Val.data2 * m_vRPN.at(sz-2).Val.data2;
339 else if (m_vRPN.at(sz-1).Cmd ==
cmVAR && m_vRPN.at(sz-2).Cmd ==
cmVAR &&
340 m_vRPN.at(sz-1).Val.ptr == m_vRPN.at(sz-2).Val.ptr)
349 if (m_vRPN.at(sz-1).Cmd ==
cmVAL && m_vRPN.at(sz-2).Cmd ==
cmVARMUL &&
350 not qFuzzyIsNull(m_vRPN.at(sz-1).Val.data2))
353 m_vRPN[sz-2].Val.data /= m_vRPN.at(sz-1).Val.data2;
354 m_vRPN[sz-2].Val.data2 /= m_vRPN.at(sz-1).Val.data2;
367 if (bOptimized ==
false)
372 m_vRPN.push_back(tok);
404 tok.
Oprt.ptr = a_pVar;
430 tok.
Fun.argc = a_iArgc;
431 tok.
Fun.ptr = a_pFun;
449 tok.
Fun.argc = a_iArgc;
450 tok.
Fun.ptr = a_pFun;
468 tok.
Fun.argc = a_iArgc;
469 tok.
Fun.idx = a_iIdx;
470 tok.
Fun.ptr = a_pFun;
492 for (
int i=0; i<
m_vRPN.size(); ++i)
502 m_vRPN[idx].Oprt.offset = i - idx;
506 m_vRPN[idx].Oprt.offset = i - idx;
549 if (
m_vRPN.size() ==
false)
551 qDebug() <<
"No bytecode available\n";
555 qDebug() <<
"Number of RPN tokens:" <<
m_vRPN.size() <<
"\n";
558 qDebug() << i <<
" : \t";
562 qDebug() <<
"VAL \t" <<
"[" <<
m_vRPN.at(i).Val.data2 <<
"]\n";
565 qDebug() <<
"VAR \t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Val.ptr,
'f', 16) <<
"]\n";
568 qDebug() <<
"VARPOW2 \t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Val.ptr,
'f', 16) <<
"]\n";
571 qDebug() <<
"VARPOW3 \t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Val.ptr,
'f', 16) <<
"]\n";
574 qDebug() <<
"VARPOW4 \t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Val.ptr,
'f', 16) <<
"]\n";
577 qDebug() <<
"VARMUL \t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Val.ptr,
'f', 16) <<
"]" <<
" * ["
578 <<
m_vRPN.at(i).Val.data <<
"]" <<
" + [" <<
m_vRPN.at(i).Val.data2 <<
"]\n";
581 qDebug() <<
"CALL\t" <<
"[ARG:" <<
m_vRPN.at(i).Fun.argc <<
"]" <<
"[ADDR: 0x" <<
m_vRPN.at(i).Fun.ptr <<
"]"
585 qDebug() <<
"CALL STRFUNC\t" <<
"[ARG:" <<
m_vRPN.at(i).Fun.argc <<
"]" <<
"[IDX:" <<
m_vRPN.at(i).Fun.idx
586 <<
"]" <<
"[ADDR: 0x" <<
m_vRPN.at(i).Fun.ptr <<
"]\n";
628 qDebug() <<
"IF\t" <<
"[OFFSET:" <<
m_vRPN.at(i).Oprt.offset <<
"]\n";
631 qDebug() <<
"ELSE\t" <<
"[OFFSET:" <<
m_vRPN.at(i).Oprt.offset <<
"]\n";
634 qDebug() <<
"ENDIF\n";
break;
636 qDebug() <<
"ASSIGN\t" <<
"[ADDR: 0x" << QString::number(*
m_vRPN.at(i).Oprt.ptr,
'f', 16) <<
"]\n";
650 qDebug() <<
"(unknown code: " <<
m_vRPN.at(i).Cmd <<
")\n";
Bytecode implementation of the Math Parser.
void AddIfElse(ECmdCode a_Oprt)
void ConstantFolding(ECmdCode a_Oprt)
void Finalize()
Add end marker to bytecode.
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
const SToken * GetBase() const
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
void AddVal(qreal a_fVal)
Add a Variable pointer to bytecode.
unsigned m_iMaxStackSize
Maximum size needed for the stack.
QmuParserByteCode()
Bytecode default constructor.
unsigned m_iStackPos
Position in the Calculation array.
rpn_type m_vRPN
The actual rpn storage.
void AddVar(qreal *a_pVar)
Add a Variable pointer to bytecode.
void clear()
Delete the bytecode.
void Assign(const QmuParserByteCode &a_ByteCode)
Copy state of another object to this.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AsciiDump()
Dump bytecode (for debugging only!).
QVector< SToken > rpn_type
Token vector for storing the RPN.
QmuParserByteCode & operator=(const QmuParserByteCode &a_ByteCode)
Assignment operator.
void AddAssignOp(qreal *a_pVar)
Add an assignement operator.
Error class of the parser.
Namespace for mathematical applications.
@ ecINTERNAL_ERROR
Internal error of any kind.
@ ecDIV_BY_ZERO
Division by zero (currently unused)
@ cmOPRT_INFIX
code for infix operators
@ cmBC
Operator item: closing bracket.
@ cmLE
Operator item: less or equal.
@ cmUNKNOWN
uninitialized item
@ cmSUB
Operator item: subtract.
@ cmGT
Operator item: greater than.
@ cmSTRING
Code for a string token.
@ cmFUNC
Code for a generic function item.
@ cmFUNC_STR
Code for a function with a string parameter.
@ cmLT
Operator item: less than.
@ cmMUL
Operator item: multiply.
@ cmGE
Operator item: greater or equal.
@ cmADD
Operator item: add.
@ cmASSIGN
Operator item: Assignment operator.
@ cmENDIF
For use in the ternary if-then-else operator.
@ cmELSE
For use in the ternary if-then-else operator.
@ cmEQ
Operator item: equals.
@ cmFUNC_BULK
Special callbacks for Bulk mode with an additional parameter for the bulk index.
@ cmARG_SEP
function argument separator
@ cmPOW
Operator item: y to the power of ...
@ cmNEQ
Operator item: not equal.
@ cmOPRT_BIN
user defined binary operator
@ cmIF
For use in the ternary if-then-else operator.
@ cmOPRT_POSTFIX
code for postfix operators
@ cmDIV
Operator item: division.
@ cmBO
Operator item: opening bracket.
qreal(* generic_fun_type)()
Callback type used for functions without arguments.
QT_WARNING_POP static Q_REQUIRED_RESULT bool QmuFuzzyComparePossibleNulls(double p1, double p2)
Definition of the parser bytecode class.
This file defines the error class used by the parser.
struct qmu::SToken::@3::@6 Fun
struct qmu::SToken::@3::@5 Val
struct qmu::SToken::@3::@7 Oprt