*-conflict_*
*~
*.pro.user
+doc/
+*.log
+
--- /dev/null
+#! /bin/bash
+
+ZIP=rpldoc.zip
+rm -Rf $ZIP doc/
+doxygen
+zip -qr9 $ZIP doc/
+ls -ld $ZIP
*/
enum Locations {
- LOC_WRITE_1 = RPL_FIRST_OF(RPLMODULE_CONFIG),
+ LOC_WRITE_1 = RPL_FIRST_OF(RPLMODULE_CONFIG), // 10201
LOC_WRITE_2,
LOC_READ_1,
LOC_READ_2,
/** @file
* @brief Generally usable exceptions.
*/
-/** @file rplcore/rplexeption.hpp
+/** @file rplcore/rplexception.hpp
*
* @brief Definitions for a generally usable exceptions.
*/
#include <iostream>
enum {
- LOC_ADD_APPENDER_1 = RPL_FIRST_OF(RPLMODULE_LOGGER), // 10000
+ LOC_ADD_APPENDER_1 = RPL_FIRST_OF(RPLMODULE_LOGGER), // 10101
};
RplLogger* RplLogger::m_globalLogger = NULL;
#include "rplcore.hpp"
enum {
- LOC_CAUSE_TERMINATION_1 = RPL_FIRST_OF(RPLMODULE_TERMINATOR), // 901
+ LOC_CAUSE_TERMINATION_1 = RPL_FIRST_OF(RPLMODULE_TERMINATOR), // 10901
};
/**
}
}
+/**
+ * @brief Starts a scope.
+ *
+ * A scope is an "area" where variables can be defined.
+ * A variable "lives" in a scope.
+ *
+ * Saves the status to restore it in <code>finishScope()</code>.
+ *
+ * @param scope OUT: status info
+ */
+void RplSymbolSpace::startScope(RplASScope& scope)
+{
+ scope.m_varNoAtStart = m_listOfVars.size();
+}
+
+/**
+ * @brief Finishes a scope.
+ *
+ * Finishes the "live" of the variables created in the ending scope.
+ *
+ * @param scope the status of the scope at start.
+ */
+void RplSymbolSpace::finishScope(RplASScope& scope)
+{
+ // in methods/classes not needed:
+ for (ix = scope.m_varNoAtStart; ix < m_listOfVars.size(); ix++){
+ const QString& name = m_listOfVars[ix]->name();
+ if (m_variables.contains(name))
+ m_variables.remove(name);
+ }
+}
+
/**
* @brief Search the class in the symbol space hierarchy.
*
* @brief Adds a variable to the symbol space.
*
* @param variable the variable to add
+ * @param varNo OUT: variable number, current number in the symbol space
* @return NULL: success<br>
* otherwise: the already defined variable/method
*/
-RplASItem* RplSymbolSpace::addVariable(RplASVarDefinition* variable)
+RplASItem* RplSymbolSpace::addVariable(RplASVarDefinition* variable, int& varNo)
{
RplASItem* rc = NULL;
const QString& name = variable->name();
rc = m_methods[name];
else {
m_variables[name] = variable;
+ varNo = m_listOfVars.size();
+ m_listOfVars.append(variable);
}
return rc;
}
name1.constData(),
name2.constData(), val.constData());
}
+/**
+ * @brief Returns the data type of the variable.
+ *
+ * @return the class of the variable
+ */
+RplASClass* RplVariable::type() const
+{
+ return m_type;
+}
+
+/**
+ * @brief Sets the data type.
+ * @param type the class of the variable
+ */
+void RplVariable::setType(RplASClass* type)
+{
+ m_type = type;
+}
+
/** @class RplVariable rplastree.hpp "rplexpr/rplastree.hpp"
*
public:
void dump(RplWriter& writer, int indent);
+ RplASClass* type() const;
+ void setType(RplASClass* type);
+
protected:
QString m_name;
// NULL for "simple" variables (int, float, bool)
RplASClass* m_type;
};
+class RplASScope
+{
+public:
+ RplASScope();
+public:
+ int m_varNoAtStart;
+};
+
class RplASUserClass;
class RplASTree;
class RplSymbolSpace
RplSymbolSpace* parent);
virtual ~RplSymbolSpace();
public:
+ void startScope(RplASScope& scope);
+ void finishScope(RplASScope& scope);
RplVariable* findVariable(const QString& name) const;
RplASClass* findClass(const QString& name) const;
RplASMethod* findMethod(const QString& name) const;
#include "rplexpr/rplexpr.hpp"
enum {
- LOC_VARDEF_EXEC_1 = RPL_FIRST_OF(RPL_MODULE_ASTREE), // 10001
+ LOC_VARDEF_EXEC_1 = RPL_FIRST_OF(RPL_MODULE_ASTREE), // 11001
LOC_UNOP_1,
LOC_UNOP_2,
LOC_UNOP_3,
* <code>m_child</code>: NULL or the index expression (map/list)
*/
-/**
- * @brief Constructor.
- *
- * @param name the name of the instance
- */
-RplASNamedValue::RplASNamedValue(const QString& name) :
- RplASNode1(AST_NAMED_VALUE),
- m_name(name),
- m_attributes(0),
- m_dataType(NULL),
- m_symbolSpace(NULL),
- m_variableNo(0)
-{
-}
-
/**
* @brief Constructor.
*
* @param name the name of the variable
* @param attributes the attributes of the variable
*/
-RplASNamedValue::RplASNamedValue(RplASClass* dataType,
- const QString& name, int attributes) :
+RplASNamedValue::RplASNamedValue(RplASClass* dataType,RplSymbolSpace* space,
+ const QString& name, int attributes) :
RplASNode1(AST_NAMED_VALUE),
m_name(name),
m_attributes(attributes),
m_dataType(dataType),
- m_symbolSpace(NULL),
+ m_symbolSpace(space),
m_variableNo(0)
{
}
return m_symbolSpace;
}
+/**
+ * @brief Sets the variable no in the instance.
+ *
+ * @param variableNo the variable number
+ */
+void RplASNamedValue::setVariableNo(int variableNo)
+{
+ m_variableNo = variableNo;
+}
+
+
/**
* @brief Returns the variable no of the variable.
*
/// the evaluation should be lazy
A_LAZY = 1<<4,
/// parameter of a method
- A_PARAM = 1<<5
+ A_PARAM = 1<<5,
+ /// a automatic variable in counted for loops:
+ A_LOOP = 1<<6
};
public:
- RplASNamedValue(const QString& name);
- RplASNamedValue(RplASClass* dataType,
+ RplASNamedValue(RplASClass* dataType, RplSymbolSpace* space,
const QString& name, int attributes);
public:
const QString& name() const;
void assign(RplVMThread& thread);
RplSymbolSpace* symbolSpace() const;
int variableNo() const;
+ void setVariableNo(int variableNo);
protected:
QString m_name;
int m_attributes;
/** @file
* @brief Configurable scanner, wich separates syntactic symbols from an input media.
*/
-/** @file rplexpr/rpllexxer.hpp
+/** @file rplexpr/rpllexer.hpp
* @brief Definitions for a configurable lexical analyser.
*/
RplToken* token = m_lexer.nextNonSpaceToken();
RplASNamedValue* var = NULL;
if (token->isTokenType(TOKEN_ID)){
- var = new RplASNamedValue(token->toString());
+ var = new RplASNamedValue(RplASInteger::m_instance,
+ m_tree.currentSpace(), token->toString(),
+ RplASNamedValue::A_LOOP);
var->setPosition(m_lexer.currentPosition());
token = m_lexer.nextNonSpaceToken();
}
token = m_lexer.nextNonSpaceToken();
if (! token->isTokenType(TOKEN_ID))
syntaxError(L_DEFINITION_MISSING_ID, "variable name expected");
+ RplSymbolSpace* symbols = m_tree.currentSpace();
// freed in the destructor of the nodes:
- RplASNamedValue* namedValue = new RplASNamedValue(clazz, token->toString(),
+ RplASNamedValue* namedValue = new RplASNamedValue(clazz, symbols,
+ token->toString(),
attributes);
namedValue->setPosition(m_lexer.currentPosition());
RplASVarDefinition* rc = new RplASVarDefinition();
rc->setChild3(value);
token = m_lexer.currentToken();
}
- RplSymbolSpace* symbols = m_tree.currentSpace();
- RplASItem* oldSymbol = symbols->addVariable(rc);
+ int varNo = 0;
+ RplASItem* oldSymbol = symbols->addVariable(rc, varNo);
if (oldSymbol != NULL)
error(L_PARSE_VAR_DEF_ALREADY_DEFINED, oldSymbol->position(),
"symbol already defined", "previous definition");
+ namedValue->setVariableNo(varNo);
return rc;
}
}
/**
- * @brief Builds a node of a variable or a field.
+ * @brief Builds a node of a variable or a field (as an operand).
*
* @param name name of the variable/field
* @param position source position
{
RplASItem* rc = NULL;
if (parent == NULL){
- RplASNamedValue* var = new RplASNamedValue(name);
+ RplSymbolSpace* space = m_tree.currentSpace();
+ RplVariable* var = space->findVariable(name);
+ RplASClass* clazz = NULL;
+ if (var != NULL)
+ clazz = var->type();
+ RplASNamedValue* var = new RplASNamedValue(clazz, space,
+ name, RplASNamedValue::A_NONE);
var->setPosition(position);
rc = var;
} else {
RplASItem* item = NULL;
RplASItem* body = NULL;
RplASNode1* lastStatement = NULL;
+ RplASScope scope;
+ m_tree.currentSpace()->startScope(scope);
bool again = true;
const RplSourcePosition* lastPos = NULL;
do {
}
}
} while(again);
+
+ if (keywordStop != K_ENDF && keywordStop != K_ENDC)
+ m_tree.currentSpace()->finishScope(scope);
return body;
}
#include "rplcore/rplcore.hpp"
#include "rplexpr/rplexpr.hpp"
+enum {
+ LOC_VAL_OF_VAR_1 = RPL_FIRST_OF(RPL_MODULE_VM), // 11401
+ LOC_UNOP_1,
+ LOC_UNOP_2,
+ LOC_UNOP_3,
+ LOC_UNOP_4, // 10005
+ LOC_BINOP_1,
+ LOC_COUNT
+};
+
int RplVMThread::m_nextId = 1;
/** @class RplVmException rplvm.hpp "rplexpr/rplvm.hpp"
throw RplVmException("valueOfVariable(): invalid index: %d", index);
return m_variables[index];
}
+/**
+ * @brief Returns the symbol space of the frame.
+ *
+ * @return the symbol space
+ */
+RplSymbolSpace* RplStackFrame::symbols() const
+{
+ return m_symbols;
+}
/** @class RplVMThread rplvm.hpp "rplexpr/rplvm.hpp"
*
m_singleStep(false),
m_debugMode(false),
m_maxStack(maxStack),
- m_stack(),
+ m_frameStack(),
+ // the stack is never empty!
+ m_topOfFrames(0),
m_valueStack(),
// the stack is never empty!
m_topOfValues(1),
{
QByteArray prefix = "vm_thread_" + QByteArray::number(m_id);
m_logger->buildStandardAppender(prefix);
- m_stack.reserve(maxStack);
+ m_frameStack.reserve(maxStack);
+ // the stack is never empty!
+ m_frameStack.append(new RplStackFrame(vm->tree().symbolSpaces()[0]));
// the stack is never empty!
m_valueStack.append(new RplASVariant);
}
int variableNo)
{
RplASVariant& rc = *m_valueStack[0];
+ int ix = m_topOfFrames;
+ RplStackFrame* frame = NULL;
+ for(int ix = m_topOfFrames; ix >= 0; ix--){
+ frame = m_frameStack[ix];
+ if (frame->symbols() == symbolSpace){
+ rc = frame->valueOfVariable(variableNo);
+ break;
+ }
+ }
+ if (frame == NULL)
+ m_logger->logv(LOG_ERROR, LOC_VAL_OF_VAR_1, "no frame has symbolspace %s",
+ symbolSpace->name().toUtf8().constData());
return rc;
}
{
m_traceWriter = traceWriter;
}
+/**
+ * @brief Returns the abstract symbol tree.
+ *
+ * @return the abstract symbol tree
+ */
+RplASTree& RplVirtualMachine::tree() const
+{
+ return m_tree;
+}
~RplStackFrame();
public:
RplASVariant& valueOfVariable(int index);
+ RplSymbolSpace* symbols() const;
+
private:
int m_countVariables;
RplASVariant* m_variables;
bool m_debugMode;
bool m_singleStep;
int m_maxStack;
- StackFrameList m_stack;
+ StackFrameList m_frameStack;
+ int m_topOfFrames;
QList<RplASVariant*> m_valueStack;
int m_topOfValues;
RplVirtualMachine* m_vm;
void setFlag(VMFlag flag);
void clearFlag(VMFlag flag);
void setTraceWriter(RplWriter* traceWriter);
+ RplASTree& tree() const;
private:
int m_maxStack;
#define RPLMODULES_HPP
enum {
- RPLMODULE_LOGGER = 1,
+ RPLMODULE_LOGGER = 101,
RPLMODULE_CONFIG,
RPLMODULE_CONTAINER,
RPLMODULE_EXCEPTION,
- RPLMODULE_TEST, // 5
+ RPLMODULE_TEST, // 105
RPLMODULE_TCPSERVER,
RPLMODULE_TCPCLIENT,
RPLMODULE_TCPPEER,
RPLMODULE_TERMINATOR,
- RPL_MODULE_ASTREE, // 10
+ RPL_MODULE_ASTREE, // 110
RPL_MODULE_ASCLASSES,
RPL_MODULE_LEXER,
RPL_MODULE_SOURCE,
- RPL_MODULE_ASVM,
- RPL_MODULE_MFPARSER, // 15
+ RPL_MODULE_VM,
+ RPL_MODULE_MFPARSER, // 115
// last element:
RPLMODULE_COUNT
};
-#define RPL_FIRST_OF(moduleNo) (moduleNo*1000+1)
+#define RPL_FIRST_OF(moduleNo) (moduleNo*100+1)
class RplModules{
public:
static int fileToNumber(const char* file);
#include "rplnet.hpp"
enum {
- LOC_1 = RPL_FIRST_OF(RPLMODULE_TCPCLIENT), // 701
+ LOC_1 = RPL_FIRST_OF(RPLMODULE_TCPCLIENT), // 10701
LOC_HANDLE_ERROR_1,
LOC_SET_REMOTE_ADDRESS_1,
};
#include "rplnet.hpp"
enum {
- LOC_SEND_1 = RPL_FIRST_OF(RPLMODULE_TCPPEER), // 801
+ LOC_SEND_1 = RPL_FIRST_OF(RPLMODULE_TCPPEER), // 10801
LOC_READ_BYTES_1,
LOC_READ_BYTES_2,
LOC_READ_BYTES_3,
#include "rplnet.hpp"
enum {
- LOC_RUN_1 = RPL_FIRST_OF(RPLMODULE_TCPSERVER), // 601
+ LOC_RUN_1 = RPL_FIRST_OF(RPLMODULE_TCPSERVER), // 10601
LOC_TCP_TREAD_RUN_1,
LOC_TCP_TREAD_RUN_2,
LOC_TCP_INCOMING_CONNECTION_1,