]> gitweb.hamatoma.de Git - reqt/commitdiff
dayly work
authorhama <hama@siduction.net>
Fri, 15 Aug 2014 22:34:53 +0000 (00:34 +0200)
committerhama <hama@siduction.net>
Fri, 15 Aug 2014 22:34:53 +0000 (00:34 +0200)
24 files changed:
README.md
rplcore/rplbytestorage.cpp
rplcore/rpllogger.cpp
rplcore/rplqstring.cpp
rplcore/rpltest.cpp
rplcore/rplwriter.cpp
rplcore/rplwriter.hpp
rpldoc.zip [new file with mode: 0644]
rplexpr/rplasclasses.cpp
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rplmfparser.cpp
rplexpr/rplsource.cpp
rplexpr/rplvm.cpp
rplexpr/rplvm.hpp
rplexpr/rplvm_test.cpp [deleted file]
rplmodules.hpp
rplnet/rpltcppeer.cpp
rplnet/rpltcpserver.cpp
unittests/rplastree_test.cpp
unittests/rplexception_test.cpp
unittests/rplmfparser_test.cpp
unittests/rplvm_test.cpp [new file with mode: 0644]
unittests/unittests.pro

index f1c2568b984a238dc452b236bd83ff7c3f45c73a..f879c271c327f2bab3362347bdf7dcac407319c5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
+doc:
+* rpldoc.zip contains a full source code documentation generated by Doxygen
 usage:
 * copy (or link) the wanted source directories (e.g. rplcore+rplnet) into your project.
-* insert the main include files (e.g. rplcore/rplcore.hpp) into your source
+* each of the sublibraries rplcore, rplmath, rplexpr... has a main include file, e.g. rplcore/rplcore.hpp
+* include this main include file into your source
+
 
 
index 4aca921cae4d26dcf7d671265e1b1927a5eb0172..df1600bc94e768df52a3e94c0c78889becf56d9b 100644 (file)
@@ -12,7 +12,7 @@
  */
 /** @file rplcore/rplbytestorage.hpp
  *
- * @brief Definitions for a very efficient storage for bytes and C strings.
+ * @brief Definitions for a very efficient storage for bytes and C strings.
  */
 
 #include "rplcore/rplcore.hpp"
@@ -114,7 +114,7 @@ const char* RplByteStorage::allocateChars(const char* source, int size)
 /**
  * @brief Duplicates a string into a new allocated block.
  *
- * The unicode string will be converted into a UTF-8 string.
+ * The unicode string will be converted into an UTF-8 string.
  *
  * @param source    the source string
  * @return          a copy of the source string. The copy ends always with '\0'
index b998d68fe6838f8d48e071a0938a87f168aa8108..f8ac50d64090e9a272365d6a5937a6b2960f882c 100644 (file)
@@ -49,7 +49,7 @@ void RplLogger::destroyGlobalLogger() {
  *
  * @brief Puts the logging info to a medium (e.g. a file).
  *
- * This is a abstract base class.
+ * This is an abstract base class.
  */
 
 /**
@@ -581,7 +581,7 @@ void RplFileAppender::log(RplLoggerLevel level, int location,
 
 /** @class RplMemoryAppender rpllogger.hpp "rplcore/rpllogger.hpp"
  *
- * @brief Puts the logging info to a internal buffer.
+ * @brief Puts the logging info to an internal buffer.
  *
  * This line list can be required: <code>getLines()</code>.
  */
index b0d64af3d4c552cfcf825fb60395b400e9c9fb39..2cd8995748ef62bcbf647146e1d3a84614d81a23 100644 (file)
@@ -161,7 +161,7 @@ int RplQString::lengthOfReal(const QString& text, int start, qreal* pValue)
 }
 
 /**
- * @brief Converts a QString into a utf-8 string
+ * @brief Converts a QString into an utf-8 string
  *
  * The expression <code>qstring.toUtf8().constData()</code> is not allowed
  * in a variable argument list like sprintf. This is a thread save workaround.
index 3fd6a3e566c7632781e74f19a0f775e60ebd2fcd..249efa628a42419df32bba771ebc1a793ac753f0 100644 (file)
@@ -17,7 +17,7 @@
 
 /** @class RplTest rpltest.hpp "rplcore/repltest"
  *
- * @brief Implements a unit test base class similar JUnit for java.
+ * @brief Implements an unit test base class similar JUnit for java.
  *
  * Example for usage:
  *
@@ -434,7 +434,7 @@ bool RplTest::logContains(const char* pattern)
  * @param node          NULL or the node (name without path)
  * @param parent        NULL or a node of the parent
  * @param withSeparator true: the result ends with slash/backslash
- * @return              the name of a existing directory
+ * @return              the name of an existing directory
  */
 QByteArray RplTest::getTempDir(const char* node, const char* parent,
                                bool withSeparator) {
index de35350a6832195db88398b1cafa2ee548dde5a5..4ff58d160fdcad436b39cfdb96656740117d001d 100644 (file)
@@ -15,7 +15,7 @@
 /** @file rplcore/rplwriter.hpp
  *
  * @brief Definitions for a writer to an output media.
-
+ */
 #include "rplcore/rplcore.hpp"
 
 const char* RplWriter::m_tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
@@ -68,12 +68,10 @@ void RplWriter::indent(int indent)
  */
 void RplWriter::format(const char* format, ...)
 {
-    char buffer[64000];
     va_list ap;
     va_start(ap, format);
-    vsnprintf(buffer, sizeof buffer, format, ap);
+    write(ap, format);
     va_end(ap);
-    write(buffer);
 }
 /**
  * @brief Formats a line and write it to the output medium.
@@ -91,6 +89,19 @@ void RplWriter::formatLine(const char* format, ...)
     writeLine(buffer);
 }
 
+/**
+ * @brief Formats a message and writes it to the output medium.
+ *
+ * @param ap        variable argument list (like in <code>vsprintf</code>)
+ * @param format    format string with placeholders
+ */
+void RplWriter::write(va_list ap, const char* format)
+{
+    char buffer[64000];
+    vsnprintf(buffer, sizeof buffer, format, ap);
+    write(buffer);
+}
+
 /**
  * @brief Writes a line with indention to the output medium.
  *
@@ -130,12 +141,15 @@ void RplWriter::formatIndented(int indent, const char* format, ...)
 /**
  * @brief Constructor.
  *
- * @param filename  the file's name
- * @param mode      write mode, "w" for write or "a" for append
- * @param eoln      line end: "\n" or "\r\n"
+ * @param filename          the file's name
+ * @param mode              write mode, "w" for write or "a" for append
+ * @param additionalStream  if not NULL the content will be written to this
+ *                          stream too. Normal usage: <code>stdout</code> or
+ *                          <code>stderr</code>
+ * @param eoln              line end: "\n" or "\r\n"
  */
 RplFileWriter::RplFileWriter(const char* filename, const char* mode,
-                             const char* eoln) :
+                             FILE* additionalStream, const char* eoln) :
     m_fp(fopen(filename, mode)),
     m_name(filename),
     m_eoln(eoln)
@@ -148,9 +162,10 @@ RplFileWriter::RplFileWriter(const char* filename, const char* mode,
  */
 void RplFileWriter::write(const char* message)
 {
-    if (m_fp != NULL){
+    if (m_fp != NULL)
         fputs(message, m_fp);
-    }
+    if (m_additionalStream != NULL)
+        fputs(message, m_additionalStream);
 }
 
 /**
@@ -164,6 +179,11 @@ void RplFileWriter::writeLine(const char* line)
             fputs(line, m_fp);
         fputs(m_eoln, m_fp);
     }
+    if (m_additionalStream != NULL){
+        if (line != NULL)
+            fputs(line, m_additionalStream);
+        fputc('\n', m_additionalStream);
+    }
 }
 
 /**
@@ -175,4 +195,5 @@ void RplFileWriter::close()
         fclose(m_fp);
         m_fp = NULL;
     }
+    m_additionalStream = NULL;
 }
index d9d57726b815ec6d77900e0348d8c25480650943..7b661e39760b649737e4e74be48db914a616729c 100644 (file)
@@ -32,6 +32,7 @@ public:
     void indent(int indent);
     void format(const char* format, ...);
     void formatLine(const char* format, ...);
+    void write(va_list ap, const char* format);
     void writeIndented(int indent, const char* line);
     void formatIndented(int indent, const char* format, ...);
 protected:
@@ -43,7 +44,7 @@ class RplFileWriter : public RplWriter
 {
 public:
     RplFileWriter(const char* filename, const char* mode = "w",
-                  const char* eoln =  "\n");
+                  FILE* additionalStream = NULL, const char* eoln =  "\n");
 public:
     virtual void write(const char* line);
     virtual void writeLine(const char* line = NULL);
@@ -52,6 +53,7 @@ protected:
     FILE* m_fp;
     QByteArray m_name;
     QByteArray m_eoln;
+    FILE* m_additionalStream;
 };
 
 #endif // RPLWRITER_HPP
diff --git a/rpldoc.zip b/rpldoc.zip
new file mode 100644 (file)
index 0000000..020aa68
Binary files /dev/null and b/rpldoc.zip differ
index 46b3d075d71fc115f0501b61aaf12d1e84784032..1ecd6a00a6841079e55f8fd8677e45294f06c906 100644 (file)
@@ -288,7 +288,7 @@ RplSymbolSpace* RplSymbolSpace::parent() const
 }
 
 /**
- * @brief Returns the body (a abstract syntax tree) of the symbol space.
+ * @brief Returns the body (an abstract syntax tree) of the symbol space.
  *
  * @return  NULL: no body available<br>
  *          othewise: the body of the instance
@@ -299,7 +299,7 @@ RplASItem* RplSymbolSpace::body() const
 }
 
 /**
- * @brief Sets the body (a abstract syntax tree) of the symbol space.
+ * @brief Sets the body (an abstract syntax tree) of the symbol space.
  *
  * @param body  the new body
  */
@@ -456,7 +456,7 @@ QString RplASBoolean::toString(void* object, int) const
  *
  * @brief Implements the class of a Boolean.
  *
- * A Boolean is one of the values true and false.
+ * A Boolean is one of the values true and false.
  */
 /**
  * @brief Constructor.
@@ -877,7 +877,7 @@ RplVariable::RplVariable(const QString& name) :
 }
 
 /**
- * @brief Writes the content of the instance into a output media.
+ * @brief Writes the content of the instance into an output media.
  *
  * @param writer    writes to output
  * @param indent    nesting level: so many tabs will be used as prefix
@@ -1014,7 +1014,7 @@ QString RplASFormula::toString(void* object, int) const
 
 /** @class RplASUserClass rplastree.hpp "rplexpr/rplastree.hpp"
  *
- * @brief Implements a data type representing a user defined class.
+ * @brief Implements a data type representing an user defined class.
  */
 
 
@@ -1034,7 +1034,7 @@ RplASUserClass::RplASUserClass(const QString& name,
 }
 
 /**
- * @brief Creates an instance of a user defined class.
+ * @brief Creates an instance of an user defined class.
  *
  * @param source    the type (user defined class) of the result
  * @return          an instance of an user defined class
index d4b9d2a437c8c27797af73b077483bf6ab03b037..9838f7d7d65959e513dc616c395b337fc45b8bc5 100644 (file)
 #include "rplcore/rplcore.hpp"
 #include "rplexpr/rplexpr.hpp"
 
+enum {
+    LOC_VARDEF_EXEC_1 = RPL_FIRST_OF(RPL_MODULE_ASTREE), // 10001
+    LOC_UNOP_1,
+    LOC_UNOP_2,
+    LOC_UNOP_3,
+    LOC_UNOP_4, // 10005
+    LOC_BINOP_1,
+    LOC_COUNT
+};
+
 unsigned int RplASItem::m_nextId = 1;
 
 #define DEFINE_TABS(indent)  \
@@ -203,6 +213,7 @@ void RplASVariant::destroyValue()
         m_value.m_object = NULL;
         break;
     }
+    m_variantType = VT_UNDEF;
 }
 /**
  * @brief Returns the variantType of the instance.
@@ -214,6 +225,33 @@ RplASVariant::VariantType RplASVariant::variantType() const
     return m_variantType;
 }
 
+/**
+ * @brief Return the name of the variant type.
+ *
+ * @return  the type as string
+ */
+const char*RplASVariant::nameOfType() const
+{
+    const char* rc = "?";
+    switch(m_variantType){
+    case VT_FLOAT:
+        rc = "Float";
+        break;
+    case VT_INTEGER:
+        rc = "Int";
+        break;
+    case VT_BOOL:
+        rc = "Bool";
+        break;
+    case VT_OBJECT:
+        rc = "Obj";
+        break;
+    default:
+        break;
+    }
+    return rc;
+}
+
 /**
  * @brief Returns the class (data type) of the instance.
  *
@@ -472,6 +510,28 @@ char* RplASItem::positionStr(char buffer[], size_t bufferSize) const
     return rc;
 }
 
+/**
+ * @brief Logs an internal error.
+ *
+ * @param logger    can write to the output medium
+ * @param location  identifies the error location
+ * @param format    string with placeholders (optional) like <code>sprintf()</code>
+ * @param ...       values for the placeholders
+ */
+void RplASItem::error(RplLogger* logger, int location, const char* format, ...)
+{
+    char buffer[1024];
+    int halfBufferSize = (sizeof buffer) / 2;
+    snprintf(buffer, halfBufferSize, "id: %d [%s]:", m_id,
+                 positionStr(buffer + halfBufferSize, halfBufferSize));
+    int length = strlen(buffer);
+    va_list ap;
+    va_start(ap, format);
+    vsnprintf(buffer + length, (sizeof buffer) - length, format, ap);
+    va_end(ap);
+    logger->log(LOG_ERROR, location, buffer);
+}
+
 /**
  * @brief Resets the static id counter.
  */
@@ -488,6 +548,99 @@ RplASItemType RplASItem::nodeType() const
 {
     return m_nodeType;
 }
+
+/**
+ * @brief Returns the node type as a string.
+ *
+ * @return  the node type as string
+ */
+const char*RplASItem::nameOfItemType() const
+{
+    const char* rc = "?";
+    switch(m_nodeType){
+    case AST_CONSTANT:
+        rc = "constant";
+        break;
+    case AST_LIST_CONSTANT:
+        rc = "list";
+        break;
+    case AST_LIST_ENTRY:
+        rc = "listEntry";
+        break;
+    case AST_MAP_CONSTANT:
+        rc = "map";
+        break;
+    case AST_MAP_ENTRY:
+        rc = "mapEntry";
+        break;
+    case AST_NAMED_VALUE:
+        rc = "namedValue";
+        break;
+    case AST_INDEXED_VALUE:
+        rc = "indexedValue";
+        break;
+    case AST_FIELD:
+        rc = "field";
+        break;
+    case AST_VAR_DEFINITION:
+        rc = "varDef";
+        break;
+    case AST_EXPR_STATEMENT:
+        rc = "exprStatement";
+        break;
+    case AST_METHOD:
+        rc = "method";
+        break;
+    case AST_ARGUMENT:
+        rc = "arg";
+        break;
+    case AST_INTRINSIC_METHOD:
+        rc = "intrinsicMethod";
+        break;
+    case AST_PRE_UNARY_OP:
+        rc = "preUnary";
+        break;
+    case AST_POST_UNARY_OP:
+        rc = "postUnary";
+        break;
+    case AST_BINARY_OP:
+        rc = "binOp";
+        break;
+    case AST_METHOD_CALL:
+        rc = "methodCall";
+        break;
+    case AST_WHILE:
+        rc = "while";
+        break;
+    case AST_REPEAT:
+        rc = "repeat";
+        break;
+    case AST_IF:
+        rc = "if";
+        break;
+    case AST_CONDITION:
+        rc = "condition";
+        break;
+    case AST_ITERATED_FOR:
+        rc = "iFor";
+        break;
+    case AST_COUNTED_FOR:
+        rc = "cFor";
+        break;
+    case AST_SWITCH:
+        rc = "switch";
+        break;
+    case AST_LEAVE:
+        rc = "leave";
+        break;
+    case AST_CONTINUE:
+        rc = "continue";
+        break;
+    default:
+        break;
+    }
+    return rc;
+}
 /**
  * @brief Returns the flags of the node.
  *
@@ -537,15 +690,14 @@ RplASConstant::RplASConstant() :
 }
 
 /**
- * @brief Calculates the expression.
+ * @brief Copies the const value to the top of value stack.
  *
- * @param value     IN/OUT: the calculated value
- * @return          NULL
+ * @param thread    IN/OUT: the execution unit, a VM thread
  */
-RplASNode1* RplASConstant::calc(RplASVariant& value)
+void RplASConstant::calc(RplVMThread& thread)
 {
-    value = m_value;
-    return NULL;
+    RplASVariant& value = thread.reserveValue();
+    value.copyValue(m_value);
 }
 
 /**
@@ -605,15 +757,14 @@ RplASListOfVariants* RplASListConstant::list(){
 }
 
 /**
- * @brief Calculates the expression.
+ * @brief Copies the list constant to the top of value stack.
  *
- * @param value     IN/OUT: the calculated value
- * @return          NULL
+ * @param thread    IN/OUT: the execution unit, a VM thread
  */
-RplASNode1* RplASListConstant::calc(RplASVariant& value)
+void RplASListConstant::calc(RplVMThread& thread)
 {
-    value = m_value;
-    return NULL;
+    RplASVariant& value = thread.reserveValue();
+    value.copyValue(m_value);
 }
 
 /**
@@ -664,16 +815,14 @@ RplASMapConstant::RplASMapConstant() :
 }
 
 /**
- * @brief Calculates the value.
+ * @brief Copies the map constant to the top of value stack.
  *
- * @param value     IN/OUT: the value of the instance
- * @return          NULL
+ * @param thread    IN/OUT: the execution unit, a VM thread
  */
-RplASNode1* RplASMapConstant::calc(RplASVariant& )
+void RplASMapConstant::calc(RplVMThread& thread)
 {
-    // ToDo: copy map:
-    //value = m_value;
-    return NULL;
+    RplASVariant& value = thread.reserveValue();
+    value.copyValue(m_value);
 }
 /**
  * @brief Writes the internals into a file.
@@ -729,7 +878,9 @@ RplASNamedValue::RplASNamedValue(const QString& name) :
     RplASNode1(AST_NAMED_VALUE),
     m_name(name),
     m_attributes(0),
-    m_dataType(NULL)
+    m_dataType(NULL),
+    m_symbolSpace(NULL),
+    m_variableNo(0)
 {
 }
 
@@ -745,7 +896,9 @@ RplASNamedValue::RplASNamedValue(RplASClass* dataType,
     RplASNode1(AST_NAMED_VALUE),
     m_name(name),
     m_attributes(attributes),
-    m_dataType(dataType)
+    m_dataType(dataType),
+    m_symbolSpace(NULL),
+    m_variableNo(0)
 {
 }
 
@@ -758,16 +911,25 @@ const QString& RplASNamedValue::name() const
 {
     return m_name;
 }
+
+/**
+ * @brief Sets the symbol space.
+ * @param space
+ * @param variableNo
+ */
+void RplASNamedValue::setSymbolSpace(RplSymbolSpace* space, int variableNo)
+{
+    m_symbolSpace = space;
+    m_variableNo = variableNo;
+}
 /**
- * @brief Calculates the value.
+ * @brief Copies the value of the variable to the top of value stack.
  *
- * @param value     In/OUT: the value of the instance
- * @param frame     not used
- * @return          NULL
+ * @param thread    IN/OUT: the execution unit, a VM thread
  */
-RplASNode1* RplASNamedValue::calc(RplASVariant& , RplStackFrame* )
+void RplASNamedValue::calc(RplVMThread& thread)
 {
-    return NULL;
+    thread.valueToTop(m_symbolSpace, m_variableNo);
 }
 /**
  * @brief Writes the internals into a file.
@@ -792,6 +954,36 @@ RplASClass* RplASNamedValue::dataType() const
     return m_dataType;
 }
 
+/**
+ * @brief Assigns the top of stack of the thread to the instance.
+ *
+ * @param thread    the execution unit, a virtual machine thread
+ */
+void RplASNamedValue::assign(RplVMThread& thread)
+{
+
+}
+
+/**
+ * @brief Returns the symbol space of the variable.
+ *
+ * @return  the symbol space
+ */
+RplSymbolSpace*RplASNamedValue::symbolSpace() const
+{
+    return m_symbolSpace;
+}
+
+/**
+ * @brief Returns the variable no of the variable.
+ *
+ * @return  the current number of the variable in the symbol space
+ */
+int RplASNamedValue::variableNo() const
+{
+    return m_variableNo;
+}
+
 /** @class RplASIndexedValue rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements an indexed values (member of a list)
@@ -836,6 +1028,7 @@ RplASVarDefinition::RplASVarDefinition() :
     RplASNode3(AST_VAR_DEFINITION),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
 }
 
 /**
@@ -888,20 +1081,26 @@ RplASClass* RplASVarDefinition::datatype() const
 /**
  * @brief Executes the statement.
  */
-void RplASVarDefinition::execute()
+void RplASVarDefinition::execute(RplVMThread& thread)
 {
-    //@ToDo
-}
-
-/**
- * @brief Calculates the initialation value while interpreting.
- *
- * @param value     IN/OUT: ignored
- * @return          NULL
- */
-RplASNode1* RplASVarDefinition::calc(RplASVariant&)
-{
-    return NULL;
+    if (m_child3 != NULL){
+        RplASNamedValue* var = dynamic_cast<RplASNamedValue*>(m_child2);
+        if (var == NULL)
+            error(thread.logger(), LOC_VARDEF_EXEC_1,
+                  "Not a named value: id: %d",
+                  m_child2 == NULL ? 0 : m_child2->id());
+        else{
+            RplASCalculable* expr = dynamic_cast<RplASCalculable*>(m_child3);
+            if (expr == NULL)
+                error(thread.logger(), LOC_VARDEF_EXEC_1,
+                                "not calculable: id: %d",
+                                m_child3 == NULL ? 0 : m_child2->id());
+            else {
+                expr->calc(thread);
+                var->assign(thread);
+            }
+        }
+    }
 }
 
 /** @class RplASExprStatement rplastree.hpp "rplexpr/rplastree.hpp"
@@ -919,27 +1118,17 @@ RplASExprStatement::RplASExprStatement() :
     RplASNode2(AST_EXPR_STATEMENT),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
 }
 
 /**
  * @brief Executes the statement.
  */
-void RplASExprStatement::execute()
+void RplASExprStatement::execute(RplVMThread& thread)
 {
 
 }
 
-/**
- * @brief Calculates the value of the expression.
- *
- * @param value     IN/OUT: the calculated value
- * @return          NULL
- */
-RplASNode1* RplASExprStatement::calc(RplASVariant& )
-{
-    return NULL;
-}
-
 /**
  * @brief Writes the internals into a file.
  *
@@ -1019,6 +1208,7 @@ void RplASNode1::dumpStatements(RplWriter& writer, int indent,
     }
 }
 
+
 /** @class RplASNode2 rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements an inner node of the abstract syntax tree with two childs.
@@ -1242,9 +1432,9 @@ void RplASNode6::setChild6(RplASItem* child6)
 
 /** @class RplASUnaryOp rplastree.hpp "rplexpr/rplastree.hpp"
  *
- * @brief Implements a unary operation.
+ * @brief Implements an unary operation.
  *
- * This is a operation with one operand, e.g. the boolean not operation.
+ * This is an operation with one operand, e.g. the boolean not operation.
  */
 
 /**
@@ -1259,6 +1449,71 @@ RplASUnaryOp::RplASUnaryOp(int op, RplASItemType type) :
 {
 }
 
+/**
+ * @brief Calculates the value of the unary operator.
+ *
+ * @param thread    IN/OUT: the execution unit, a VM thread
+ */
+void RplASUnaryOp::calc(RplVMThread& thread)
+{
+    RplASVariant& value = thread.topOfValues();
+    switch(m_operator){
+    case UOP_PLUS:
+        break;
+    case UOP_MINUS:
+        switch (value.variantType()){
+        case RplASVariant::VT_FLOAT:
+            value.setFloat(- value.asFloat());
+            break;
+        case RplASVariant::VT_INTEGER:
+            value.setInt(- value.asInt());
+            break;
+        case RplASVariant::VT_BOOL:
+        case RplASVariant::VT_OBJECT:
+        default:
+            error(thread.logger(), LOC_UNOP_1, "wrong type %s for '-'",
+                  value.nameOfType());
+            break;
+        }
+        break;
+    case UOP_LOGICAL_NOT:
+        switch (value.variantType()){
+        case RplASVariant::VT_FLOAT:
+            value.setBool(value.asFloat() != 0.0);
+            break;
+        case RplASVariant::VT_INTEGER:
+            value.setBool(value.asInt() != 0);
+            break;
+        case RplASVariant::VT_BOOL:
+            value.setBool(! value.asBool());
+            break;
+        case RplASVariant::VT_OBJECT:
+        default:
+            error(thread.logger(), LOC_UNOP_2, "wrong type %s for '!'",
+                  value.nameOfType());
+            break;
+        }
+        break;
+    case UOP_BIT_NOT:
+        switch (value.variantType()){
+        case RplASVariant::VT_INTEGER:
+            value.setInt(~value.asInt());
+            break;
+        case RplASVariant::VT_FLOAT:
+        case RplASVariant::VT_BOOL:
+        case RplASVariant::VT_OBJECT:
+        default:
+            error(thread.logger(), LOC_UNOP_3, "wrong type %s for '~'",
+                  value.nameOfType());
+            break;
+        }
+        break;
+    default:
+        error(thread.logger(), LOC_UNOP_4, "unknown operator: %d", m_operator);
+        break;
+    }
+}
+
 /**
  * @brief Returns the operator of the unary operation.
  *
@@ -1323,26 +1578,24 @@ RplASCondition::RplASCondition() :
 
 /**
  * @brief Calculates the value of the condition
- * @param value     IN/OUT: the bool value of the condition
- * @return          NULL
+ *
+ * @param thread    IN/OUT: the bool value of the condition
  */
-RplASNode1* RplASCondition::calc(RplASVariant& value)
+void RplASCondition::calc(RplVMThread& thread)
 {
-    value.setBool(false);
     RplASCalculable* node = dynamic_cast<RplASCalculable*>(m_child);
     if (node == NULL)
         throw RplASException(m_position, "child of condition is not calculable");
-    node->calc(value);
-    return NULL;
+    node->calc(thread);
 }
 /**
  * @brief Calculates the boolean value and returns it.
  */
-bool RplASCondition::calcAsBool()
+bool RplASCondition::calcAsBool(RplVMThread& thread)
 {
     bool rc = false;
-    RplASVariant value;
-    calc(value);
+    calc(thread);
+    RplASVariant& value = thread.topOfValues();
     switch(value.m_variantType){
     case RplASVariant::VT_FLOAT:
         rc = value.m_value.m_float == 0;
@@ -1393,20 +1646,21 @@ void RplASCondition::dump(RplWriter& writer, int indent)
 RplASIf::RplASIf() :
     RplASNode4(AST_IF)
 {
+    m_flags |= NF_STATEMENT;
 }
 
 /**
  * @brief Executes the statement.
  *
  */
-void RplASIf::execute()
+void RplASIf::execute(RplVMThread& thread)
 {
     RplASCondition* condition = dynamic_cast<RplASCondition*>(m_child2);
     if (condition == NULL)
         throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
                              "if statement: not a condition");
     RplASStatement* body = NULL;
-    if(condition->calcAsBool()){
+    if(condition->calcAsBool(thread)){
         body = dynamic_cast<RplASStatement*>(m_child3);
         if (body == NULL)
             throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
@@ -1417,7 +1671,7 @@ void RplASIf::execute()
             throw RplASException(m_child4->position(),
                                  "if statement: else-part is not a statement");
     }
-    body->execute();
+    body->execute(thread);
 }
 
 /**
@@ -1469,6 +1723,7 @@ RplASForIterated::RplASForIterated(RplASNamedValue* variable) :
     RplASNode4(AST_ITERATED_FOR),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
     m_child2 = variable;
 }
 
@@ -1476,7 +1731,7 @@ RplASForIterated::RplASForIterated(RplASNamedValue* variable) :
  * @brief Executes the statement.
  *
  */
-void RplASForIterated::execute()
+void RplASForIterated::execute(RplVMThread& thread)
 {
 }
 
@@ -1531,6 +1786,7 @@ RplASForCounted::RplASForCounted(RplASNamedValue* variable) :
     RplASNode6(AST_ITERATED_FOR),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
     m_child3 = variable;
 }
 
@@ -1538,7 +1794,7 @@ RplASForCounted::RplASForCounted(RplASNamedValue* variable) :
  * @brief Executes the statement.
  *
  */
-void RplASForCounted::execute()
+void RplASForCounted::execute(RplVMThread& thread)
 {
     RplASStatement* body = dynamic_cast<RplASStatement*>(m_child2);
     if (body == NULL)
@@ -1552,7 +1808,7 @@ void RplASForCounted::execute()
         var = dynamic_cast<RplASNamedValue*>(m_child3);
     }
     for(int ii = start; ii <= end; ii += step){
-        body->execute();
+        body->execute(thread);
     }
 }
 
@@ -1601,6 +1857,7 @@ RplASWhile::RplASWhile() :
     RplASNode3(AST_WHILE),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
 }
 
 /**
@@ -1608,7 +1865,7 @@ RplASWhile::RplASWhile() :
  *
  * Meaning of the childs:
  */
-void RplASWhile::execute()
+void RplASWhile::execute(RplVMThread& thread)
 {
     RplASStatement* body = dynamic_cast<RplASStatement*>(m_child3);
     if (body == NULL)
@@ -1618,8 +1875,8 @@ void RplASWhile::execute()
     if (condition == NULL)
         throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
                              "for statement: not a condition");
-    while(condition->calcAsBool()){
-        body->execute();
+    while(condition->calcAsBool(thread)){
+        body->execute(thread);
     }
 }
 
@@ -1660,6 +1917,7 @@ RplASRepeat::RplASRepeat() :
     RplASNode3(AST_REPEAT),
     RplASStatement()
 {
+    m_flags |= NF_STATEMENT;
 }
 
 /**
@@ -1669,7 +1927,7 @@ RplASRepeat::RplASRepeat() :
  * m_child: body
  * m_child2: condition
  */
-void RplASRepeat::execute()
+void RplASRepeat::execute(RplVMThread& thread)
 {
     RplASStatement* body = dynamic_cast<RplASStatement*>(m_child3);
     if (body == NULL)
@@ -1680,8 +1938,8 @@ void RplASRepeat::execute()
         throw RplASException(m_child2 == NULL ? m_position : m_child2->position(),
                              "repeat statement: not a condition");
     do {
-        body->execute();
-    } while(condition->calcAsBool());
+        body->execute(thread);
+    } while(condition->calcAsBool(thread));
 }
 
 /**
@@ -1706,7 +1964,7 @@ void RplASRepeat::dump(RplWriter& writer, int indent)
 
 /** @class RplASClass rplastree.hpp "rplexpr/rplastree.hpp"
  *
- * @brief Implements the base class of a Abstract Syntax Tree class.
+ * @brief Implements the base class of an Abstract Syntax Tree class.
  *
  * This class is abstract.
  */
@@ -1999,6 +2257,7 @@ RplASMethodCall::RplASMethodCall(const QString& name, RplASItem* parent) :
     m_name(name),
     m_method(NULL)
 {
+    m_flags |= NF_STATEMENT;
     m_child3 = parent;
 }
 
@@ -2027,7 +2286,7 @@ void RplASMethodCall::dump(RplWriter& writer, int indent)
 /**
  * @brief Executes the statement.
  */
-void RplASMethodCall::execute()
+void RplASMethodCall::execute(RplVMThread& thread)
 {
 }
 
@@ -2072,16 +2331,46 @@ RplASArgument* RplASMethodCall::arg1() const
  */
 RplASBinaryOp::RplASBinaryOp() :
     RplASNode2(AST_BINARY_OP),
-    m_operator(0)
+    m_operator(BOP_UNDEF)
 {
 }
 
+/**
+ * @brief Calculates the binary operation.
+ *
+ * @param thread    IN/OUT: the bool value of the condition
+ */
+void RplASBinaryOp::calc(RplVMThread& thread)
+{
+    if (isAssignment())
+        assign(thread);
+    else{
+        switch(m_operator){
+        case BOP_PLUS:
+        case BOP_MINUS:
+        case BOP_TIMES:
+        case BOP_DIV:
+        case BOP_MOD:
+        case BOP_POWER:
+        case BOP_LOG_OR:
+        case BOP_LOG_AND:
+        case BOP_LOG_XOR:
+        case BOP_BIT_OR:
+        case BOP_BIT_AND:
+        case BOP_BIT_XOR:
+            break;
+        default:
+            break;
+        }
+    }
+}
+
 /**
  * @brief Returns the operator.
  *
  * @return the operator
  */
-int RplASBinaryOp::getOperator() const
+RplASBinaryOp::BinOperator RplASBinaryOp::getOperator() const
 {
     return m_operator;
 }
@@ -2091,7 +2380,7 @@ int RplASBinaryOp::getOperator() const
  *
  * @param op    the operator
  */
-void RplASBinaryOp::setOperator(int op)
+void RplASBinaryOp::setOperator(BinOperator op)
 {
     m_operator = op;
 }
@@ -2118,6 +2407,47 @@ void RplASBinaryOp::dump(RplWriter& writer, int indent)
         m_child2->dump(writer, indent + 1);
 }
 
+/**
+ * @brief Does an assignment.
+ *
+ * @param thread
+ */
+void RplASBinaryOp::assign(RplVMThread& thread)
+{
+    RplASVariant& rValue = thread.lValue(m_child);
+    RplASCalculable* expr = dynamic_cast<RplASCalculable*>(m_child2);
+    if (expr == NULL)
+        error(thread.logger(), LOC_BINOP_1, "not a calulable: id: %d",
+              m_child2 == NULL ? 0 : m_child2->id());
+    else {
+        RplASVariant& value = thread.popValue();
+        switch(m_operator){
+        case BOP_ASSIGN:
+            break;
+        case BOP_PLUS_ASSIGN:
+            switch(value.variantType()){
+
+            }
+            break;
+        case BOP_MINUS_ASSIGN:
+        case BOP_TIMES_ASSIGN:
+        case BOP_DIV_ASSIGN:
+        case BOP_MOD_ASSIGN:
+        case BOP_POWER_ASSIGN:
+        case BOP_LOG_OR_ASSIGN:
+        case BOP_LOG_AND_ASSIGN:
+        case BOP_LOG_XOR_ASSIGN:
+        case BOP_BIT_OR_ASSIGN:
+        case BOP_BIT_AND_ASSIGN:
+        case BOP_BIT_XOR_ASSIGN:
+            break;
+        default:
+            break;
+        }
+        rValue.copyValue(value);
+    }
+}
+
 /** @class RplASMethod rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a method definition for the Abstract Syntax Tree.
index 742d6be88f86fc832d1d00c498deb8d217d703aa..06e8e8b5287fd7ec364080f0b7a357f11947f813 100644 (file)
@@ -92,8 +92,8 @@ public:
     void setString(const QString& string);
     QString toString(int maxLength = 80) const;
     VariantType variantType() const;
+    const char* nameOfType() const;
     const RplASClass* getClass() const;
-protected:
     void copyValue(const RplASVariant& source);
     void destroyValue();
 private:
@@ -117,8 +117,10 @@ public:
         NF_UNDEF,
         /// the node calculates a value:
         NF_CALCULABLE   = 1 << 1,
+        /// the node calculates a value:
+        NF_STATEMENT    = 1 << 2,
         /// the tree under this node is complete checked for data type correctness
-        NF_TYPECHECK_COMPLETE   = 1 << 2,
+        NF_TYPECHECK_COMPLETE   = 1 << 3,
         /// debugger: this node is a breakpoint
         NF_BREAKPOINT           = 1 << 5
     };
@@ -132,6 +134,7 @@ public:
     void setPosition(const RplSourcePosition* position);
     unsigned int id() const;
     char* positionStr(char buffer[], size_t bufferSize) const;
+    void error(RplLogger* logger, int location, const char* format, ...);
 public:
     /**
      * @brief Writes the content of the instance into an output medium.
@@ -143,6 +146,7 @@ public:
 public:
     static void reset();
     RplASItemType nodeType() const;
+    const char* nameOfItemType() const;
 
     int flags() const;
     void setFlags(int flags);
@@ -158,24 +162,23 @@ private:
 };
 
 class RplASNode1;
+class RplVMThread;
 class RplASCalculable
 {
 public:
-    virtual RplASNode1* calc(RplASVariant& value) = 0;
+    virtual void calc(RplVMThread& thread) = 0;
 };
 
 class RplStackFrame;
-class RplASStorable{
-public:
-    virtual RplASNode1* calc(RplASVariant& value, RplStackFrame* frame) = 0;
+class RplASStorable : RplASCalculable {
 };
-
+class RplVMThread;
 class RplASConstant : public RplASItem, public RplASCalculable
 {
 public:
     RplASConstant();
 public:
-    virtual RplASNode1* calc(RplASVariant& value);
+    virtual void calc(RplVMThread& thread);
 public:
     virtual void dump(RplWriter& writer,int indent);
     RplASVariant& value();
@@ -268,7 +271,7 @@ class RplASListConstant : public RplASNode1, public RplASCalculable
 public:
     RplASListConstant();
 public:
-    virtual RplASNode1* calc(RplASVariant& value);
+    virtual void calc(RplVMThread& thread);
 public:
     virtual void dump(RplWriter& writer,int indent);
     RplASVariant& value();
@@ -281,7 +284,7 @@ class RplASMapConstant : public RplASNode1, public RplASCalculable
 public:
     RplASMapConstant();
 public:
-    virtual RplASNode1* calc(RplASVariant& value);
+    virtual void calc(RplVMThread& thread);
 public:
     virtual void dump(RplWriter& writer,int indent);
     RplASVariant& value();
@@ -290,6 +293,7 @@ private:
     RplASVariant m_value;
 };
 
+class RplSymbolSpace;
 class RplASNamedValue : public RplASNode1, public RplASStorable
 {
 public:
@@ -313,15 +317,19 @@ public:
                     const QString& name, int attributes);
 public:
     const QString& name() const;
-public:
-    virtual RplASNode1* calc(RplASVariant& value, RplStackFrame* frame);
+    void setSymbolSpace(RplSymbolSpace* space, int variableNo);
+    virtual void calc(RplVMThread& thread);
     void dump(RplWriter& writer, int indent);
     RplASClass* dataType() const;
-
+    void assign(RplVMThread& thread);
+    RplSymbolSpace* symbolSpace() const;
+    int variableNo() const;
 protected:
     QString m_name;
     int m_attributes;
     RplASClass* m_dataType;
+    RplSymbolSpace* m_symbolSpace;
+    int m_variableNo;
 };
 
 class RplASIndexedValue : public RplASNode2 {
@@ -336,7 +344,7 @@ class RplASStatement
 public:
     RplASStatement();
 public:
-    virtual void execute() = 0;
+    virtual void execute(RplVMThread& thread) = 0;
 };
 
 
@@ -345,8 +353,7 @@ class RplASVarDefinition : public RplASNode3, public RplASStatement
 public:
     RplASVarDefinition();
 public:
-    virtual void execute();
-    virtual RplASNode1* calc(RplASVariant& value);
+    virtual void execute(RplVMThread& thread);
     void dump(RplWriter& writer, int indent);
     const QString& name() const;
     RplASClass* datatype() const;
@@ -357,32 +364,90 @@ class RplASExprStatement : public RplASNode2, public RplASStatement
 public:
     RplASExprStatement();
 public:
-    virtual void execute();
-    virtual RplASNode1* calc(RplASVariant& value);
+    virtual void execute(RplVMThread& thread);
     void dump(RplWriter& writer, int indent);
 };
 
-class RplASUnaryOp : public RplASNode1
+class RplASUnaryOp : public RplASNode1, RplASCalculable
 {
+public:
+    enum {
+        UOP_UNDEF,
+        UOP_PLUS,
+        UOP_MINUS,
+        UOP_LOGICAL_NOT,
+        UOP_BIT_NOT
+    };
 public:
     RplASUnaryOp(int op, RplASItemType type);
 public:
+    virtual void calc(RplVMThread& thread);
     int getOperator() const;
     void dump(RplWriter& writer, int indent);
 
 private:
     int m_operator;
 };
-class RplASBinaryOp : public RplASNode2
+class RplASBinaryOp : public RplASNode2, public RplASCalculable
 {
+public:
+    enum BinOperator {
+        BOP_UNDEF,
+        BOP_ASSIGN,
+        BOP_PLUS_ASSIGN,
+        BOP_MINUS_ASSIGN,
+        BOP_TIMES_ASSIGN,
+        BOP_DIV_ASSIGN,
+        BOP_MOD_ASSIGN,
+        BOP_POWER_ASSIGN,
+        BOP_LOG_OR_ASSIGN,
+        BOP_LOG_AND_ASSIGN,
+        BOP_LOG_XOR_ASSIGN,
+        BOP_BIT_OR_ASSIGN,
+        BOP_BIT_AND_ASSIGN,
+        BOP_BIT_XOR_ASSIGN,
+        BOP_LSHIFT_ASSIGN,
+        BOP_LOG_RSHIFT_ASSIGN,
+        BOP_ARTITH_RSHIFT_ASSIGN,
+        BOP_PLUS,
+        BOP_MINUS,
+        BOP_TIMES,
+        BOP_DIV,
+        BOP_MOD,
+        BOP_POWER,
+        BOP_LOG_OR,
+        BOP_LOG_AND,
+        BOP_LOG_XOR,
+        BOP_BIT_OR,
+        BOP_BIT_AND,
+        BOP_BIT_XOR,
+        BOP_LSHIFT,
+        BOP_LOG_RSHIFT,
+        BOP_ARTITH_RSHIFT,
+        BOP_EQ,
+        BOP_NE,
+        BOP_LE,
+        BOP_LT,
+        BOP_GE,
+        BOP_GT,
+        BOB_COUNT
+    };
+private:
+    inline bool isAssignment() const {
+        return m_operator >= BOP_ASSIGN
+                && m_operator <= BOP_ARTITH_RSHIFT_ASSIGN;
+    }
 public:
     RplASBinaryOp();
 public:
-    int getOperator() const;
-    void setOperator(int op);
+    void calc(RplVMThread& thread);
+    BinOperator getOperator() const;
+    void setOperator(BinOperator op);
     void dump(RplWriter& writer, int indent);
 private:
-    int m_operator;
+    void assign(RplVMThread& thread);
+private:
+    BinOperator m_operator;
 };
 
 class RplASCondition : public RplASNode1, public RplASCalculable
@@ -390,8 +455,8 @@ class RplASCondition : public RplASNode1, public RplASCalculable
 public:
     RplASCondition();
 public:
-    RplASNode1* calc(RplASVariant& value);
-    bool calcAsBool();
+    void calc(RplVMThread& thread);
+    bool calcAsBool(RplVMThread& thread);
     void dump(RplWriter& writer, int indent);
 };
 
@@ -400,7 +465,7 @@ class RplASIf : public RplASNode4, public RplASStatement
 public:
     RplASIf();
 public:
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
     virtual void dump(RplWriter& writer, int indent);
 };
 
@@ -409,7 +474,7 @@ class RplASForIterated : public RplASNode4, public RplASStatement
 public:
     RplASForIterated(RplASNamedValue* variable);
 public:
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
     virtual void dump(RplWriter& writer, int indent);
 };
 
@@ -418,7 +483,7 @@ class RplASForCounted : public RplASNode6, public RplASStatement
 public:
     RplASForCounted(RplASNamedValue* variable);
 public:
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
     virtual void dump(RplWriter& writer, int indent);
 };
 
@@ -427,7 +492,7 @@ class RplASWhile : public RplASNode3, public RplASStatement
 public:
     RplASWhile();
 public:
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
     virtual void dump(RplWriter& writer, int indent);
 };
 
@@ -436,7 +501,7 @@ class RplASRepeat : public RplASNode3, public RplASStatement
 public:
     RplASRepeat();
 public:
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
     virtual void dump(RplWriter& writer, int indent);
 };
 
@@ -457,7 +522,7 @@ public:
     RplASMethodCall(const QString& name, RplASItem* parent);
 public:
     void dump(RplWriter& writer, int indent);
-    virtual void execute();
+    virtual void execute(RplVMThread& thread);
 
 public:
     RplASMethod* method() const;
@@ -497,7 +562,7 @@ class RplASMethod : public RplASNode2
 public:
     RplASMethod(const QString& name, RplASTree& tree);
 public:
-    void execute();
+    void execute(RplVMThread& thread);
     void dump(RplWriter& writer, int indent);
     RplSymbolSpace* symbols() const;
     void setSymbols();
index 31d4a37e6a7d86a970b4099477c5d1cb57dd429e..5fadecaa6dd8c52874773af12bd88aee93cdc8c9 100644 (file)
@@ -651,6 +651,110 @@ RplASItem* RplMFParser::parseOperand(int level, RplASItem* parent)
     }
     return rc;
 }
+RplASBinaryOp::BinOperator encodeBinOp(int op){
+    RplASBinaryOp::BinOperator rc = RplASBinaryOp::BOP_UNDEF;
+    switch(op){
+    case RplMFParser::O_ASSIGN:
+        rc = RplASBinaryOp::BOP_ASSIGN;
+        break;
+    case RplMFParser::O_PLUS_ASSIGN:
+        rc = RplASBinaryOp::BOP_PLUS_ASSIGN;
+        break;
+    case RplMFParser::O_MINUS_ASSIGN:
+        rc = RplASBinaryOp::BOP_MINUS_ASSIGN;
+        break;
+    case RplMFParser::O_DIV_ASSIGN:
+        rc = RplASBinaryOp::BOP_DIV_ASSIGN;
+        break;
+    case RplMFParser::O_TIMES_ASSIGN:
+        rc = RplASBinaryOp::BOP_TIMES_ASSIGN;
+        break;
+    case RplMFParser::O_MOD_ASSIGN:
+        rc = RplASBinaryOp::BOP_MOD_ASSIGN;
+        break;
+    case RplMFParser::O_POWER_ASSIGN:
+        rc = RplASBinaryOp::BOP_POWER_ASSIGN;
+        break;
+    case RplMFParser::O_OR_ASSIGN:
+        rc = RplASBinaryOp::BOP_LOG_OR_ASSIGN;
+        break;
+    case RplMFParser::O_AND_ASSIGN:
+        rc = RplASBinaryOp::BOP_LOG_AND_ASSIGN;
+        break;
+    case RplMFParser::O_LSHIFT_ASSIGN:
+        rc = RplASBinaryOp::BOP_LSHIFT_ASSIGN;
+        break;
+    case RplMFParser::O_RSHIFT_ASSIGN:
+        rc = RplASBinaryOp::BOP_LOG_RSHIFT_ASSIGN;
+        break;
+    case RplMFParser::O_RSHIFT2_ASSIGN:
+        rc = RplASBinaryOp::BOP_ARTITH_RSHIFT_ASSIGN;
+        break;
+    case RplMFParser::O_OR:
+        rc = RplASBinaryOp::BOP_LOG_OR;
+        break;
+    case RplMFParser::O_AND:
+        rc = RplASBinaryOp::BOP_LOG_AND;
+        break;
+    case RplMFParser::O_EQ:
+        rc = RplASBinaryOp::BOP_EQ;
+        break;
+    case RplMFParser::O_NE:
+        rc = RplASBinaryOp::BOP_NE;
+        break;
+    case RplMFParser::O_LT:
+        rc = RplASBinaryOp::BOP_LT;
+        break;
+    case RplMFParser::O_GT:
+        rc = RplASBinaryOp::BOP_GT;
+        break;
+    case RplMFParser::O_LE:
+        rc = RplASBinaryOp::BOP_LE;
+        break;
+    case RplMFParser::O_GE:
+        rc = RplASBinaryOp::BOP_GE;
+        break;
+    case RplMFParser::O_PLUS:
+        rc = RplASBinaryOp::BOP_PLUS;
+        break;
+    case RplMFParser::O_MINUS:
+        rc = RplASBinaryOp::BOP_MINUS;
+        break;
+    case RplMFParser::O_DIV:
+        rc = RplASBinaryOp::BOP_DIV;
+        break;
+    case RplMFParser::O_MOD:
+        rc = RplASBinaryOp::BOP_MOD;
+        break;
+    case RplMFParser::O_TIMES:
+        rc = RplASBinaryOp::BOP_TIMES;
+        break;
+    case RplMFParser::O_POWER:
+        rc = RplASBinaryOp::BOP_POWER;
+        break;
+    case RplMFParser::O_XOR:
+        rc = RplASBinaryOp::BOP_LOG_XOR;
+        break;
+    case RplMFParser::O_BIT_OR:
+        rc = RplASBinaryOp::BOP_BIT_OR;
+        break;
+    case RplMFParser::O_BIT_AND:
+        rc = RplASBinaryOp::BOP_BIT_AND;
+        break;
+    case RplMFParser::O_LSHIFT:
+        rc = RplASBinaryOp::BOP_LSHIFT;
+        break;
+    case RplMFParser::O_RSHIFT:
+        rc = RplASBinaryOp::BOP_LOG_RSHIFT;
+        break;
+    case RplMFParser::O_RSHIFT2:
+        rc = RplASBinaryOp::BOP_ARTITH_RSHIFT;
+        break;
+    default:
+        break;
+    }
+    return rc;
+}
 
 /**
  * @brief Parses an expression.
@@ -684,7 +788,7 @@ RplASItem* RplMFParser::parseExpr(int depth){
                 if (IS_BINARY_OP(opId)){
                     RplASBinaryOp* op = new RplASBinaryOp();
                     op->setPosition(m_lexer.currentPosition());
-                    op->setOperator(opId);
+                    op->setOperator(encodeBinOp(opId));
 
                     int prio = m_lexer.prioOfOp(token->id());
                     if (prio < lastPrio
index 65153f3498f4bf43a3c43ab2ff2194d2d9dc604c..a542bead9346c9c222a1f90575b990f76ba3169c 100644 (file)
@@ -12,7 +12,7 @@
  * The abstract base class <code>RplReader</code> and its concrete derivations
  * <code>RplStringReader</code>, <code>RplFileReader</code> are used to read
  * from one medium.
- * The <code>RplSource</code> combines several readers and build a uniquely
+ * The <code>RplSource</code> combines several readers and build an uniquely
  * usable input stream.
  */
 /** @file rplexpr/rplsource.hpp
index 91c15186bc53dcd608c7e4ef708f5f028a581a4a..d3eb63b970fb69206f5488686dd68f310243883e 100644 (file)
@@ -10,6 +10,7 @@
  *
  * @brief Implements an interpreter of an abstract syntax tree.
  */
+
 /** @file rplexpr/rplvm.hpp
  *
  * @brief Definitions for an interpreter of an abstract syntax tree.
@@ -18,6 +19,8 @@
 #include "rplcore/rplcore.hpp"
 #include "rplexpr/rplexpr.hpp"
 
+int RplVMThread::m_nextId = 1;
+
 /** @class RplVmException rplvm.hpp "rplexpr/rplvm.hpp"
  *
  * @brief Implements an exception for the virtual machine.
@@ -102,14 +105,22 @@ RplASVariant& RplStackFrame::valueOfVariable(int index)
  * @param vm        the parent, the virtual machine
  */
 RplVMThread::RplVMThread(int maxStack, RplVirtualMachine* vm) :
+    m_id(m_nextId++),
     m_singleStep(false),
     m_debugMode(false),
     m_maxStack(maxStack),
     m_stack(),
-    m_currentValue(),
-    m_vm(vm)
+    m_valueStack(),
+    // the stack is never empty!
+    m_topOfValues(1),
+    m_vm(vm),
+    m_logger(new RplLogger())
 {
+    QByteArray prefix = "vm_thread_" + QByteArray::number(m_id);
+    m_logger->buildStandardAppender(prefix);
     m_stack.reserve(maxStack);
+    // the stack is never empty!
+    m_valueStack.append(new RplASVariant);
 }
 
 /**
@@ -122,13 +133,16 @@ RplVMThread::RplVMThread(int maxStack, RplVirtualMachine* vm) :
 void RplVMThread::execute(RplASNode1* statements, RplSymbolSpace* space)
 {
     bool debugMode = m_debugMode;
+    RplASNode1 *next;
     while(statements != NULL){
         if (debugMode
                 && (m_singleStep
                     || (statements->flags() & RplASItem::NF_BREAKPOINT) != 0))
             debug(statements);
-        RplASCalculable* statement = dynamic_cast<RplASCalculable*>(statements);
-        statement->calc(m_currentValue);
+        RplASStatement* statement = dynamic_cast<RplASStatement*>(statements);
+        if (statement != NULL)
+            statement->execute(*this);
+        statements = dynamic_cast<RplASNode1*>(statements->child());
     }
 }
 
@@ -142,11 +156,109 @@ void RplVMThread::debug(RplASNode1* statement)
 
 }
 
+/**
+ * @brief Returns the logger of the instance.
+ *
+ * @return  the logger
+ */
+RplLogger* RplVMThread::logger() const
+{
+    return m_logger;
+}
+/**
+ * @brief Reserves a value in the thread's value stack.
+ *
+ * @return  the reserved value
+ */
+RplASVariant&RplVMThread::reserveValue()
+{
+    RplASVariant* rc;
+    if (++m_topOfValues < m_valueStack.size()){
+        rc = m_valueStack[m_topOfValues];
+        rc->destroyValue();
+    } else {
+        rc = new RplASVariant();
+        m_valueStack.append(rc);
+    }
+    return *rc;
+}
+
+/**
+ * @brief Returns the top of the value stack.
+ *
+ * @return  the top of the value stack
+ */
+RplASVariant& RplVMThread::topOfValues()
+{
+    RplASVariant& rc = *m_valueStack[m_topOfValues];
+    return rc;
+}
+
+/**
+ * @brief Returns the top of stack and removes it.
+ *
+ * @return the old top of stack
+ */
+RplASVariant& RplVMThread::popValue()
+{
+    RplASVariant& rc = *m_valueStack[m_topOfValues];
+    if (m_topOfValues > 0)
+        m_topOfValues--;
+    return rc;
+}
+
+/**
+ * @brief Copies a variable value to the top of the stack.
+ *
+ * @param symbolSpace   the symbol space of the variable
+ * @param variableNo    the current no of the variable in the symbol space
+ */
+void RplVMThread::valueToTop(RplSymbolSpace* symbolSpace, int variableNo)
+{
+    //@ToDo
+}
+
+/**
+ * @brief Returns the "left value" (of an assignment).
+ * @param item
+ * @return
+ */
+RplASVariant& RplVMThread::lValue(RplASItem* item)
+{
+    RplASVariant* rc;
+    switch(item->nodeType()){
+    case AST_NAMED_VALUE:
+    {
+        RplASNamedValue* var = dynamic_cast<RplASNamedValue*>(item);
+        rc = &valueOfVariable(var->symbolSpace(), var->variableNo());
+        break;
+    }
+    default:
+        break;
+    }
+    return *rc;
+}
+
+/**
+ * @brief Returns the reference of the value of a variable.
+ *
+ * @param symbolSpace   the symbol space
+ * @param variableNo    the current number in the symbol space
+ * @return
+ */
+RplASVariant& RplVMThread::valueOfVariable(RplSymbolSpace* symbolSpace,
+                                          int variableNo)
+{
+    RplASVariant& rc = *m_valueStack[0];
+
+    return rc;
+}
+
 /** @class RplVirtualMachine rplvm.hpp "rplexpr/rplvm.hpp"
  *
  * @brief Implements a virtual machine.
  *
- * This is a execution unit which interprets an abstract syntax tree.
+ * This is an execution unit which interprets an abstract syntax tree.
  */
 RplVirtualMachine::RplVirtualMachine(RplASTree& tree, RplSource& source,
                                      int maxStack) :
@@ -243,3 +355,14 @@ void RplVirtualMachine::clearFlag(RplVirtualMachine::VMFlag flag)
 {
     m_flags &= ~flag;
 }
+
+/**
+ * @brief Sets the trace writer.
+ *
+ * @param traceWriter   the new writer
+ */
+void RplVirtualMachine::setTraceWriter(RplWriter* traceWriter)
+{
+    m_traceWriter = traceWriter;
+}
+
index 41349356118a5968c9d3a6c951ccaac14a8b9f97..c9c9d8429654303f07221bf2ce44663bebb25b01 100644 (file)
@@ -29,6 +29,10 @@ private:
 class RplVirtualMachine;
 class RplVMThread
 {
+    friend class RplASItem;
+    friend class RplASStatement;
+    friend class RplASCalculable;
+    friend class RplASCondition;
 public:
     typedef QList<RplStackFrame*> StackFrameList;
 public:
@@ -36,13 +40,27 @@ public:
 public:
     void execute(RplASNode1* statements, RplSymbolSpace* space);
     virtual void debug(RplASNode1* statement);
+    RplWriter* errorWriter() const;
+    void setErrorWriter(RplWriter* errorWriter);
+    RplLogger* logger() const;
+    RplASVariant& reserveValue();
+    RplASVariant& topOfValues();
+    RplASVariant& popValue();
+    void valueToTop(RplSymbolSpace* symbolSpace, int variableNo);
+    RplASVariant& lValue(RplASItem* item);
+    RplASVariant& valueOfVariable(RplSymbolSpace* symbolSpace, int variableNo);
 protected:
+    int m_id;
     bool m_debugMode;
     bool m_singleStep;
     int m_maxStack;
     StackFrameList m_stack;
-    RplASVariant m_currentValue;
+    QList<RplASVariant*> m_valueStack;
+    int m_topOfValues;
     RplVirtualMachine* m_vm;
+    RplLogger* m_logger;
+private:
+    static int m_nextId;
 };
 
 class RplVirtualMachine
@@ -67,6 +85,8 @@ public:
     bool hasFlag(VMFlag flag) const;
     void setFlag(VMFlag flag);
     void clearFlag(VMFlag flag);
+    void setTraceWriter(RplWriter* traceWriter);
+
 private:
     int m_maxStack;
     QList<RplVMThread*> m_threads;
@@ -74,6 +94,7 @@ private:
     RplSource& m_source;
     RplASTree& m_tree;
     LineList m_trace;
+    RplWriter* m_traceWriter;
 };
 
 #endif // RPLVM_HPP
diff --git a/rplexpr/rplvm_test.cpp b/rplexpr/rplvm_test.cpp
deleted file mode 100644 (file)
index 05acac0..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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("<test>", 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.setFlag(RplVirtualMachine::VF_TRACE_STATEMENTS);
-        vm.executeModule("<test>");
-        //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();
-}
-
index 998e0c09fe49ee25321b40ea02d834488736aae6..9bfcb7ea6ca6df138a4dee080ff335862ec55eed 100644 (file)
@@ -11,7 +11,12 @@ enum {
     RPLMODULE_TCPCLIENT,
     RPLMODULE_TCPPEER,
     RPLMODULE_TERMINATOR,
-
+    RPL_MODULE_ASTREE, // 10
+    RPL_MODULE_ASCLASSES,
+    RPL_MODULE_LEXER,
+    RPL_MODULE_SOURCE,
+    RPL_MODULE_ASVM,
+    RPL_MODULE_MFPARSER, // 15
     // last element:
     RPLMODULE_COUNT
 };
index 207c36b08b5c8cc48c6b65f608beb9b7898e10a6..743de3114466b5012dd3c33d57a266284d7a721f 100644 (file)
@@ -48,7 +48,7 @@ static int s_dummy = 0;
  * @param thread        the current thread. Used for sleep()
  * @param terminator    NULL or for controlled thread termination
  * @param logger        logger. If Null the global logger will be taken (not thread safe!)
- * @return              a instance of <code>RplTcpPeer</code>
+ * @return              an instance of <code>RplTcpPeer</code>
  */
 RplTcpPeer* RplTcpPeer::createPeer(RplConfigurator& configurator,
                                    QThread* thread,
index d6ab51972383b1698756403f4c0236cb663c3658..25cc44e0161198f420f3d271b5c27d89aed23e7e 100644 (file)
@@ -111,7 +111,7 @@ qintptr RplTcpThread::getSocketDescriptor() const {
  */
 RplTcpServer::RplTcpServer(RplConfigurator& configurator,
                            RplTaskHandler* taskHandler,
-                           RplThreadFactory& threadFactory,
+                           RplVMThreadFactory& threadFactory,
                            RplLogger* logger,
                            QObject* parent) :
     QTcpServer(parent),
index 7786ab4f37ccae1a6ac389fd59b24a039693927a..e660b3f09c42213e72fca971132bf1d7053340c4 100644 (file)
@@ -72,10 +72,10 @@ public:
     }
     void testRplASConstant(){
         RplASConstant constant;
-        constant.value().setString("Jonny");
+        //constant.value().setString("Jonny");
         RplASVariant value;
-        constant.calc(value);
-        checkE("Jonny", *value.asString());
+        //constant.calc(value);
+        //checkE("Jonny", *value.asString());
     }
     void testRplASNamedValue(){
         RplASNamedValue value("gugo");
@@ -86,9 +86,9 @@ public:
         RplASConstant* constant = new RplASConstant();
         constant->value().setString("True");
         cond.setChild(constant);
-        checkT(cond.calcAsBool());
+        //checkT(cond.calcAsBool());
         constant->value().setInt(0);
-        checkF(cond.calcAsBool());
+        //checkF(cond.calcAsBool());
     }
 
     virtual void doIt() {
index b39f30826caca5ed3ad1f7313e22d190b671a261..39e124a6544c28f1365310eb50130af9478e54ac 100644 (file)
@@ -7,6 +7,9 @@
 */
 #include "rplcore/rplcore.hpp"
 #include "rplcore/rpltest.hpp"
+/** @file
+ * @brief Unit test of the basic exceptions.
+ */
 
 class TestRplException : public RplTest{
 public:
index 74d0300143ef087fc8ad0fcee1293d76d566dd55..c2841b850670f1b85c689e5b80c394fed6a26e3b 100644 (file)
 #include "rplexpr/rplexpr.hpp"
 #include "rplcore/rpltest.hpp"
 
-class TestRplVM : public RplTest{
+class TestRplMFParser : public RplTest{
 private:
     RplSource m_source;
     RplASTree m_tree;
     RplStringReader m_reader;
     const char* m_currentSource;
 public:
-    TestRplVM() :
+    TestRplMFParser() :
         RplTest("RplMFParser"),
         m_source(),
         m_tree(),
@@ -192,7 +192,7 @@ public:
     }
 };
 void testRplMFParser() {
-    TestRplVM test;
+    TestRplMFParser test;
     test.run();
 }
 
diff --git a/unittests/rplvm_test.cpp b/unittests/rplvm_test.cpp
new file mode 100644 (file)
index 0000000..16767fa
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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("<test>", content);
+        m_source.addReader(&m_reader);
+        m_source.addSourceUnit(m_reader.currentSourceUnit());
+    }
+
+private:
+    void checkAST(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");
+        RplMFParser parser(m_source, m_tree);
+        parser.parse();
+        RplVirtualMachine vm(m_tree, m_source);
+        vm.setFlag(RplVirtualMachine::VF_TRACE_STATEMENTS);
+        RplFileWriter writer(fnCurrent);
+        vm.setTraceWriter(&writer);
+        vm.executeModule("<test>");
+        assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
+                         __FILE__, lineNo);
+    }
+public:
+    void baseTest(){
+        setSource("Int a=2+3*4");
+        checkAST("baseTest.txt", __LINE__);
+    }
+    virtual void doIt(void) {
+        baseTest();
+    }
+};
+void testRplVM() {
+    TestRplVM test;
+    test.run();
+}
+
index 18dec12f282a4904b761b246cdcb8e9a0788ebd3..285f0e13e3711a31eb3f399f5d170187a4040877 100644 (file)
@@ -17,7 +17,6 @@ INCLUDEPATH = ..
 TEMPLATE = app
 
 SOURCES += main.cpp \
-    rplmatrix_test.cpp \
     ../rplcore/rpllogger.cpp \
     ../rplcore/rpltest.cpp \
     ../rplcore/rplstring.cpp \
@@ -28,19 +27,20 @@ SOURCES += main.cpp \
     ../rplexpr/rplastree.cpp \
     ../rplexpr/rplparser.cpp \
     ../rplexpr/rplmfparser.cpp \
+    ../rplcore/rplqstring.cpp \
+    ../rplexpr/rplasclasses.cpp \
+    ../rplcore/rplbytestorage.cpp \
+    ../rplexpr/rplvm.cpp \
+    ../rplcore/rplwriter.cpp \
+    rplmatrix_test.cpp \
     rplexception_test.cpp \
     rplstring_test.cpp \
     rplsource_test.cpp \
     rpllexer_test.cpp \
     rplqstring_test.cpp \
-    ../rplcore/rplqstring.cpp \
-    ../rplexpr/rplasclasses.cpp \
     rplastree_test.cpp \
     rplmfparser_test.cpp \
-    ../rplexpr/rplvm_test.cpp \
+    rplvm_test.cpp \
     rplbytestorage_test.cpp \
-    ../rplcore/rplbytestorage.cpp \
-    ../rplexpr/rplvm.cpp \
-    rplwriter_test.cpp \
-    ../rplcore/rplwriter.cpp
+    rplwriter_test.cpp