From a2ae1153693834df1258d301d5843a4039819544 Mon Sep 17 00:00:00 2001 From: hama Date: Sun, 3 Aug 2014 23:18:45 +0200 Subject: [PATCH] dayly work --- rplexpr/rplasclasses.cpp | 47 ++++++++- rplexpr/rplasclasses.hpp | 16 ++- rplexpr/rplastree.cpp | 80 ++++++++++---- rplexpr/rplastree.hpp | 37 ++++--- rplexpr/rplmfparser.cpp | 12 ++- rplexpr/rplvm.cpp | 187 +++++++++++++++++++++++++++++++++ rplexpr/rplvm.hpp | 54 ++++++++-- rplexpr/rplvm_test.cpp | 68 ++++++++++++ unittests/main.cpp | 3 + unittests/rplmfparser_test.cpp | 6 +- unittests/unittests.pro | 3 +- 11 files changed, 459 insertions(+), 54 deletions(-) create mode 100644 rplexpr/rplvm_test.cpp diff --git a/rplexpr/rplasclasses.cpp b/rplexpr/rplasclasses.cpp index 62772d3..c8c5fc8 100644 --- a/rplexpr/rplasclasses.cpp +++ b/rplexpr/rplasclasses.cpp @@ -206,6 +206,16 @@ const char*RplSymbolSpace::spaceTypeName(RplSymbolSpace::SymbolSpaceType type) } return rc; } +/** + * @brief Returns the list of the variables. + * + * @return the list of the variables + */ +RplSymbolSpace::VariableList RplSymbolSpace::listOfVars() const +{ + return m_listOfVars; +} + /** * @brief Returns the parent of the symbol space. * @@ -290,6 +300,24 @@ RplASItem* RplSymbolSpace::addMethod(RplASMethod* method) } return rc; } +/** + * @brief Adds a class to the instance. + * + * @param clazz the class to add + * @return NULL: success
+ * otherwise: the already defined class + */ +RplASUserClass* RplSymbolSpace::addClass(RplASUserClass* clazz) +{ + RplASUserClass* rc = NULL; + const QString& name = clazz->name(); + if (m_classes.contains(name)){ + rc = dynamic_cast(m_classes[name]); + } else { + m_classes[name] = clazz; + } + return rc; +} /** * @brief Returns the name of the symbol space. @@ -929,8 +957,11 @@ QString RplASFormula::toString(void* object, int) const * * @param name name of the user defined class */ -RplASUserClass::RplASUserClass(const QString& name, RplASTree& tree) : - RplASClass(name, tree) +RplASUserClass::RplASUserClass(const QString& name, + const RplSourcePosition* position, + RplASTree& tree) : + RplASClass(name, tree), + m_position(position) { } @@ -972,10 +1003,20 @@ bool RplASUserClass::boolValueOf(void* object) const * @param maxLength maximum length of the string * @return */ -QString RplASUserClass::toString(void* object, int maxLength) const +QString RplASUserClass::toString(void*, int) const { return m_name; } +/** + * @brief Returns the source position of the instance. + * + * @return the source position + */ +const RplSourcePosition* RplASUserClass::position() const +{ + return m_position; +} + /** @class RplASUserObject rplastree.hpp "rplexpr/rplastree.hpp" diff --git a/rplexpr/rplasclasses.hpp b/rplexpr/rplasclasses.hpp index d0798bf..888d5ac 100644 --- a/rplexpr/rplasclasses.hpp +++ b/rplexpr/rplasclasses.hpp @@ -25,6 +25,7 @@ protected: RplASClass* m_type; }; +class RplASUserClass; class RplSymbolSpace { public: @@ -40,6 +41,7 @@ public: typedef QMap VariableMap; typedef QMap ClassMap; typedef QMap MethodMap; + typedef QList VariableList; public: RplSymbolSpace(SymbolSpaceType type, const QString& name, RplSymbolSpace* parent); @@ -53,7 +55,9 @@ public: void setBody(RplASItem* body); RplASItem* addVariable(RplASVarDefinition* variable); RplASItem* addMethod(RplASMethod* method); - RplASClass* addClass(RplASClass* clazz); + RplASUserClass* addClass(RplASUserClass* clazz); + RplSymbolSpace* parent() const; + VariableList listOfVars() const; public: static void initGlobal(RplSymbolSpace& global); static const char* spaceTypeName(SymbolSpaceType type); @@ -65,9 +69,10 @@ private: MethodMap m_methods; RplSymbolSpace* m_parent; RplASItem* m_body; + VariableList m_listOfVars; + public: static RplSymbolSpace m_global; - RplSymbolSpace* parent() const; }; class RplASBoolean : public RplASClass { @@ -167,12 +172,17 @@ public: class RplASUserClass : public RplASClass { public: - RplASUserClass(const QString& name, RplASTree& tree); + RplASUserClass(const QString& name, const RplSourcePosition* position, + RplASTree& tree); public: void* newValueInstance(void* source = NULL) const; void destroyValueInstance(void* object) const; virtual bool boolValueOf(void* object) const; virtual QString toString(void *object, int maxLength = 80) const; + const RplSourcePosition* position() const; + +private: + const RplSourcePosition* m_position; }; class RplASUserObject { diff --git a/rplexpr/rplastree.cpp b/rplexpr/rplastree.cpp index 763da66..8b1638a 100644 --- a/rplexpr/rplastree.cpp +++ b/rplexpr/rplastree.cpp @@ -477,16 +477,38 @@ RplASItemType RplASItem::nodeType() const { return m_nodeType; } - -/** @class RplASExpr rplastree.hpp "rplexpr/rplastree.hpp" +/** + * @brief Returns the flags of the node. * - * @brief Implements the abstract base class of value containing items. + * @return the bitmask with the flags + */ +int RplASItem::flags() const +{ + return m_flags; +} +/** + * @brief Sets the flags of the node. * + * @param flags the new value of the bitmask */ -RplASCalculable::RplASCalculable() +void RplASItem::setFlags(int flags) { + m_flags = flags; } + +/** @class RplASCalculable rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief An abstract base class for items which calculates a value. + * + */ + +/** @class RplASStorable rplastree.hpp "rplexpr/rplastree.hpp" + * + * @brief Implements the abstract base class of value containing items. + * + */ + /** @class RplASConstant rplastree.hpp "rplexpr/rplastree.hpp" * * @brief Implements a constant for the Abstract Syntax Tree. @@ -506,11 +528,13 @@ RplASConstant::RplASConstant() : /** * @brief Calculates the expression. * - * @param value OUT: the calculated value + * @param value IN/OUT: the calculated value + * @return NULL */ -void RplASConstant::calc(RplASVariant& value) +RplASNode1* RplASConstant::calc(RplASVariant& value) { value = m_value; + return NULL; } /** @@ -573,11 +597,13 @@ RplASListOfVariants* RplASListConstant::list(){ /** * @brief Calculates the expression. * - * @param value OUT: the calculated value + * @param value IN/OUT: the calculated value + * @return NULL */ -void RplASListConstant::calc(RplASVariant& value) +RplASNode1* RplASListConstant::calc(RplASVariant& value) { value = m_value; + return NULL; } /** @@ -631,11 +657,14 @@ RplASMapConstant::RplASMapConstant() : /** * @brief Calculates the value. * - * @param value OUT: the value of the instance + * @param value IN/OUT: the value of the instance + * @return NULL */ -void RplASMapConstant::calc(RplASVariant&) +RplASNode1* RplASMapConstant::calc(RplASVariant& value) { - + // ToDo: copy map: + //value = m_value; + return NULL; } /** * @brief Writes the internals into a file. @@ -723,11 +752,12 @@ const QString& RplASNamedValue::name() const /** * @brief Calculates the value. * - * @param value OUT: the value of the instance + * @param value In/OUT: the value of the instance + * @return NULL */ -void RplASNamedValue::calc(RplASVariant& ) +RplASNode1* RplASNamedValue::calc(RplASVariant& value, RplStackFrame* frame) { - + return NULL; } /** * @brief Writes the internals into a file. @@ -859,10 +889,12 @@ void RplASVarDefinition::execute() /** * @brief Calculates the initialation value while interpreting. * - * @param value OUT: ignored + * @param value IN/OUT: ignored + * @return NULL */ -void RplASVarDefinition::calc(RplASVariant&) +RplASNode1* RplASVarDefinition::calc(RplASVariant&) { + return NULL; } /** @class RplASExprStatement rplastree.hpp "rplexpr/rplastree.hpp" @@ -893,10 +925,12 @@ void RplASExprStatement::execute() /** * @brief Calculates the value of the expression. * - * @param value OUT: the calculated value + * @param value IN/OUT: the calculated value + * @return NULL */ -void RplASExprStatement::calc(RplASVariant& ) +RplASNode1* RplASExprStatement::calc(RplASVariant& ) { + return NULL; } /** @@ -1279,18 +1313,22 @@ RplASCondition::RplASCondition() : { } -void RplASCondition::calc(RplASVariant& value) +/** + * @brief Calculates the value of the condition + * @param value IN/OUT: the bool value of the condition + * @return NULL + */ +RplASNode1* RplASCondition::calc(RplASVariant& value) { value.setBool(false); RplASCalculable* node = dynamic_cast(m_child); if (node == NULL) throw RplASException(m_position, "child of condition is not calculable"); node->calc(value); + return NULL; } /** * @brief Calculates the boolean value and returns it. - * - * @return the boolean value of the expression */ bool RplASCondition::calcAsBool() { diff --git a/rplexpr/rplastree.hpp b/rplexpr/rplastree.hpp index 9937bb5..4ff89a8 100644 --- a/rplexpr/rplastree.hpp +++ b/rplexpr/rplastree.hpp @@ -112,10 +112,12 @@ class RplASItem public: enum NodeFlags { NF_UNDEF, - /// Debugger: this node is a breakpoint - NF_BREAKPOINT = 1 << 1, + /// the node calculates a value: + VF_CALCULABLE = 1 << 1, /// the tree under this node is complete checked for data type correctness - NF_TYPECHECK_COMPLETE = 1 << 2 + NF_TYPECHECK_COMPLETE = 1 << 2, + /// debugger: this node is a breakpoint + NF_BREAKPOINT = 1 << 5 }; public: @@ -140,6 +142,9 @@ public: static void reset(); RplASItemType nodeType() const; + int flags() const; + void setFlags(int flags); + protected: unsigned int m_id:16; RplASItemType m_nodeType:8; @@ -150,12 +155,17 @@ private: static unsigned int m_nextId; }; +class RplASNode1; class RplASCalculable { public: - RplASCalculable(); + virtual RplASNode1* calc(RplASVariant& value) = 0; +}; + +class RplStackFrame; +class RplASStorable{ public: - virtual void calc(RplASVariant& value) = 0; + virtual RplASNode1* calc(RplASVariant& value, RplStackFrame* frame) = 0; }; class RplASConstant : public RplASItem, public RplASCalculable @@ -163,7 +173,7 @@ class RplASConstant : public RplASItem, public RplASCalculable public: RplASConstant(); public: - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value); public: virtual void dump(FILE* fp, int indent); RplASVariant& value(); @@ -171,6 +181,7 @@ private: RplASVariant m_value; }; + class RplASNode1 : public RplASItem { public: @@ -255,7 +266,7 @@ class RplASListConstant : public RplASNode1, public RplASCalculable public: RplASListConstant(); public: - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value); public: virtual void dump(FILE* fp, int indent); RplASVariant& value(); @@ -268,7 +279,7 @@ class RplASMapConstant : public RplASNode1, public RplASCalculable public: RplASMapConstant(); public: - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value); public: virtual void dump(FILE* fp, int indent); RplASVariant& value(); @@ -277,7 +288,7 @@ private: RplASVariant m_value; }; -class RplASNamedValue : public RplASNode1, public RplASCalculable +class RplASNamedValue : public RplASNode1, public RplASStorable { public: enum Attributes { @@ -301,7 +312,7 @@ public: public: const QString& name() const; public: - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value, RplStackFrame* frame); void dump(FILE* fp, int indent); RplASClass* dataType() const; @@ -333,7 +344,7 @@ public: RplASVarDefinition(); public: virtual void execute(); - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value); void dump(FILE* fp, int indent); const QString& name() const; RplASClass* datatype() const; @@ -345,7 +356,7 @@ public: RplASExprStatement(); public: virtual void execute(); - virtual void calc(RplASVariant& value); + virtual RplASNode1* calc(RplASVariant& value); void dump(FILE* fp, int indent); }; @@ -377,7 +388,7 @@ class RplASCondition : public RplASNode1, public RplASCalculable public: RplASCondition(); public: - void calc(RplASVariant& value); + RplASNode1* calc(RplASVariant& value); bool calcAsBool(); void dump(FILE* fp, int indent); }; diff --git a/rplexpr/rplmfparser.cpp b/rplexpr/rplmfparser.cpp index cf9350f..14e07e7 100644 --- a/rplexpr/rplmfparser.cpp +++ b/rplexpr/rplmfparser.cpp @@ -59,7 +59,9 @@ enum MFLocations{ L_PARSE_VAR_DEF_ALREADY_DEFINED, L_PARSE_VAR_DEF_ALREADY_DEFINED2, L_PARSE_CLASS_NO_NAME, - L_PARSE_CLASS_LOWERCASE = 2050 + L_PARSE_CLASS_LOWERCASE = 2050, + L_PARSE_CLASS_ALREADY_DEFINED, + L_PARSE_CLASS_ALREADY_DEFINED2 }; @@ -988,9 +990,13 @@ void RplMFParser::parseClass() if (! token->isCapitalizedId()) syntaxError(L_PARSE_CLASS_LOWERCASE, "class name must start with an uppercase character"); QString name = token->toString(); - RplASUserClass* clazz = new RplASUserClass(name, m_tree); + RplASUserClass* clazz = new RplASUserClass(name, startPos, m_tree); RplSymbolSpace* parent = m_tree.currentSpace(); - parent->addClass(clazz); + RplASUserClass* alreadyDefined = parent->addClass(clazz); + if (alreadyDefined != NULL){ + error(L_PARSE_CLASS_ALREADY_DEFINED, alreadyDefined->position(), + "class already defined", "previous defined class"); + } m_tree.startClassOrMethod(name, RplSymbolSpace::SST_CLASS); clazz->setSymbols(); diff --git a/rplexpr/rplvm.cpp b/rplexpr/rplvm.cpp index 8e351c4..e63779c 100644 --- a/rplexpr/rplvm.cpp +++ b/rplexpr/rplvm.cpp @@ -10,4 +10,191 @@ #include "rplcore/rplcore.hpp" #include "rplexpr/rplexpr.hpp" +/** @class RplVmException rplvm.hpp "rplexpr/rplvm.hpp" + * + * @brief Implements an exception for the virtual machine. + * + */ +/** + * @brief Constructor + * @param format the message with placeholders + * @param ... the values for the placeholders + */ +RplVmException::RplVmException(const char* format, ...) : + RplException("") +{ + char buffer[16000]; + va_list ap; + va_start(ap, format); + vsnprintf(buffer, sizeof buffer, format, ap); + va_end(ap); + m_message = buffer; +} +/** @class RplStackFrame rplvm.hpp "rplexpr/rplvm.hpp" + * + * @brief Implements the storage for a symbol space. + * + * The owner of a symbol space can be "global", a module, a class, or a method. + * Some symbol spaces have more than one stack frame, e.g. a recursive called + * method. + */ + + +/** + * @brief Constructor. + * + * @param symbols the symbol space belonging to the stack frame + */ + +RplStackFrame::RplStackFrame(RplSymbolSpace* symbols) : + m_countVariables(symbols->listOfVars().size()), + m_variables(NULL), + m_symbols(symbols) +{ + if (m_countLocals > 0) + m_variables = new RplASVariant[m_countVariables]; +} + +/** + * @brief Destructor. + */ +RplStackFrame::~RplStackFrame() +{ + delete[] m_variables; + m_variables = NULL; +} + +/** + * @brief Returns the storage of a variable given by the index. + * + * @param index the index of the variable + * + * @return the storage of the variable + */ +RplASVariant& RplStackFrame::valueOfVariable(int index) +{ + if (index < 0 || index >= m_countVariables) + throw RplVmException("valueOfVariable(): invalid index: %d", index); + return *m_listOfVariables[index]; +} + +/** @class RplVMThread rplvm.hpp "rplexpr/rplvm.hpp" + * + * @brief Implements a thread of the virtual machine. + * + * The virtual machine can execute many threads at the same time. + * Each thread has its own stack. + */ + +/** + * @brief Constructor. + * + * @param maxStack the maximal number of nested stack frames + * @param vm the parent, the virtual machine + */ +RplVMThread::RplVMThread(int maxStack, RplVirtualMachine* vm) : + m_singleStep(false), + m_debugMode(false), + m_maxStack(maxStack), + m_stack(), + m_currentValue(), + m_vm(vm) +{ + m_stack.reserve(maxStack); +} + +/** + * @brief Executes a statement list. + * + * @param statements the first statement of a statement list chained by + * m_child + * @param space the current symbol space + */ +void RplVMThread::execute(RplASNode1* statements, RplSymbolSpace* space) +{ + bool debugMode = m_debugMode; + while(statements != NULL){ + if (debugMode + && (m_singleStep || (statement->flags() & NF_BREAKPOINT) != 0)) + debug(statements); + RplASCalculable* statement = dynamic_cast(statements); + statement->calc(&m_currentValue); + } +} + +/** + * @brief Handles a debugger break. + * + * @param statement the current statement (not yet executed) + */ +void RplVMThread::debug(RplASNode1* statement) +{ + +} + +/** @class RplVirtualMachine rplvm.hpp "rplexpr/rplvm.hpp" + * + * @brief Implements a virtual machine. + * + * This is a execution unit which interprets an abstract syntax tree. + */ +RplVirtualMachine::RplVirtualMachine(RplASTree* tree, RplSource* source, + int maxStack) : + m_maxStack(maxStack), + m_threads(), + m_flags(VF_UNDEF), + m_source(source), + m_tree(tree) +{ + m_threads.reserve(8); +} + +/** + * @brief Adds a thread to the instance. + * + * @param program the statement list to execute + * @param space the current symbol space + * @param maxStack the maximal number of nested stack frames. + * <= 0: use the default + */ +void RplVirtualMachine::addThread(RplASItem* program, RplSymbolSpace* space, + int maxStack) +{ + RplVMThread* thread = new RplVMThread( + maxThread <= 0 ? m_maxStack : maxStack, self); + m_threads.append(thread); + thread->execute(program, space); +} +/** + * @brief Tests whether a given flag is set. + * + * @param flag flag to test + * @return true: the flag is set
+ * false: otherwise + */ +bool RplVirtualMachine::hasFlag(RplVirtualMachine::VMFlag flag) const +{ + bool rc = (m_flags & flag) != 0; +} +/** + * @brief Adds a flag to the current flags. + * + * @param flag + * @return + */ +void RplVirtualMachine::setFlag(RplVirtualMachine::VMFlag flag) +{ + m_flag |= flag; +} + +/** + * @brief Adds a flag to the current flags. + * + * @param flag + * @return + */ +void RplVirtualMachine::clearFlag(RplVirtualMachine::VMFlag flag) +{ + m_flag &= ~flag; +} diff --git a/rplexpr/rplvm.hpp b/rplexpr/rplvm.hpp index c8f8d62..2fa0a07 100644 --- a/rplexpr/rplvm.hpp +++ b/rplexpr/rplvm.hpp @@ -10,25 +10,65 @@ #ifndef RPLVM_HPP #define RPLVM_HPP +class RplVmException : public RplException { +public: + RplVmException(const char* message, ...); +}; class RplStackFrame { public: - RplStackFrame(int countArgs, int countLocals); + RplStackFrame(RplSymbolSpace* symbols); ~RplStackFrame(); public: + RplASVariant& valueOfVariable(int index); private: + int m_countVariables; RplASVariant* m_variables; + RplSymbolSpace* m_symbols; }; -class RPLVirtualMachine +class RplVirtualMachine; +class RplVMThread { public: - RPLVirtualMachine(); + typedef QList StackFrameList; +public: + RplVMThread(int maxStack, RplVirtualMachine* vm); +public: + void execute(RplASNode1* statements, RplSymbolSpace* space); + virtual void debug(RplASNode1* statement); +protected: + bool m_debugMode; + bool m_singleStep; + int m_maxStack; + StackFrameList m_stack; + RplASVariant m_currentValue; + RplVirtualMachine* m_vm; +}; + +class RplVirtualMachine +{ +public: + enum VMFlag { + VF_UNDEF, + VF_TRACE_STATEMENTS = 1<<1, + VF_TRACE_LOCALS = 1<<2, + VF_TRACE_AUTO_VARIABLES = 1<<3 + + }; + +public: + RplVirtualMachine(RplASTree& tree, RplSource& source, int maxStack = 1024); public: - void calc(); + void addThread(RplASItem* program, RplSymbolSpace* space, int maxStack = 0); + bool hasFlag(VMFlag flag) const; + void setFlag(VMFlag flag); + void clearFlag(VMFlag flag); private: - RplStackFrame m_global; - QMap m_modules; - QList m_stack; + int m_maxStack; + QList m_threads; + int m_flags; + RplSource& m_source; + RplASTree& m_tree; }; #endif // RPLVM_HPP diff --git a/rplexpr/rplvm_test.cpp b/rplexpr/rplvm_test.cpp new file mode 100644 index 0000000..d3acb7f --- /dev/null +++ b/rplexpr/rplvm_test.cpp @@ -0,0 +1,68 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + +#include "rplcore/rplcore.hpp" +#include "rplexpr/rplexpr.hpp" +#include "rplcore/rpltest.hpp" + +class TestRplVM : public RplTest{ +private: + RplSource m_source; + RplASTree m_tree; + RplStringReader m_reader; + const char* m_currentSource; +public: + TestRplVM() : + RplTest("RplVM"), + m_source(), + m_tree(), + m_reader(m_source) + { + m_source.addReader(&m_reader); + } +protected: + void setSource(const char* content){ + RplASItem::reset(); + m_currentSource = content; + m_tree.clear(); + m_source.clear(); + m_reader.clear(); + m_reader.addSource("", content); + m_source.addReader(&m_reader); + m_source.addSourceUnit(m_reader.currentSourceUnit()); + } + +private: + void checkAST(RplVirtualMachine& vm, const char* fileExpected, int lineNo){ + QByteArray fnExpected = "test"; + fnExpected += QDir::separator().toLatin1(); + fnExpected += "rplvm"; + fnExpected += (char) QDir::separator().toLatin1(); + fnExpected += fileExpected; + QByteArray fnCurrent = getTempFile(fileExpected, "rplvm"); + vm.dump(fnCurrent, RplASTree::DMP_NO_GLOBALS); + assertEqualFiles(fnExpected.constData(), fnCurrent.constData(), + __FILE__, lineNo); + } +public: + void baseTest(){ + setSource("Int a=2+3*4"); + RplMFParser parser(m_source, m_tree); + parser.parse(); + RplVirtualMachine vm(m_tree, m_source); + checkAST(vm, "baseTest.txt", __LINE__); + } + virtual void doIt(void) { + baseTest(); + } +}; +void testRplVM() { + TestRplVM test; + test.run(); +} + diff --git a/unittests/main.cpp b/unittests/main.cpp index bee689c..87406f8 100644 --- a/unittests/main.cpp +++ b/unittests/main.cpp @@ -22,6 +22,9 @@ void testCore(){ } void testExpr(){ + extern void testRplVM(); + testRplVM(); + extern void testRplMFParser(); testRplMFParser(); diff --git a/unittests/rplmfparser_test.cpp b/unittests/rplmfparser_test.cpp index 14f1174..13edfaa 100644 --- a/unittests/rplmfparser_test.cpp +++ b/unittests/rplmfparser_test.cpp @@ -10,14 +10,14 @@ #include "rplexpr/rplexpr.hpp" #include "rplcore/rpltest.hpp" -class TestRplMFParser : public RplTest{ +class TestRplVM : public RplTest{ private: RplSource m_source; RplASTree m_tree; RplStringReader m_reader; const char* m_currentSource; public: - TestRplMFParser() : + TestRplVM() : RplTest("RplMFParser"), m_source(), m_tree(), @@ -189,7 +189,7 @@ public: } }; void testRplMFParser() { - TestRplMFParser test; + TestRplVM test; test.run(); } diff --git a/unittests/unittests.pro b/unittests/unittests.pro index 4ce578f..891dbfd 100644 --- a/unittests/unittests.pro +++ b/unittests/unittests.pro @@ -36,5 +36,6 @@ SOURCES += main.cpp \ ../rplcore/rplqstring.cpp \ ../rplexpr/rplasclasses.cpp \ rplastree_test.cpp \ - rplmfparser_test.cpp + rplmfparser_test.cpp \ + ../rplexpr/rplvm_test.cpp -- 2.39.5