+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
+
*/
/** @file rplcore/rplbytestorage.hpp
*
- * @brief Definitions for a 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"
/**
* @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'
*
* @brief Puts the logging info to a medium (e.g. a file).
*
- * This is a abstract base class.
+ * This is an abstract base class.
*/
/**
/** @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>.
*/
}
/**
- * @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.
/** @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:
*
* @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) {
/** @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";
*/
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.
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.
*
/**
* @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)
*/
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);
}
/**
fputs(line, m_fp);
fputs(m_eoln, m_fp);
}
+ if (m_additionalStream != NULL){
+ if (line != NULL)
+ fputs(line, m_additionalStream);
+ fputc('\n', m_additionalStream);
+ }
}
/**
fclose(m_fp);
m_fp = NULL;
}
+ m_additionalStream = NULL;
}
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:
{
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);
FILE* m_fp;
QByteArray m_name;
QByteArray m_eoln;
+ FILE* m_additionalStream;
};
#endif // RPLWRITER_HPP
}
/**
- * @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
}
/**
- * @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
*/
*
* @brief Implements the class of a Boolean.
*
- * A Boolean is a one of the values true and false.
+ * A Boolean is one of the values true and false.
*/
/**
* @brief Constructor.
}
/**
- * @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
/** @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.
*/
}
/**
- * @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
#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) \
m_value.m_object = NULL;
break;
}
+ m_variantType = VT_UNDEF;
}
/**
* @brief Returns the variantType of the instance.
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.
*
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.
*/
{
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.
*
}
/**
- * @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);
}
/**
}
/**
- * @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);
}
/**
}
/**
- * @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.
RplASNode1(AST_NAMED_VALUE),
m_name(name),
m_attributes(0),
- m_dataType(NULL)
+ m_dataType(NULL),
+ m_symbolSpace(NULL),
+ m_variableNo(0)
{
}
RplASNode1(AST_NAMED_VALUE),
m_name(name),
m_attributes(attributes),
- m_dataType(dataType)
+ m_dataType(dataType),
+ m_symbolSpace(NULL),
+ m_variableNo(0)
{
}
{
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.
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)
RplASNode3(AST_VAR_DEFINITION),
RplASStatement()
{
+ m_flags |= NF_STATEMENT;
}
/**
/**
* @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"
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.
*
}
}
+
/** @class RplASNode2 rplastree.hpp "rplexpr/rplastree.hpp"
*
* @brief Implements an inner node of the abstract syntax tree with two childs.
/** @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.
*/
/**
{
}
+/**
+ * @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.
*
/**
* @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;
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(),
throw RplASException(m_child4->position(),
"if statement: else-part is not a statement");
}
- body->execute();
+ body->execute(thread);
}
/**
RplASNode4(AST_ITERATED_FOR),
RplASStatement()
{
+ m_flags |= NF_STATEMENT;
m_child2 = variable;
}
* @brief Executes the statement.
*
*/
-void RplASForIterated::execute()
+void RplASForIterated::execute(RplVMThread& thread)
{
}
RplASNode6(AST_ITERATED_FOR),
RplASStatement()
{
+ m_flags |= NF_STATEMENT;
m_child3 = variable;
}
* @brief Executes the statement.
*
*/
-void RplASForCounted::execute()
+void RplASForCounted::execute(RplVMThread& thread)
{
RplASStatement* body = dynamic_cast<RplASStatement*>(m_child2);
if (body == NULL)
var = dynamic_cast<RplASNamedValue*>(m_child3);
}
for(int ii = start; ii <= end; ii += step){
- body->execute();
+ body->execute(thread);
}
}
RplASNode3(AST_WHILE),
RplASStatement()
{
+ m_flags |= NF_STATEMENT;
}
/**
*
* Meaning of the childs:
*/
-void RplASWhile::execute()
+void RplASWhile::execute(RplVMThread& thread)
{
RplASStatement* body = dynamic_cast<RplASStatement*>(m_child3);
if (body == NULL)
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);
}
}
RplASNode3(AST_REPEAT),
RplASStatement()
{
+ m_flags |= NF_STATEMENT;
}
/**
* m_child: body
* m_child2: condition
*/
-void RplASRepeat::execute()
+void RplASRepeat::execute(RplVMThread& thread)
{
RplASStatement* body = dynamic_cast<RplASStatement*>(m_child3);
if (body == NULL)
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));
}
/**
/** @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.
*/
m_name(name),
m_method(NULL)
{
+ m_flags |= NF_STATEMENT;
m_child3 = parent;
}
/**
* @brief Executes the statement.
*/
-void RplASMethodCall::execute()
+void RplASMethodCall::execute(RplVMThread& thread)
{
}
*/
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;
}
*
* @param op the operator
*/
-void RplASBinaryOp::setOperator(int op)
+void RplASBinaryOp::setOperator(BinOperator op)
{
m_operator = op;
}
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.
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:
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
};
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.
public:
static void reset();
RplASItemType nodeType() const;
+ const char* nameOfItemType() const;
int flags() const;
void setFlags(int flags);
};
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();
public:
RplASListConstant();
public:
- virtual RplASNode1* calc(RplASVariant& value);
+ virtual void calc(RplVMThread& thread);
public:
virtual void dump(RplWriter& writer,int indent);
RplASVariant& value();
public:
RplASMapConstant();
public:
- virtual RplASNode1* calc(RplASVariant& value);
+ virtual void calc(RplVMThread& thread);
public:
virtual void dump(RplWriter& writer,int indent);
RplASVariant& value();
RplASVariant m_value;
};
+class RplSymbolSpace;
class RplASNamedValue : public RplASNode1, public RplASStorable
{
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 {
public:
RplASStatement();
public:
- virtual void execute() = 0;
+ virtual void execute(RplVMThread& thread) = 0;
};
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;
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
public:
RplASCondition();
public:
- RplASNode1* calc(RplASVariant& value);
- bool calcAsBool();
+ void calc(RplVMThread& thread);
+ bool calcAsBool(RplVMThread& thread);
void dump(RplWriter& writer, int indent);
};
public:
RplASIf();
public:
- virtual void execute();
+ virtual void execute(RplVMThread& thread);
virtual void dump(RplWriter& writer, int indent);
};
public:
RplASForIterated(RplASNamedValue* variable);
public:
- virtual void execute();
+ virtual void execute(RplVMThread& thread);
virtual void dump(RplWriter& writer, int indent);
};
public:
RplASForCounted(RplASNamedValue* variable);
public:
- virtual void execute();
+ virtual void execute(RplVMThread& thread);
virtual void dump(RplWriter& writer, int indent);
};
public:
RplASWhile();
public:
- virtual void execute();
+ virtual void execute(RplVMThread& thread);
virtual void dump(RplWriter& writer, int indent);
};
public:
RplASRepeat();
public:
- virtual void execute();
+ virtual void execute(RplVMThread& thread);
virtual void dump(RplWriter& writer, int indent);
};
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;
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();
}
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.
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
* 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
*
* @brief Implements an interpreter of an abstract syntax tree.
*/
+
/** @file rplexpr/rplvm.hpp
*
* @brief Definitions for an interpreter of an abstract syntax tree.
#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.
* @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);
}
/**
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());
}
}
}
+/**
+ * @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) :
{
m_flags &= ~flag;
}
+
+/**
+ * @brief Sets the trace writer.
+ *
+ * @param traceWriter the new writer
+ */
+void RplVirtualMachine::setTraceWriter(RplWriter* traceWriter)
+{
+ m_traceWriter = traceWriter;
+}
+
class RplVirtualMachine;
class RplVMThread
{
+ friend class RplASItem;
+ friend class RplASStatement;
+ friend class RplASCalculable;
+ friend class RplASCondition;
public:
typedef QList<RplStackFrame*> StackFrameList;
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
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;
RplSource& m_source;
RplASTree& m_tree;
LineList m_trace;
+ RplWriter* m_traceWriter;
};
#endif // RPLVM_HPP
+++ /dev/null
-/*
- * 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();
-}
-
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
};
* @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,
*/
RplTcpServer::RplTcpServer(RplConfigurator& configurator,
RplTaskHandler* taskHandler,
- RplThreadFactory& threadFactory,
+ RplVMThreadFactory& threadFactory,
RplLogger* logger,
QObject* parent) :
QTcpServer(parent),
}
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");
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() {
*/
#include "rplcore/rplcore.hpp"
#include "rplcore/rpltest.hpp"
+/** @file
+ * @brief Unit test of the basic exceptions.
+ */
class TestRplException : public RplTest{
public:
#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(),
}
};
void testRplMFParser() {
- TestRplVM test;
+ TestRplMFParser test;
test.run();
}
--- /dev/null
+/*
+ * 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();
+}
+
TEMPLATE = app
SOURCES += main.cpp \
- rplmatrix_test.cpp \
../rplcore/rpllogger.cpp \
../rplcore/rpltest.cpp \
../rplcore/rplstring.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