]> gitweb.hamatoma.de Git - reqt/commitdiff
dayly work
authorhama <hama@siduction.net>
Thu, 7 Aug 2014 21:57:12 +0000 (23:57 +0200)
committerhama <hama@siduction.net>
Thu, 7 Aug 2014 21:57:12 +0000 (23:57 +0200)
35 files changed:
rplcore/rplbytestorage.cpp [new file with mode: 0644]
rplcore/rplbytestorage.hpp [new file with mode: 0644]
rplcore/rplcore.hpp
rplexpr/rplasclasses.cpp
rplexpr/rplasclasses.hpp
rplexpr/rplastree.cpp
rplexpr/rplastree.hpp
rplexpr/rpllexer.cpp
rplexpr/rplvm.cpp
rplexpr/rplvm.hpp
rplexpr/rplvm_test.cpp
rplstatic/rplstatic.pro
test/rplmfparser/baseTest.txt
test/rplmfparser/defTest.txt
test/rplmfparser/field1.txt
test/rplmfparser/forC1.txt
test/rplmfparser/forC2.txt
test/rplmfparser/forIt1.txt
test/rplmfparser/ifTest1.txt
test/rplmfparser/ifTest2.txt
test/rplmfparser/list1.txt
test/rplmfparser/list2.txt
test/rplmfparser/map1.txt
test/rplmfparser/map2.txt
test/rplmfparser/meth1.txt
test/rplmfparser/meth2.txt
test/rplmfparser/meth3.txt
test/rplmfparser/meth4.txt
test/rplmfparser/methc1.txt
test/rplmfparser/opTest1.txt
test/rplmfparser/repeatTest.txt
test/rplmfparser/whileTest.txt
unittests/main.cpp
unittests/rplbytestorage_test.cpp [new file with mode: 0644]
unittests/unittests.pro

diff --git a/rplcore/rplbytestorage.cpp b/rplcore/rplbytestorage.cpp
new file mode 100644 (file)
index 0000000..0230073
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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"
+
+/** @class RplByteStorage rplbytestorage.hpp "rplcore/rplbytestorage.hpp"
+ *
+ * @brief Implements a very efficient byte storage.
+ *
+ * Efficiency: Allocation of one block needs mostly only 1 comparison
+ * and 2 assignments.
+ *
+ * Restriction: The blocks can be returned (freed) only once, not block by block.
+ * This can be an advantage!
+ *
+ * Process:
+ * The storage administrates large buffers. Allocation can be done only in the
+ * last buffer. If the buffer has too little space for the new block a new
+ * buffer will be allocated and linked into the buffer list.
+ * One buffer can store dozens or hundreds of blocks. Therefore allocation and
+ * freeing is much cheeper than allocation by <code>new()</code>.
+ */
+
+/**
+ * @brief Constructor.
+ *
+ * @param bufferSize    the size of one buffer
+ */
+RplByteStorage::RplByteStorage(int bufferSize) :
+    m_bufferSize(bufferSize),
+    m_buffer(NULL),
+    m_rest(0),
+    m_freePosition(NULL),
+    m_summarySize(0),
+    m_buffers(0)
+{
+}
+
+/**
+ * @brief Destructor.
+ */
+RplByteStorage::~RplByteStorage()
+{
+    const uint8_t* ptr = m_buffer;
+    while(ptr != NULL){
+        const uint8_t* old = ptr;
+        ptr = *(const uint8_t**)(ptr);
+        delete[] old;
+        m_buffers--;
+    }
+    assert(m_buffers == 0);
+}
+
+/**
+ * @brief Allocates a block in a new allocated buffer.
+ *
+ * This method will be called if the buffer has too little space.
+ * A new buffer will be allocated and the block will be allocated
+ * in this new block.
+ *
+ * @note The block address is returned, but the allocation must be done outside!
+ *
+ * @param   size of the new block (inclusive the trailing '\0')
+ * @return  a new block with the <code>size</code> bytes
+ */
+char* RplByteStorage::allocBuffer(int size)
+{
+    m_rest = size + sizeof(uint8_t*) <= (size_t) m_bufferSize
+            ? m_bufferSize : size + sizeof(uint8_t*);
+    m_summarySize += m_rest;
+    m_buffers++;
+    uint8_t* rc = new uint8_t[m_rest];
+    * (uint8_t**)rc = m_buffer;
+    m_buffer = rc;
+    rc += sizeof(uint8_t*);
+    // the block allocation will be done outside!
+    m_freePosition = rc;
+    m_rest -= sizeof(uint8_t*);
+    return reinterpret_cast<char*>(rc);
+}
+
+/**
+ * @brief Duplicates a string into a new allocated block.
+ *
+ * @param source    the source string
+ * @param size      the length of the string.
+ *                  If < 0 <code>strlen(source)</code> will be used
+ * @return          a copy of the source string. The copy ends always with '\0'
+ */
+const char* RplByteStorage::allocateChars(const char* source, int size)
+{
+    if (size < 0)
+        size = strlen(source);
+    const char* rc = allocateChars(size + 1);
+    memcpy((void*) rc, source, size);
+    ((char*)rc)[size] = '\0';
+    return rc;
+}
+
+/**
+ * @brief Duplicates a string into a new allocated block.
+ *
+ * The unicode string will be converted into a UTF-8 string.
+ *
+ * @param source    the source string
+ * @return          a copy of the source string. The copy ends always with '\0'
+ */
+const char* RplByteStorage::allocUtf8(const QString& source)
+{
+    const char* rc = allocateChars(source.toUtf8().constData());
+    return rc;
+}
+
+/**
+ * @brief Allocates a byte block without initialization.
+ *
+ * @param size  the size of the block to allocate
+ *
+ * @return  a byte block (without a trailing '\0')
+ */
+uint8_t* RplByteStorage::allocateBytes(int size)
+{
+    uint8_t* rc = size <= m_rest ? m_freePosition
+            : reinterpret_cast<uint8_t*>(allocBuffer(size));
+    m_freePosition += size;
+    m_rest -= size;
+    return rc;
+}
+
+/**
+ * @brief Allocates a byte block initialized by '\0'.
+ *
+ * @param size  the size of the block to allocate
+ *
+ * @return  a byte block (without a trailing '\0')
+ */
+uint8_t* RplByteStorage::allocateZeros(int size)
+{
+    uint8_t* rc = allocateBytes(size);
+    memset(rc, 0, size);
+    return rc;
+}
+
+/**
+ * @brief Allocates a byte block.
+ *
+ * @param size  the size of the block to allocate
+ *
+ * @return  a byte block (without a trailing '\0')
+ */
+uint8_t* RplByteStorage::allocateBytes(void* source, int size)
+{
+    uint8_t* rc = allocateBytes(size);
+    memcpy(rc, source, size);
+    return rc;
+}
diff --git a/rplcore/rplbytestorage.hpp b/rplcore/rplbytestorage.hpp
new file mode 100644 (file)
index 0000000..41e0a9c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+*/
+
+
+#ifndef RPLCHARSTORAGE_HPP
+#define RPLCHARSTORAGE_HPP
+
+class RplByteStorage
+{
+public:
+    RplByteStorage(int blockSize);
+    ~RplByteStorage();
+public:
+    char* allocBuffer(int size);
+    /**
+     * @brief Allocates a char block.
+     *
+     * @return a new block
+     */
+    inline char* allocateChars(int size){
+        char* rc = size <= m_rest ? (char*) m_freePosition
+                                        : allocBuffer(size);
+        m_freePosition += size;
+        m_rest -= size;
+        return rc;
+    }
+    const char* allocateChars(const char* source, int size = -1);
+    const char* allocUtf8(const QString& source);
+    uint8_t* allocateBytes(int size);
+    uint8_t* allocateZeros(int size);
+    uint8_t*allocateBytes(void* source, int size);
+private:
+    int m_bufferSize;
+    uint8_t* m_buffer;
+    int m_rest;
+    uint8_t* m_freePosition;
+    qint64 m_summarySize;
+    int m_buffers;
+};
+
+#endif // RPLCHARSTORAGE_HPP
index 168232cbad7dfadab15709fa59d6d66cb4accced..f58b0c6ebda11de3428290d69972f39048852de5 100644 (file)
@@ -34,6 +34,7 @@ typedef unsigned char uint8_t;
 #define RPL_UNUSED(x) (void)(x)
 
 #include "rplmodules.hpp"
+#include "rplcore/rplbytestorage.hpp"
 #include "rplcore/rpllogger.hpp"
 #include "rplcore/rplexception.hpp"
 #include "rplcore/rplcontainer.hpp"
index 446087d0e2dc41dfadb8bcd10b0184845c0422d6..04201ab422c2260ef14a7b9ad9a53010dddd4645 100644 (file)
@@ -19,6 +19,9 @@ RplASBoolean* RplASBoolean::m_instance = NULL;
 RplASVoid* RplASVoid::m_instance = NULL;
 RplASFormula* RplASFormula::m_instance = NULL;
 
+///@ToDo static
+///RplSymbolSpace* RplSymbolSpace::m_global = NULL;
+
 /** @class RplSymbolSpace rplastree.hpp "rplexpr/rplastree.hpp"
  *
  * @brief Implements a symbol space for the parser.
@@ -40,37 +43,48 @@ RplASFormula* RplASFormula::m_instance = NULL;
  * Each class defines a symbol space and takes the symbol space of the superclass
  * as its parent. If there is no superclass the module's symbol space will be taken.
  *
- * Each method defines its own symbol space. The parent may be the symbol space of
- * the module or of the class.
+ * Each method defines its own symbol space. The parent may be the symbol space
+ * of the module or of the class.
  */
-
+/**
+ * @brief Constructor, only for the global symbol space.
+ *
+ * @param name      the symbol space's name
+ * @param parent    the parent of the symbol space
+ */
+RplSymbolSpace::RplSymbolSpace(RplASTree& tree) :
+    m_type(SST_GLOBAL),
+    m_name("$global"),
+    m_variables(),
+    m_classes(),
+    m_parent(NULL),
+    m_body(NULL),
+    m_listOfVars(),
+    m_tree(tree)
+{
+}
 /**
  * @brief Constructor.
  *
+ * @param type      the type of the symbol space: SST_MODULE, ...
  * @param name      the symbol space's name
  * @param parent    the parent of the symbol space
  */
 RplSymbolSpace::RplSymbolSpace(RplSymbolSpace::SymbolSpaceType type,
-        const QString &name, RplSymbolSpace *parent) :
+                               const QString& name,
+                               RplSymbolSpace* parent) :
     m_type(type),
     m_name(name),
     m_variables(),
     m_classes(),
     m_parent(parent),
-    m_body(NULL)
-{
-    if (type == SST_GLOBAL){
-        m_classes[RplASInteger::m_instance->name()] = RplASInteger::m_instance;
-        m_classes[RplASBoolean::m_instance->name()] = RplASBoolean::m_instance;
-        m_classes[RplASFloat::m_instance->name()] = RplASFloat::m_instance;
-        m_classes[RplASString::m_instance->name()] = RplASString::m_instance;
-        m_classes[RplASList::m_instance->name()] = RplASList::m_instance;
-        m_classes[RplASMap::m_instance->name()] = RplASMap::m_instance;
-        m_classes[RplASVoid::m_instance->name()] = RplASVoid::m_instance;
-        m_classes[RplASFormula::m_instance->name()] = RplASFormula::m_instance;
-    }
+    m_body(NULL),
+    m_listOfVars(),
+    m_tree(parent->m_tree)
+{
 }
 
+
 /**
  * @brief Destructor.
  */
@@ -196,7 +210,8 @@ void RplSymbolSpace::dump(FILE* fp, int indent, const char* header)
  * @param type  type to inspect
  * @return      the name of the type
  */
-const char*RplSymbolSpace::spaceTypeName(RplSymbolSpace::SymbolSpaceType type)
+const char*RplSymbolSpace::spaceTypeName(
+        RplSymbolSpace::SymbolSpaceType type)
 {
     const char* rc = NULL;
     switch(type){
@@ -221,6 +236,35 @@ const char*RplSymbolSpace::spaceTypeName(RplSymbolSpace::SymbolSpaceType type)
     }
     return rc;
 }
+
+/**
+ * @brief Initilizes the global symbol space.
+ *
+ * @param tree  the abstract syntax tree
+ * @return      the global symbol space
+ */
+RplSymbolSpace* RplSymbolSpace::createGlobal(RplASTree& tree)
+{
+    RplSymbolSpace* rc = new RplSymbolSpace(tree);
+    rc->m_tree = tree;
+    RplASInteger::m_instance = new RplASInteger(tree);
+    rc->m_classes[RplASInteger::m_instance->name()] = RplASInteger::m_instance;
+    RplASBoolean::m_instance = new RplASBoolean(tree);
+    rc->m_classes[RplASBoolean::m_instance->name()] = RplASBoolean::m_instance;
+    RplASFloat::m_instance = new RplASFloat(tree);
+    rc->m_classes[RplASFloat::m_instance->name()] = RplASFloat::m_instance;
+    RplASString::m_instance = new RplASString(tree);
+    rc->m_classes[RplASString::m_instance->name()] = RplASString::m_instance;
+    RplASList::m_instance = new RplASList(tree);
+    rc->m_classes[RplASList::m_instance->name()] = RplASList::m_instance;
+    RplASMap::m_instance = new RplASMap(tree);
+    rc->m_classes[RplASMap::m_instance->name()] = RplASMap::m_instance;
+    RplASVoid::m_instance = new RplASVoid(tree);
+    rc->m_classes[RplASVoid::m_instance->name()] = RplASVoid::m_instance;
+    RplASFormula::m_instance = new RplASFormula(tree);
+    rc->m_classes[RplASFormula::m_instance->name()] = RplASFormula::m_instance;
+    return rc;
+}
 /**
  * @brief Returns the list of the variables.
  *
index 02c3fd0519f02f474517e53ee26b82cb6f0dcb7e..05ffd1aaf4c3b180f756690cae833b1fef5bbc23 100644 (file)
@@ -26,6 +26,7 @@ protected:
 };
 
 class RplASUserClass;
+class RplASTree;
 class RplSymbolSpace
 {
 public:
@@ -42,6 +43,8 @@ public:
     typedef QMap<QString, RplASClass*> ClassMap;
     typedef QMap<QString, RplASMethod*> MethodMap;
     typedef QList<RplASVarDefinition*> VariableList;
+private:
+    RplSymbolSpace(RplASTree& tree);
 public:
     RplSymbolSpace(SymbolSpaceType type, const QString& name,
                    RplSymbolSpace* parent);
@@ -60,8 +63,8 @@ public:
     RplSymbolSpace* parent() const;
     VariableList listOfVars() const;
 public:
-    static void initGlobal(RplSymbolSpace& global);
     static const char* spaceTypeName(SymbolSpaceType type);
+    static RplSymbolSpace* createGlobal(RplASTree& tree);
 private:
     SymbolSpaceType m_type;
     QString m_name;
@@ -71,9 +74,7 @@ private:
     RplSymbolSpace* m_parent;
     RplASItem* m_body;
     VariableList m_listOfVars;
-
-public:
-    static RplSymbolSpace m_global;
+    RplASTree& m_tree;
 };
 
 class RplASBoolean : public RplASClass {
index 8b1638ae74f0cf0d3b9bfe74dfc1534243ca0da2..55a1bdc1f945b20bd818511325b86d9374559734 100644 (file)
@@ -104,8 +104,13 @@ RplASException::RplASException() :
 
 /** @class RplASVariant rplastree.hpp "rplexpr/rplastree.hpp"
  *
- * @brief Implements a class which can be one of the basic types.
+ * @brief Implements a class which can hold the value of any type.
  *
+ * The VM uses some tricks (performance): Therefore this class
+ * must not be virtual!
+ */
+/**
+ * @brief Constructor.
  */
 RplASVariant::RplASVariant() :
     m_variantType(VT_UNDEF),
@@ -660,7 +665,7 @@ RplASMapConstant::RplASMapConstant() :
  * @param value     IN/OUT: the value of the instance
  * @return          NULL
  */
-RplASNode1* RplASMapConstant::calc(RplASVariant& value)
+RplASNode1* RplASMapConstant::calc(RplASVariant& )
 {
     // ToDo: copy map:
     //value = m_value;
@@ -755,7 +760,7 @@ const QString& RplASNamedValue::name() const
  * @param value     In/OUT: the value of the instance
  * @return          NULL
  */
-RplASNode1* RplASNamedValue::calc(RplASVariant& value, RplStackFrame* frame)
+RplASNode1* RplASNamedValue::calc(RplASVariant& , RplStackFrame* )
 {
     return NULL;
 }
@@ -1770,11 +1775,11 @@ void RplASClass::setSymbols()
  * @brief Constructor.
  */
 RplASTree::RplASTree() :
-    // freed in ~RplASTree()
-    m_global(new RplSymbolSpace(RplSymbolSpace::SST_GLOBAL, "global", NULL)),
+    m_global(NULL),
     m_modules(),
     m_symbolSpaces(),
-    m_currentSpace(NULL)
+    m_currentSpace(NULL),
+    m_store(128*1024)
 {
     init();
 }
@@ -1794,6 +1799,7 @@ RplASTree::~RplASTree()
  */
 void RplASTree::init()
 {
+    m_global = RplSymbolSpace::createGlobal(*this);
     m_symbolSpaces.append(m_global);
     m_currentSpace = m_global;
 }
@@ -1809,6 +1815,15 @@ void RplASTree::destroy()
     }
     m_symbolSpaceHeap.clear();
 }
+/**
+ * @brief Returns the string storage of the instance.
+ *
+ * @return  the efficient allocator for C strings
+ */
+RplByteStorage& RplASTree::store()
+{
+    return m_store;
+}
 
 /**
  * @brief Handles the start of a new module.
index 4ff89a8dc0be084b7f68137d39b7326d1f9f1cce..2e21c12181adf215d7f65f943fbb572f4ec4a709 100644 (file)
@@ -55,6 +55,9 @@ class RplASItem;
 class RplASCondition;
 
 class RplASVariant {
+    /* The VM uses some tricks (performance): Therefore this class
+    * must not be virtual!
+    */
 public:
     enum VariantType {
         VT_UNDEF,
@@ -113,7 +116,7 @@ public:
     enum NodeFlags {
         NF_UNDEF,
         /// the node calculates a value:
-        VF_CALCULABLE   = 1 << 1,
+        NF_CALCULABLE   = 1 << 1,
         /// the tree under this node is complete checked for data type correctness
         NF_TYPECHECK_COMPLETE   = 1 << 2,
         /// debugger: this node is a breakpoint
@@ -596,6 +599,8 @@ public:
               const char* header = NULL);
     RplSymbolSpace*findmodule(const QString& name);
     RplSourcePosition* copyPosition();
+    RplByteStorage& store();
+
 protected:
     void init();
     void destroy();
@@ -610,6 +615,7 @@ private:
     RplSymbolSpace* m_currentSpace;
     // contain all ever built symbol spaces:
     SymbolSpaceMap m_symbolSpaceHeap;
+    RplByteStorage m_store;
 };
 
 #endif // RPLASTREE_HPP
index 0080407ee42eea97a0c4f047d6ade008f17a99b0..e8738cf0c22319040553abb227a87e621f12122a 100644 (file)
@@ -850,7 +850,6 @@ const RplSourcePosition* RplLexer::currentPosition() const
 RplToken* RplLexer::nextToken()
 {
     RplToken* rc = NULL;
-    const RplSourcePosition* waitingPosition = NULL;
     int ix;
     if (m_waitingToken != NULL){
         rc = m_currentToken = m_waitingToken;
@@ -874,7 +873,7 @@ RplToken* RplLexer::nextToken()
                 QChar cc = m_input.at(0);
                 int cc2 = cc.unicode();
                 if (cc.isSpace()){
-                    waitingPosition = m_currentPosition;
+                    //waitingPosition = m_currentPosition;
                     m_currentToken->m_tokenType = TOKEN_SPACE;
                     ix = 1;
                     while(ix < m_input.size() && m_input.at(ix).isSpace())
@@ -902,7 +901,7 @@ RplToken* RplLexer::nextToken()
                                                  CC_2nd_COMMENT_START, m_commentStarts);
                             if (rc != NULL)
                                 scanComment();
-                            waitingPosition = m_currentPosition;
+                            //waitingPosition = m_currentPosition;
                         }
 
                         if (rc == NULL && (m_charInfo[cc2] & CC_FIRST_OP)){
index 47ddbb6030001cd0db03549e960204b786b2d990..176a44d31947d317eb44d4ed7ed78a32c741adf7 100644 (file)
@@ -52,7 +52,7 @@ RplStackFrame::RplStackFrame(RplSymbolSpace* symbols) :
     m_variables(NULL),
     m_symbols(symbols)
 {
-    if (m_countLocals > 0)
+    if (m_countVariables > 0)
         m_variables = new RplASVariant[m_countVariables];
 }
 
@@ -76,7 +76,7 @@ RplASVariant& RplStackFrame::valueOfVariable(int index)
 {
     if (index < 0 || index >= m_countVariables)
         throw RplVmException("valueOfVariable(): invalid index: %d", index);
-    return *m_listOfVariables[index];
+    return m_variables[index];
 }
 
 /** @class RplVMThread rplvm.hpp "rplexpr/rplvm.hpp"
@@ -116,10 +116,11 @@ void RplVMThread::execute(RplASNode1* statements, RplSymbolSpace* space)
     bool debugMode = m_debugMode;
     while(statements != NULL){
         if (debugMode
-                && (m_singleStep || (statement->flags() & NF_BREAKPOINT) != 0))
+                && (m_singleStep
+                    || (statements->flags() & RplASItem::NF_BREAKPOINT) != 0))
             debug(statements);
         RplASCalculable* statement = dynamic_cast<RplASCalculable*>(statements);
-        statement->calc(&m_currentValue);
+        statement->calc(m_currentValue);
     }
 }
 
@@ -139,15 +140,17 @@ void RplVMThread::debug(RplASNode1* statement)
  *
  * This is a execution unit which interprets an abstract syntax tree.
  */
-RplVirtualMachine::RplVirtualMachine(RplASTree* tree, RplSource* source,
+RplVirtualMachine::RplVirtualMachine(RplASTree& tree, RplSource& source,
                                      int maxStack) :
     m_maxStack(maxStack),
     m_threads(),
     m_flags(VF_UNDEF),
     m_source(source),
-    m_tree(tree)
+    m_tree(tree),
+    m_trace()
 {
     m_threads.reserve(8);
+    m_trace.reserve(1024);
 }
 
 /**
@@ -190,13 +193,14 @@ void RplVirtualMachine::addThread(RplASItem* initialization,
                                   int maxStack)
 {
     RplVMThread* thread = new RplVMThread(
-                maxThread <= 0 ? m_maxStack : maxStack, self);
+                maxStack <= 0 ? m_maxStack : maxStack, this);
     m_threads.append(thread);
     if (initialization != NULL){
-        thread->execute(initialization, spaceInitialization);
+        thread->execute(dynamic_cast<RplASNode1*>(initialization),
+                        spaceInitialization);
     }
     if (statements != NULL)
-        thread->execute(statements, space);
+        thread->execute(dynamic_cast<RplASNode1*>(statements), space);
 }
 /**
  * @brief Tests whether a given flag is set.
@@ -208,6 +212,7 @@ void RplVirtualMachine::addThread(RplASItem* initialization,
 bool RplVirtualMachine::hasFlag(RplVirtualMachine::VMFlag flag) const
 {
     bool rc = (m_flags & flag) != 0;
+    return rc;
 }
 /**
  * @brief Adds a flag to the current flags.
@@ -217,7 +222,7 @@ bool RplVirtualMachine::hasFlag(RplVirtualMachine::VMFlag flag) const
  */
 void RplVirtualMachine::setFlag(RplVirtualMachine::VMFlag flag)
 {
-    m_flag |= flag;
+    m_flags |= flag;
 }
 
 /**
@@ -228,5 +233,5 @@ void RplVirtualMachine::setFlag(RplVirtualMachine::VMFlag flag)
  */
 void RplVirtualMachine::clearFlag(RplVirtualMachine::VMFlag flag)
 {
-    m_flag &= ~flag;
+    m_flags &= ~flag;
 }
index 24eeb37cfe615b09b0ae1cb2d1a7e4da4da0e4fb..41349356118a5968c9d3a6c951ccaac14a8b9f97 100644 (file)
@@ -55,7 +55,7 @@ public:
         VF_TRACE_AUTO_VARIABLES = 1<<3
 
     };
-
+    typedef QList<const char*> LineList;
 public:
     RplVirtualMachine(RplASTree& tree, RplSource& source, int maxStack = 1024);
 public:
@@ -73,6 +73,7 @@ private:
     int m_flags;
     RplSource& m_source;
     RplASTree& m_tree;
+    LineList m_trace;
 };
 
 #endif // RPLVM_HPP
index 6c194f08b4c09aa0fdd999da660b1004b933a61b..05acac0bdbb1938a42fb1338656c40940f9b80f3 100644 (file)
@@ -45,8 +45,9 @@ private:
         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);
+        //vm.dump(fnCurrent, RplASTree::DMP_NO_GLOBALS);
         assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
                          __FILE__, lineNo);
     }
index 19d3f14f9347b433503e6c1051e9b3385bf4cc8b..736821257d8ee8bf10d1619ab2aa7b24fc6f5245 100644 (file)
@@ -37,7 +37,8 @@ SOURCES += \
     ../rplexpr/rplasclasses.cpp \
     ../rplexpr/rplmfparser.cpp \
     ../rplexpr/rplvm.cpp \
-    ../rplexpr/rplparser.cpp
+    ../rplexpr/rplparser.cpp \
+    ../rplcore/rplbytestorage.cpp
 
 HEADERS += ../rplmodules.hpp \
     ../rplcore/rplconfig.hpp \
@@ -66,7 +67,8 @@ HEADERS += ../rplmodules.hpp \
     ../rplexpr/rplasclasses.hpp \
     ../rplexpr/rplmfparser.hpp \
     ../rplexpr/rplvm.hpp \
-    ../rplexpr/rplparser.hpp
+    ../rplexpr/rplparser.hpp \
+    ../rplcore/rplbytestorage.hpp
 
 unix:!symbian {
     maemo5 {
index 0f195b5b98bc159687c8b90ab727b7d0173f5f6b..10ff4237ffbb4e948d757372ee58ac9346b350c2 100644 (file)
@@ -1,5 +1,5 @@
 2+3*4
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Body:
 Expr id: 6 expr: 2 succ: 0 <test>:1:1
        BinOp id: 2 op: + (26) left: 1 right: 4 <test>:1:1
index 89dc16b6c7825cd5d216a4f5056d024e10d3f5da..e8826b39adbc9b508ad8ad3e22d2ead28ae011b0 100644 (file)
@@ -1,5 +1,5 @@
 Int i = 3; const lazy Str s = 'Hi'; const List l;
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef i id: 2 namedValue: 1 value: 3 succ: 5 <test>:1:4
        namedValue i id: 1 attr: 0x0 <test>:1:4
index 4cbe9265aafb5490d5589418570620c65b709e8b..b9960dfe3caa02c2dd3c7861af119310e0c621d9 100644 (file)
@@ -1,7 +1,7 @@
 file.find('*.c')[0].name;
 [1,2,3].join(' ');
 3.14.trunc;
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Body:
 Expr id: 8 expr: 7 succ: 15 <test>:1:24
        field name id: 7 parent: 5 succ: <test>:1:24
index 64c14c34e664d7bebe005fc84f2965fc2beeb57f..82ef81de76283d5e89888bdfe3008608e5203ca0 100644 (file)
@@ -2,7 +2,7 @@ Int a;
 for b from 10 to 1 step -2 do
 a += 1;
 od
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 0 succ: 4 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index 117dc323cbbdb2448b09b889802a477507325f04..1ad13311140b1074cb90d72f880327f2ef7d12aa 100644 (file)
@@ -1,5 +1,5 @@
 Int a; for to 10 do a += 1 od
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 0 succ: 3 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index e76a69ddf8c982df6edcd5eab7a3c8d2aebb8fd0..b3198fda5daef88d214c13667ce9086bfe88c324 100644 (file)
@@ -2,7 +2,7 @@ Map a;
 for x in a do
 a += 1;
 od
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 0 succ: 4 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index 217a7bef0ed91c58e86109cfc2ab1c53c56fc6e9..136e306fc0372d1c039279e264b4f02f54dec938 100644 (file)
@@ -5,7 +5,7 @@ if 11 < 12
 then a = 13 * 14
 else a = 15 / 16
 fi
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 0 succ: 4 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index bfaa9ea906fbdbe37b4a87ac8b4c9fcf3ff8995a..26a5e662ffc691bb83d8dc310c3804a02803f259 100644 (file)
@@ -2,7 +2,7 @@ Str x;
 if 7 < 6
 then x = '123';
 fi
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef x id: 2 namedValue: 1 value: 0 succ: 3 <test>:1:4
        namedValue x id: 1 attr: 0x0 <test>:1:4
index 2de17e1eb0f22e827feedb0d0bfff83cea1dda94..9c0026e7cc4df4cc24b98533a46efd09dfbee13b 100644 (file)
@@ -1,5 +1,5 @@
 List b = [];
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef b id: 2 namedValue: 1 value: 3 succ: 0 <test>:1:5
        namedValue b id: 1 attr: 0x0 <test>:1:5
index fd904e5f43e23a6e33ff68f4ec08bed4c973290b..1f2deead218f84824e81291fe0533e7828214311 100644 (file)
@@ -1,5 +1,5 @@
 List a = [2+3, 3.14, 7, 'hi', a]; List b = [];
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 3 succ: 11 <test>:1:5
        namedValue a id: 1 attr: 0x0 <test>:1:5
index 0d69fce63eebd7647c19f7d26af86a6b59e89792..1e51ff7a284df230359c1ecfeebdbb17d53d2891 100644 (file)
@@ -1,5 +1,5 @@
 Map a = {};
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 3 succ: 0 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index ca8537656660136f04ba0fca40155f948c666dd1..35c785289f2974ecf3bbdb8da9034b962a525d11 100644 (file)
@@ -1,6 +1,6 @@
 Map a = {'a': 2+3,'bcd':3.14,'ccc':7, 'hi':'world'};
 Map b = {};
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 3 succ: 11 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index 3f7dc3fa9b91a6cb496090dcf69956c365a421aa..ba888fc2edd2541758c95a82a4fb4e1d6e972a56 100644 (file)
@@ -1,5 +1,5 @@
 func Float pi: 3.1415; endf func Str delim(): '/' endf;
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Methods:
 Method <NoneType> delim() id: 4 parent: <test> args: 0 body: 6 <test>:1:28
        Expr id: 6 expr: 5 succ: 0 <test>:1:46
index 4838410c36741d0e976f390aee9ced9872fb49a5..c29148d1067e938e37f116e164b6920f46b9a781 100644 (file)
@@ -1,7 +1,7 @@
 func Int fac(const Int n):
 Int rc; if rc <= 1 then rc = 1 else rc = n*fac(n-1) fi
 rc endf
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Methods:
 Method <NoneType> fac() id: 1 parent: <test> args: 4 body: 6 <test>:0:55
        Expr id: 4 expr: 3 succ: 0 
index 74b57d87e998d321f6eb085ead94970547ecc454..f3fe793653fd7272549b49a886a995e63a82f767 100644 (file)
@@ -6,7 +6,7 @@ endf
 func Int max(const Int a, Int b, Int c):
 max(a, max(b, c))
 endf
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Methods:
 Method <NoneType> max() id: 21 parent: <test> args: 24 body: 40 <test>:5:5
        Expr id: 24 expr: 23 succ: 27 
index 1e0449ab5b736f1a69d17d6221d500e90e22edce..ac39b737fbc80537f418a4d30b1749b5c96523eb 100644 (file)
@@ -6,7 +6,7 @@ rc
 endf
 max(a, max(b, c))
 endf
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Methods:
 Method <NoneType> max() id: 1 parent: <test> args: 4 body: 40 <test>:0:4
        Expr id: 4 expr: 3 succ: 7 
index 3ccf636a6470745d4f6ce0099a36fb8159e5125f..e418cbb8d40255c8cc35e0770fe62bc89f6ff56f 100644 (file)
@@ -1,7 +1,7 @@
 rand();
 sin(a);
 max(1+2*3,4**(5-4));
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Body:
 Expr id: 2 expr: 1 succ: 6 <test>:1:4
        call rand Id: 1 args: 0 parent: 0 succ: 0 <test>:1:4
index ac8e160ee80d02311d3cce5c333fd1b71c84b861..b63236646045ffe2f956556661b9e615cad6cb6c 100644 (file)
@@ -4,7 +4,7 @@ Int b = 100;
 b++;
 a--*++b**(8-3);
 a=b=(a+(b-2)*3)
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 3 succ: 5 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index e2acdec93ed6c7a81fb052a3e85c26dc2804ff14..1d1818edb8f3c209139e35e109069bbe177b6462 100644 (file)
@@ -2,7 +2,7 @@ Int a;
 repeat
 a++;
 until a != 2 * 3;
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 0 succ: 3 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index ad6887d058a2b78fbe6601d876e95e762e16c528..44bccb1488947da1ca416bba126671e7cd98e74e 100644 (file)
@@ -2,7 +2,7 @@ Int a = 20;
 while 3 < 5 do
  a = 7
 od
-= <test> (module) parent: global
+= <test> (module) parent: $global
 == Variables:
 varDef a id: 2 namedValue: 1 value: 3 succ: 4 <test>:1:4
        namedValue a id: 1 attr: 0x0 <test>:1:4
index 87406f888c049f0cf92f077c470ca0f5f8b6390c..74a74511bb764708a67b26b5e14bf749fd34f9a1 100644 (file)
@@ -11,6 +11,8 @@
 #include <QCoreApplication>
 
 void testCore(){
+    extern void testRplByteStorage();
+    testRplByteStorage();
     extern void testRplQString();
     testRplQString();
 
diff --git a/unittests/rplbytestorage_test.cpp b/unittests/rplbytestorage_test.cpp
new file mode 100644 (file)
index 0000000..6c8ae4c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 "rplcore/rpltest.hpp"
+
+class TestRplByteStorage : public RplTest{
+public:
+    TestRplByteStorage() :
+        RplTest("RplByteStorage")
+    {}
+private:
+    void testChars(){
+        RplByteStorage store(100);
+        char* s1 = store.allocateChars(4);
+        memcpy((void*) s1, "123", 4);
+        const char* s2 = store.allocateChars("abc");
+        const char* s3 = store.allocateChars("defghij", 3);
+        checkE(s1, "123");
+        checkE(s2, "abc");
+        checkE(s3, "def");
+        const char* ptr = s1 + 4;
+        checkT(ptr == s2);
+        ptr += 4;
+        checkT(ptr == s3);
+    }
+
+    void testBytes(){
+        RplByteStorage store(100);
+        uint8_t* s1 = store.allocateBytes(4);
+        memcpy((void*) s1, "1234", 4);
+        uint8_t* s2 = store.allocateBytes((void*) "abcd", 4);
+        uint8_t* s3 = store.allocateBytes((void*) "efghij", 4);
+        uint8_t* s4 = store.allocateZeros(4);
+
+        checkE("1234abcdefgh", (const char*) s1);
+        uint8_t* ptr = s1 + 4;
+        checkT(ptr == s2);
+        ptr += 4;
+        checkT(ptr == s3);
+        ptr += 4;
+        checkT(ptr == s4);
+        for (int ii = 0; ii < 4; ii++)
+            checkE(0, (int) s4[ii]);
+    }
+    void testBufferChange(){
+        RplByteStorage store(10);
+        char buffer[2];
+        buffer[1] = '\0';
+        for (int ii = 0; ii < 10000; ii++){
+            buffer[1] = 'A' + ii % 26;
+            store.allocateBytes(buffer, 1);
+        }
+        int a = 1;
+    }
+
+public:
+    virtual void doIt() {
+        testBufferChange();
+        testChars();
+        testBytes();
+    }
+};
+void testRplByteStorage() {
+    TestRplByteStorage test;
+    test.run();
+}
+
+
index 891dbfdaaf3c84e6b60258b37e606e7294a38562..a28f5c205ee6d1609f1647ef3de8a289ff5aa8c5 100644 (file)
@@ -37,5 +37,8 @@ SOURCES += main.cpp \
     ../rplexpr/rplasclasses.cpp \
     rplastree_test.cpp \
     rplmfparser_test.cpp \
-    ../rplexpr/rplvm_test.cpp
+    ../rplexpr/rplvm_test.cpp \
+    rplbytestorage_test.cpp \
+    ../rplcore/rplbytestorage.cpp \
+    ../rplexpr/rplvm.cpp