Use class hierarchy for the different types of expressions.

master
Torsten Paul 2014-11-24 23:37:42 +01:00
parent 756f8079d8
commit dc8f559b85
6 changed files with 628 additions and 490 deletions

View File

@ -94,19 +94,19 @@ std::string Builtins::isDeprecated(const std::string &name)
Builtins::Builtins() Builtins::Builtins()
{ {
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0))))); this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(ValuePtr(2.0))))); this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(2.0)))));
this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(ValuePtr(12.0))))); this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(12.0)))));
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0))))); this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
Value::VectorType zero3; Value::VectorType zero3;
zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0));
ValuePtr zero3val(zero3); ValuePtr zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new Expression(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(ValuePtr(500))))); this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(500)))));
} }
Builtins::~Builtins() Builtins::~Builtins()

View File

@ -23,7 +23,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
#include "expression.h" #include "expression.h"
#include "value.h" #include "value.h"
#include "evalcontext.h" #include "evalcontext.h"
@ -32,14 +31,10 @@
#include <algorithm> #include <algorithm>
#include "stl-utils.h" #include "stl-utils.h"
#include "printutils.h" #include "printutils.h"
#include "stackcheck.h"
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
ExpressionEvaluator * Expression::evaluators[256];
// static initializer for the expression evaluator lookup table
ExpressionEvaluatorInit Expression::evaluatorInit;
// unnamed namespace // unnamed namespace
namespace { namespace {
Value::VectorType flatten(Value::VectorType const& vec) { Value::VectorType flatten(Value::VectorType const& vec) {
@ -71,358 +66,49 @@ namespace {
} }
} }
class ExpressionEvaluatorAbort : public ExpressionEvaluator Expression::Expression()
{ {
ValuePtr evaluate(const class Expression *, const class Context *) const {
abort();
}
};
class ExpressionEvaluatorNot : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return ! expr->children[0]->evaluate(context);
}
};
class ExpressionEvaluatorLogicalAnd : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) && expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorLogicalOr : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) || expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorMultiply : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) * expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorDivision : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) / expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorModulo : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) % expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorPlus : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) + expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorMinus : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) - expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorLess : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) < expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorLessOrEqual : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) <= expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorEqual : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) == expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorNotEqual : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children.at(0)->evaluate(context) != expr->children.at(1)->evaluate(context);
}
};
class ExpressionEvaluatorGreaterOrEqual : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) >= expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorGreater : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context) > expr->children[1]->evaluate(context);
}
};
class ExpressionEvaluatorTernary : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[expr->children[0]->evaluate(context) ? 1 : 2]->evaluate(context);
}
};
class ExpressionEvaluatorArray : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context)[expr->children[1]->evaluate(context)];
}
};
class ExpressionEvaluatorInvert : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return -expr->children[0]->evaluate(context);
}
};
class ExpressionEvaluatorConst : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *) const {
return ValuePtr(expr->const_value);
}
};
class ExpressionEvaluatorRange : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
ValuePtr v1 = expr->children[0]->evaluate(context);
if (v1->type() == Value::NUMBER) {
ValuePtr v2 = expr->children[1]->evaluate(context);
if (v2->type() == Value::NUMBER) {
if (expr->children.size() == 2) {
Value::RangeType range(v1->toDouble(), v2->toDouble());
return ValuePtr(range);
} else {
ValuePtr v3 = expr->children[2]->evaluate(context);
if (v3->type() == Value::NUMBER) {
Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
return ValuePtr(range);
}
}
}
}
return ValuePtr::undefined;
}
};
class ExpressionEvaluatorVector : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
Value::VectorType vec;
BOOST_FOREACH(const Expression *e, expr->children) {
vec.push_back(*(e->evaluate(context)));
}
return ValuePtr(vec);
}
};
class ExpressionEvaluatorLookup : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return context->lookup_variable(expr->var_name);
}
};
class ExpressionEvaluatorMember : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
ValuePtr v = expr->children[0]->evaluate(context);
if (v->type() == Value::VECTOR) {
if (expr->var_name == "x") return v[0];
if (expr->var_name == "y") return v[1];
if (expr->var_name == "z") return v[2];
} else if (v->type() == Value::RANGE) {
if (expr->var_name == "begin") return v[0];
if (expr->var_name == "step") return v[1];
if (expr->var_name == "end") return v[2];
}
return ValuePtr::undefined;
}
};
static void function_recursion_detected(const char *func)
{
PRINTB("ERROR: Recursion detected calling function '%s'", func);
} }
class ExpressionEvaluatorFunction : public ExpressionEvaluator Expression::Expression(const ValuePtr &val)
{ {
ValuePtr evaluate(const class Expression *expr, const class Context *context) const { const_value = val;
if (expr->recursioncount >= 1000) {
function_recursion_detected(expr->call_funcname.c_str());
// TO DO: throw function_recursion_detected();
return ValuePtr::undefined;
}
expr->recursioncount += 1;
EvalContext *c = new EvalContext(context, expr->call_arguments);
ValuePtr result = context->evaluate_function(expr->call_funcname, c);
delete c;
expr->recursioncount -= 1;
return result;
}
};
class ExpressionEvaluatorLet : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
Context c(context);
evaluate_sequential_assignment(expr->call_arguments, &c);
return expr->children[0]->evaluate(&c);
}
};
class ExpressionEvaluatorLcExpression : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
return expr->children[0]->evaluate(context);
}
};
class ExpressionEvaluatorLc : public ExpressionEvaluator
{
ValuePtr evaluate(const class Expression *expr, const class Context *context) const {
Value::VectorType vec;
if (expr->call_funcname == "if") {
if (expr->children[0]->evaluate(context)) {
if (expr->children[1]->type == EXPRESSION_TYPE_LC) {
return expr->children[1]->evaluate(context);
} else {
vec.push_back((*expr->children[1]->evaluate(context)));
}
}
return ValuePtr(vec);
} else if (expr->call_funcname == "for") {
EvalContext for_context(context, expr->call_arguments);
Context assign_context(context);
// comprehension for statements are by the parser reduced to only contain one single element
const std::string &it_name = for_context.getArgName(0);
ValuePtr it_values = for_context.getArgValue(0, &assign_context);
Context c(context);
if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps();
if (steps >= 1000000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it));
vec.push_back((*expr->children[0]->evaluate(&c)));
}
}
}
else if (it_values->type() == Value::VECTOR) {
for (size_t i = 0; i < it_values->toVector().size(); i++) {
c.set_variable(it_name, it_values->toVector()[i]);
vec.push_back((*expr->children[0]->evaluate(&c)));
}
}
else if (it_values->type() != Value::UNDEFINED) {
c.set_variable(it_name, it_values);
vec.push_back((*expr->children[0]->evaluate(&c)));
}
if (expr->children[0]->type == EXPRESSION_TYPE_LC) {
return ValuePtr(flatten(vec));
} else {
return ValuePtr(vec);
}
} else if (expr->call_funcname == "let") {
Context c(context);
evaluate_sequential_assignment(expr->call_arguments, &c);
return expr->children[0]->evaluate(&c);
} else {
abort();
}
}
};
ExpressionEvaluatorInit::ExpressionEvaluatorInit()
{
ExpressionEvaluator *abort = new ExpressionEvaluatorAbort();
for (int a = 0;a < 256;a++) {
Expression::evaluators[a] = abort;
}
Expression::evaluators[EXPRESSION_TYPE_NOT] = new ExpressionEvaluatorNot();
Expression::evaluators[EXPRESSION_TYPE_LOGICAL_AND] = new ExpressionEvaluatorLogicalAnd();
Expression::evaluators[EXPRESSION_TYPE_LOGICAL_OR] = new ExpressionEvaluatorLogicalOr();
Expression::evaluators[EXPRESSION_TYPE_MULTIPLY] = new ExpressionEvaluatorMultiply();
Expression::evaluators[EXPRESSION_TYPE_DIVISION] = new ExpressionEvaluatorDivision();
Expression::evaluators[EXPRESSION_TYPE_MODULO] = new ExpressionEvaluatorModulo();
Expression::evaluators[EXPRESSION_TYPE_PLUS] = new ExpressionEvaluatorPlus();
Expression::evaluators[EXPRESSION_TYPE_MINUS] = new ExpressionEvaluatorMinus();
Expression::evaluators[EXPRESSION_TYPE_LESS] = new ExpressionEvaluatorLess();
Expression::evaluators[EXPRESSION_TYPE_LESS_OR_EQUAL] = new ExpressionEvaluatorLessOrEqual();
Expression::evaluators[EXPRESSION_TYPE_EQUAL] = new ExpressionEvaluatorEqual();
Expression::evaluators[EXPRESSION_TYPE_NOT_EQUAL] = new ExpressionEvaluatorNotEqual();
Expression::evaluators[EXPRESSION_TYPE_GREATER_OR_EQUAL] = new ExpressionEvaluatorGreaterOrEqual();
Expression::evaluators[EXPRESSION_TYPE_GREATER] = new ExpressionEvaluatorGreater();
Expression::evaluators[EXPRESSION_TYPE_TERNARY] = new ExpressionEvaluatorTernary();
Expression::evaluators[EXPRESSION_TYPE_ARRAY_ACCESS] = new ExpressionEvaluatorArray();
Expression::evaluators[EXPRESSION_TYPE_INVERT] = new ExpressionEvaluatorInvert();
Expression::evaluators[EXPRESSION_TYPE_CONST] = new ExpressionEvaluatorConst();
Expression::evaluators[EXPRESSION_TYPE_RANGE] = new ExpressionEvaluatorRange();
Expression::evaluators[EXPRESSION_TYPE_VECTOR] = new ExpressionEvaluatorVector();
Expression::evaluators[EXPRESSION_TYPE_LOOKUP] = new ExpressionEvaluatorLookup();
Expression::evaluators[EXPRESSION_TYPE_MEMBER] = new ExpressionEvaluatorMember();
Expression::evaluators[EXPRESSION_TYPE_FUNCTION] = new ExpressionEvaluatorFunction();
Expression::evaluators[EXPRESSION_TYPE_LET] = new ExpressionEvaluatorLet();
Expression::evaluators[EXPRESSION_TYPE_LC_EXPRESSION] = new ExpressionEvaluatorLcExpression();
Expression::evaluators[EXPRESSION_TYPE_LC] = new ExpressionEvaluatorLc();
} }
Expression::Expression(const unsigned char type) : recursioncount(0) Expression::Expression(const std::string &val)
{ {
setType(type); var_name = val;
} }
Expression::Expression(const unsigned char type, Expression *left, Expression *right) Expression::Expression(const std::string &val, Expression *expr)
: recursioncount(0)
{ {
setType(type); var_name = val;
this->children.push_back(left); children.push_back(expr);
this->children.push_back(right); first = expr;
} }
Expression::Expression(const unsigned char type, Expression *expr) Expression::Expression(Expression *expr)
: recursioncount(0)
{ {
setType(type); children.push_back(expr);
this->children.push_back(expr); first = expr;
} }
Expression::Expression(const ValuePtr &val) : const_value(val), recursioncount(0) Expression::Expression(Expression *left, Expression *right)
{ {
setType(EXPRESSION_TYPE_CONST); children.push_back(left);
children.push_back(right);
first = left;
second = right;
}
Expression::Expression(Expression *expr1, Expression *expr2, Expression *expr3)
{
children.push_back(expr1);
children.push_back(expr2);
children.push_back(expr3);
first = expr1;
second = expr2;
third = expr3;
} }
Expression::~Expression() Expression::~Expression()
@ -430,20 +116,6 @@ Expression::~Expression()
std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>()); std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
} }
void Expression::setType(const unsigned char type)
{
this->type = type;
this->evaluator = evaluators[type];
}
ValuePtr Expression::evaluate(const Context *context) const
{
char _c;
context->checkStack(&_c);
return evaluator->evaluate(this, context);
}
namespace /* anonymous*/ { namespace /* anonymous*/ {
std::ostream &operator << (std::ostream &o, AssignmentList const& l) { std::ostream &operator << (std::ostream &o, AssignmentList const& l) {
@ -458,10 +130,15 @@ namespace /* anonymous*/ {
} }
bool Expression::isListComprehension()
{
return false;
}
std::string Expression::toString() const std::string Expression::toString() const
{ {
std::stringstream stream; std::stringstream stream;
/*
switch (this->type) { switch (this->type) {
case EXPRESSION_TYPE_MULTIPLY: case EXPRESSION_TYPE_MULTIPLY:
case EXPRESSION_TYPE_DIVISION: case EXPRESSION_TYPE_DIVISION:
@ -561,9 +238,361 @@ std::string Expression::toString() const
assert(false && "Illegal expression type"); assert(false && "Illegal expression type");
break; break;
} }
*/
return stream.str(); return stream.str();
} }
ExpressionNot::ExpressionNot(Expression *expr) : Expression(expr)
{
}
ValuePtr ExpressionNot::evaluate(const Context *context) const
{
return !first->evaluate(context);
}
ExpressionLogicalAnd::ExpressionLogicalAnd(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionLogicalAnd::evaluate(const Context *context) const
{
return this->first->evaluate(context) && this->second->evaluate(context);
}
ExpressionLogicalOr::ExpressionLogicalOr(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionLogicalOr::evaluate(const Context *context) const
{
return this->first->evaluate(context) || this->second->evaluate(context);
}
ExpressionMultiply::ExpressionMultiply(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionMultiply::evaluate(const Context *context) const
{
return this->first->evaluate(context) * this->second->evaluate(context);
}
ExpressionDivision::ExpressionDivision(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionDivision::evaluate(const Context *context) const
{
return this->first->evaluate(context) / this->second->evaluate(context);
}
ExpressionModulo::ExpressionModulo(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionModulo::evaluate(const Context *context) const
{
return this->first->evaluate(context) % this->second->evaluate(context);
}
ExpressionPlus::ExpressionPlus(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionPlus::evaluate(const Context *context) const
{
return this->first->evaluate(context) + this->second->evaluate(context);
}
ExpressionMinus::ExpressionMinus(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionMinus::evaluate(const Context *context) const
{
return this->first->evaluate(context) - this->second->evaluate(context);
}
ExpressionLess::ExpressionLess(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionLess::evaluate(const Context *context) const
{
return this->first->evaluate(context) < this->second->evaluate(context);
}
ExpressionLessOrEqual::ExpressionLessOrEqual(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionLessOrEqual::evaluate(const Context *context) const
{
return this->first->evaluate(context) <= this->second->evaluate(context);
}
ExpressionEqual::ExpressionEqual(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionEqual::evaluate(const Context *context) const
{
return this->first->evaluate(context) == this->second->evaluate(context);
}
ExpressionNotEqual::ExpressionNotEqual(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionNotEqual::evaluate(const Context *context) const
{
return this->first->evaluate(context) != this->second->evaluate(context);
}
ExpressionGreaterOrEqual::ExpressionGreaterOrEqual(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionGreaterOrEqual::evaluate(const Context *context) const
{
return this->first->evaluate(context) >= this->second->evaluate(context);
}
ExpressionGreater::ExpressionGreater(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionGreater::evaluate(const Context *context) const
{
return this->first->evaluate(context) > this->second->evaluate(context);
}
ExpressionTernary::ExpressionTernary(Expression *expr1, Expression *expr2, Expression *expr3) : Expression(expr1, expr2, expr3)
{
}
ValuePtr ExpressionTernary::evaluate(const Context *context) const
{
return (this->first->evaluate(context) ? this->second : this->third)->evaluate(context);
}
ExpressionArray::ExpressionArray(Expression *left, Expression *right) : Expression(left, right)
{
}
ValuePtr ExpressionArray::evaluate(const Context *context) const {
return this->first->evaluate(context)[this->second->evaluate(context)];
}
ExpressionInvert::ExpressionInvert(Expression *expr) : Expression(expr)
{
}
ValuePtr ExpressionInvert::evaluate(const Context *context) const
{
return -this->first->evaluate(context);
}
ExpressionConst::ExpressionConst(const ValuePtr &val) : Expression(val)
{
}
ValuePtr ExpressionConst::evaluate(const class Context *) const
{
return ValuePtr(this->const_value);
}
ExpressionRange::ExpressionRange(Expression *expr1, Expression *expr2) : Expression(expr1, expr2)
{
}
ExpressionRange::ExpressionRange(Expression *expr1, Expression *expr2, Expression *expr3) : Expression(expr1, expr2, expr3)
{
}
ValuePtr ExpressionRange::evaluate(const Context *context) const
{
ValuePtr v1 = this->first->evaluate(context);
if (v1->type() == Value::NUMBER) {
ValuePtr v2 = this->second->evaluate(context);
if (v2->type() == Value::NUMBER) {
if (this->children.size() == 2) {
Value::RangeType range(v1->toDouble(), v2->toDouble());
return ValuePtr(range);
} else {
ValuePtr v3 = this->third->evaluate(context);
if (v3->type() == Value::NUMBER) {
Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
return ValuePtr(range);
}
}
}
}
return ValuePtr::undefined;
}
ExpressionVector::ExpressionVector(Expression *expr) : Expression(expr)
{
}
ValuePtr ExpressionVector::evaluate(const Context *context) const
{
Value::VectorType vec;
BOOST_FOREACH(const Expression *e, this->children) {
vec.push_back(*(e->evaluate(context)));
}
return ValuePtr(vec);
}
ExpressionLookup::ExpressionLookup(const std::string &val) : Expression(val)
{
}
ValuePtr ExpressionLookup::evaluate(const Context *context) const
{
return context->lookup_variable(this->var_name);
}
ExpressionMember::ExpressionMember(const std::string &val, Expression *expr) : Expression(val, expr)
{
}
ValuePtr ExpressionMember::evaluate(const Context *context) const
{
ValuePtr v = this->first->evaluate(context);
if (v->type() == Value::VECTOR) {
if (this->var_name == "x") return v[0];
if (this->var_name == "y") return v[1];
if (this->var_name == "z") return v[2];
} else if (v->type() == Value::RANGE) {
if (this->var_name == "begin") return v[0];
if (this->var_name == "step") return v[1];
if (this->var_name == "end") return v[2];
}
return ValuePtr::undefined;
}
static void function_recursion_detected(const char *func)
{
PRINTB("ERROR: Recursion detected calling function '%s'", func);
}
ExpressionFunction::ExpressionFunction()
{
}
ValuePtr ExpressionFunction::evaluate(const Context *context) const
{
if (StackCheck::inst()->check()) {
function_recursion_detected(this->call_funcname.c_str());
// TO DO: throw function_recursion_detected();
return ValuePtr::undefined;
}
EvalContext *c = new EvalContext(context, this->call_arguments);
ValuePtr result = context->evaluate_function(this->call_funcname, c);
delete c;
return result;
}
ExpressionLet::ExpressionLet()
{
}
ValuePtr ExpressionLet::evaluate(const Context *context) const
{
Context c(context);
evaluate_sequential_assignment(this->call_arguments, &c);
return this->children[0]->evaluate(&c);
}
ExpressionLcExpression::ExpressionLcExpression(Expression *expr) : Expression(expr)
{
}
ValuePtr ExpressionLcExpression::evaluate(const Context *context) const
{
return this->children[0]->evaluate(context);
}
ExpressionLc::ExpressionLc(Expression *expr) : Expression(expr)
{
}
ExpressionLc::ExpressionLc(Expression *expr1, Expression *expr2) : Expression(expr1, expr2)
{
}
bool ExpressionLc::isListComprehension()
{
return true;
}
ValuePtr ExpressionLc::evaluate(const Context *context) const
{
Value::VectorType vec;
if (this->call_funcname == "if") {
if (this->children[0]->evaluate(context)) {
if (this->children[1]->isListComprehension()) {
return this->children[1]->evaluate(context);
} else {
vec.push_back((*this->children[1]->evaluate(context)));
}
}
return ValuePtr(vec);
} else if (this->call_funcname == "for") {
EvalContext for_context(context, this->call_arguments);
Context assign_context(context);
// comprehension for statements are by the parser reduced to only contain one single element
const std::string &it_name = for_context.getArgName(0);
ValuePtr it_values = for_context.getArgValue(0, &assign_context);
Context c(context);
if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps();
if (steps >= 1000000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it));
vec.push_back((*this->children[0]->evaluate(&c)));
}
}
}
else if (it_values->type() == Value::VECTOR) {
for (size_t i = 0; i < it_values->toVector().size(); i++) {
c.set_variable(it_name, it_values->toVector()[i]);
vec.push_back((*this->children[0]->evaluate(&c)));
}
}
else if (it_values->type() != Value::UNDEFINED) {
c.set_variable(it_name, it_values);
vec.push_back((*this->children[0]->evaluate(&c)));
}
if (this->children[0]->isListComprehension()) {
return ValuePtr(flatten(vec));
} else {
return ValuePtr(vec);
}
} else if (this->call_funcname == "let") {
Context c(context);
evaluate_sequential_assignment(this->call_arguments, &c);
return this->children[0]->evaluate(&c);
} else {
abort();
}
}
std::ostream &operator<<(std::ostream &stream, const Expression &expr) std::ostream &operator<<(std::ostream &stream, const Expression &expr)
{ {
stream << expr.toString(); stream << expr.toString();

View File

@ -5,49 +5,13 @@
#include "value.h" #include "value.h"
#include "typedefs.h" #include "typedefs.h"
#define EXPRESSION_TYPE_NOT ('!')
#define EXPRESSION_TYPE_LOGICAL_AND ('&')
#define EXPRESSION_TYPE_LOGICAL_OR ('|')
#define EXPRESSION_TYPE_MULTIPLY ('*')
#define EXPRESSION_TYPE_DIVISION ('/')
#define EXPRESSION_TYPE_MODULO ('%')
#define EXPRESSION_TYPE_PLUS ('+')
#define EXPRESSION_TYPE_MINUS ('-')
#define EXPRESSION_TYPE_LESS ('<')
#define EXPRESSION_TYPE_LESS_OR_EQUAL ('0')
#define EXPRESSION_TYPE_EQUAL ('=')
#define EXPRESSION_TYPE_NOT_EQUAL ('1')
#define EXPRESSION_TYPE_GREATER_OR_EQUAL ('2')
#define EXPRESSION_TYPE_GREATER ('>')
#define EXPRESSION_TYPE_TERNARY ('?')
#define EXPRESSION_TYPE_ARRAY_ACCESS ('[')
#define EXPRESSION_TYPE_INVERT ('I')
#define EXPRESSION_TYPE_CONST ('C')
#define EXPRESSION_TYPE_RANGE ('R')
#define EXPRESSION_TYPE_VECTOR ('V')
#define EXPRESSION_TYPE_LOOKUP ('L')
#define EXPRESSION_TYPE_MEMBER ('N')
#define EXPRESSION_TYPE_FUNCTION ('F')
#define EXPRESSION_TYPE_LET ('l')
#define EXPRESSION_TYPE_LC_EXPRESSION ('i')
#define EXPRESSION_TYPE_LC ('c')
class ExpressionEvaluator
{
public:
virtual ValuePtr evaluate(const class Expression *expr, const class Context *context) const = 0;
};
class ExpressionEvaluatorInit
{
public:
ExpressionEvaluatorInit();
};
class Expression class Expression
{ {
public: public:
std::vector<Expression*> children; std::vector<Expression*> children;
Expression *first;
Expression *second;
Expression *third;
ValuePtr const_value; ValuePtr const_value;
std::string var_name; std::string var_name;
@ -55,45 +19,204 @@ public:
std::string call_funcname; std::string call_funcname;
AssignmentList call_arguments; AssignmentList call_arguments;
Expression();
Expression(const ValuePtr &val); Expression(const ValuePtr &val);
Expression(const unsigned char type); Expression(const std::string &val);
Expression(const unsigned char type, Expression *left, Expression *right); Expression(const std::string &val, Expression *expr);
Expression(const unsigned char type, Expression *expr); Expression(Expression *expr);
~Expression(); Expression(Expression *left, Expression *right);
Expression(Expression *expr1, Expression *expr2, Expression *expr3);
virtual ~Expression();
void setType(const unsigned char type); virtual bool isListComprehension();
ValuePtr evaluate(const class Context *context) const; virtual ValuePtr evaluate(const class Context *context) const = 0;
std::string toString() const; std::string toString() const;
private:
// Boolean: ! && ||
// Operators: * / % + -
// Relations: < <= == != >= >
// Vector element: []
// Condition operator: ?:
// Invert (prefix '-'): I
// Constant value: C
// Create Range: R
// Create Vector: V
// Create Matrix: M
// Lookup Variable: L
// Lookup member per name: N
// Function call: F
// Let expression: l
// List comprehension expression: i
// List comprehension: c
unsigned char type;
ExpressionEvaluator *evaluator;
mutable int recursioncount;
static ExpressionEvaluator *evaluators[256];
static ExpressionEvaluatorInit evaluatorInit;
friend class ExpressionEvaluatorInit;
friend class ExpressionEvaluatorLc; // for type
friend class ExpressionEvaluatorFunction; // for recursioncount
}; };
std::ostream &operator<<(std::ostream &stream, const Expression &expr); std::ostream &operator<<(std::ostream &stream, const Expression &expr);
class ExpressionNot : public Expression
{
public:
ExpressionNot(Expression *expr);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLogicalAnd : public Expression
{
public:
ExpressionLogicalAnd(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLogicalOr : public Expression
{
public:
ExpressionLogicalOr(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionMultiply : public Expression
{
public:
ExpressionMultiply(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionDivision : public Expression
{
public:
ExpressionDivision(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionModulo : public Expression
{
public:
ExpressionModulo(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionPlus : public Expression
{
public:
ExpressionPlus(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionMinus : public Expression
{
public:
ExpressionMinus(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLess : public Expression
{
public:
ExpressionLess(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLessOrEqual : public Expression
{
public:
ExpressionLessOrEqual(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionEqual : public Expression
{
public:
ExpressionEqual(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionNotEqual : public Expression
{
public:
ExpressionNotEqual(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionGreaterOrEqual : public Expression
{
public:
ExpressionGreaterOrEqual(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionGreater : public Expression
{
public:
ExpressionGreater(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionTernary : public Expression
{
public:
ExpressionTernary(Expression *expr1, Expression *expr2, Expression *expr3);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionArray : public Expression
{
public:
ExpressionArray(Expression *left, Expression *right);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionInvert : public Expression
{
public:
ExpressionInvert(Expression *expr);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionConst : public Expression
{
public:
ExpressionConst(const ValuePtr &val);
ValuePtr evaluate(const class Context *) const;
};
class ExpressionRange : public Expression
{
public:
ExpressionRange(Expression *expr1, Expression *expr2);
ExpressionRange(Expression *expr1, Expression *expr2, Expression *expr3);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionVector : public Expression
{
public:
ExpressionVector(Expression *expr);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLookup : public Expression
{
public:
ExpressionLookup(const std::string &val);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionMember : public Expression
{
public:
ExpressionMember(const std::string &val, Expression *expr);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionFunction : public Expression
{
public:
ExpressionFunction();
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLet : public Expression
{
public:
ExpressionLet();
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLcExpression : public Expression
{
public:
ExpressionLcExpression(Expression *expr);
ValuePtr evaluate(const class Context *context) const;
};
class ExpressionLc : public Expression
{
bool isListComprehension();
public:
ExpressionLc(Expression *expr);
ExpressionLc(Expression *expr1, Expression *expr2);
ValuePtr evaluate(const class Context *context) const;
};

View File

@ -35,6 +35,7 @@
#include <algorithm> #include <algorithm>
#include "stl-utils.h" #include "stl-utils.h"
#include "printutils.h" #include "printutils.h"
#include "stackcheck.h"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/math/special_functions/fpclassify.hpp> #include <boost/math/special_functions/fpclassify.hpp>
@ -88,21 +89,14 @@ Function::~Function()
delete expr; delete expr;
} }
static const char *txt = "stack usage: ";
ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
{ {
char _c;
bool set = ctx->setStack(&_c);
if (!expr) return ValuePtr::undefined; if (!expr) return ValuePtr::undefined;
Context *c = new Context(ctx); Context *c = new Context(ctx);
c->setVariables(definition_arguments, evalctx); c->setVariables(definition_arguments, evalctx);
ValuePtr result = expr->evaluate(c); ValuePtr result = expr->evaluate(c);
delete c; delete c;
if (set) {
std::cout << txt << ctx->stackUsage() << std::endl;
}
return result; return result;
} }

View File

@ -39,6 +39,7 @@
#include "PlatformUtils.h" #include "PlatformUtils.h"
#include "LibraryInfo.h" #include "LibraryInfo.h"
#include "nodedumper.h" #include "nodedumper.h"
#include "stackcheck.h"
#include "CocoaUtils.h" #include "CocoaUtils.h"
#include <string> #include <string>
@ -655,6 +656,8 @@ int main(int argc, char **argv)
{ {
int rc = 0; int rc = 0;
bool isGuiLaunched = getenv("GUI_LAUNCHED") != 0; bool isGuiLaunched = getenv("GUI_LAUNCHED") != 0;
StackCheck::inst()->init();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
if (isGuiLaunched) set_output_handler(CocoaUtils::nslog, NULL); if (isGuiLaunched) set_output_handler(CocoaUtils::nslog, NULL);
#else #else

View File

@ -308,65 +308,57 @@ single_module_instantiation:
expr: expr:
TOK_TRUE TOK_TRUE
{ {
$$ = new Expression(ValuePtr(true)); $$ = new ExpressionConst(ValuePtr(true));
} }
| TOK_FALSE | TOK_FALSE
{ {
$$ = new Expression(ValuePtr(false)); $$ = new ExpressionConst(ValuePtr(false));
} }
| TOK_UNDEF | TOK_UNDEF
{ {
$$ = new Expression(ValuePtr::undefined); $$ = new ExpressionConst(ValuePtr::undefined);
} }
| TOK_ID | TOK_ID
{ {
$$ = new Expression(EXPRESSION_TYPE_LOOKUP); $$ = new ExpressionLookup($1);
$$->var_name = $1;
free($1); free($1);
} }
| expr '.' TOK_ID | expr '.' TOK_ID
{ {
$$ = new Expression(EXPRESSION_TYPE_MEMBER, $1); $$ = new ExpressionMember($3, $1);
$$->var_name = $3;
free($3); free($3);
} }
| TOK_STRING | TOK_STRING
{ {
$$ = new Expression(ValuePtr(std::string($1))); $$ = new ExpressionConst(ValuePtr(std::string($1)));
free($1); free($1);
} }
| TOK_NUMBER | TOK_NUMBER
{ {
$$ = new Expression(ValuePtr($1)); $$ = new ExpressionConst(ValuePtr($1));
} }
| TOK_LET '(' arguments_call ')' expr %prec LET | TOK_LET '(' arguments_call ')' expr %prec LET
{ {
$$ = new Expression(EXPRESSION_TYPE_LET); $$ = new ExpressionLet();
$$->call_arguments = *$3; $$->call_arguments = *$3;
delete $3; delete $3;
$$->children.push_back($5); $$->children.push_back($5);
} }
| '[' expr ':' expr ']' | '[' expr ':' expr ']'
{ {
$$ = new Expression(EXPRESSION_TYPE_RANGE); $$ = new ExpressionRange($2, $4);
$$->children.push_back($2);
$$->children.push_back($4);
} }
| '[' expr ':' expr ':' expr ']' | '[' expr ':' expr ':' expr ']'
{ {
$$ = new Expression(EXPRESSION_TYPE_RANGE); $$ = new ExpressionRange($2, $4, $6);
$$->children.push_back($2);
$$->children.push_back($4);
$$->children.push_back($6);
} }
| '[' list_comprehension_elements ']' | '[' list_comprehension_elements ']'
{ {
$$ = new Expression(EXPRESSION_TYPE_LC_EXPRESSION); $$ = new ExpressionLcExpression($2);
$$->children.push_back($2);
} }
| '[' optional_commas ']' | '[' optional_commas ']'
{ {
$$ = new Expression(ValuePtr(Value::VectorType())); $$ = new ExpressionConst(ValuePtr(Value::VectorType()));
} }
| '[' vector_expr optional_commas ']' | '[' vector_expr optional_commas ']'
{ {
@ -374,55 +366,55 @@ expr:
} }
| expr '*' expr | expr '*' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_MULTIPLY, $1, $3); $$ = new ExpressionMultiply($1, $3);
} }
| expr '/' expr | expr '/' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_DIVISION, $1, $3); $$ = new ExpressionDivision($1, $3);
} }
| expr '%' expr | expr '%' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_MODULO, $1, $3); $$ = new ExpressionModulo($1, $3);
} }
| expr '+' expr | expr '+' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_PLUS, $1, $3); $$ = new ExpressionPlus($1, $3);
} }
| expr '-' expr | expr '-' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_MINUS, $1, $3); $$ = new ExpressionMinus($1, $3);
} }
| expr '<' expr | expr '<' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_LESS, $1, $3); $$ = new ExpressionLess($1, $3);
} }
| expr LE expr | expr LE expr
{ {
$$ = new Expression(EXPRESSION_TYPE_LESS_OR_EQUAL, $1, $3); $$ = new ExpressionLessOrEqual($1, $3);
} }
| expr EQ expr | expr EQ expr
{ {
$$ = new Expression(EXPRESSION_TYPE_EQUAL, $1, $3); $$ = new ExpressionEqual($1, $3);
} }
| expr NE expr | expr NE expr
{ {
$$ = new Expression(EXPRESSION_TYPE_NOT_EQUAL, $1, $3); $$ = new ExpressionNotEqual($1, $3);
} }
| expr GE expr | expr GE expr
{ {
$$ = new Expression(EXPRESSION_TYPE_GREATER_OR_EQUAL, $1, $3); $$ = new ExpressionGreaterOrEqual($1, $3);
} }
| expr '>' expr | expr '>' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_GREATER, $1, $3); $$ = new ExpressionGreater($1, $3);
} }
| expr AND expr | expr AND expr
{ {
$$ = new Expression(EXPRESSION_TYPE_LOGICAL_AND, $1, $3); $$ = new ExpressionLogicalAnd($1, $3);
} }
| expr OR expr | expr OR expr
{ {
$$ = new Expression(EXPRESSION_TYPE_LOGICAL_OR, $1, $3); $$ = new ExpressionLogicalOr($1, $3);
} }
| '+' expr | '+' expr
{ {
@ -430,11 +422,11 @@ expr:
} }
| '-' expr | '-' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_INVERT, $2); $$ = new ExpressionInvert($2);
} }
| '!' expr | '!' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_NOT, $2); $$ = new ExpressionNot($2);
} }
| '(' expr ')' | '(' expr ')'
{ {
@ -442,18 +434,15 @@ expr:
} }
| expr '?' expr ':' expr | expr '?' expr ':' expr
{ {
$$ = new Expression(EXPRESSION_TYPE_TERNARY); $$ = new ExpressionTernary($1, $3, $5);
$$->children.push_back($1);
$$->children.push_back($3);
$$->children.push_back($5);
} }
| expr '[' expr ']' | expr '[' expr ']'
{ {
$$ = new Expression(EXPRESSION_TYPE_ARRAY_ACCESS, $1, $3); $$ = new ExpressionArray($1, $3);
} }
| TOK_ID '(' arguments_call ')' | TOK_ID '(' arguments_call ')'
{ {
$$ = new Expression(EXPRESSION_TYPE_FUNCTION); $$ = new ExpressionFunction();
$$->call_funcname = $1; $$->call_funcname = $1;
$$->call_arguments = *$3; $$->call_arguments = *$3;
free($1); free($1);
@ -466,7 +455,7 @@ list_comprehension_elements:
be parsed as an expression) */ be parsed as an expression) */
TOK_LET '(' arguments_call ')' list_comprehension_elements TOK_LET '(' arguments_call ')' list_comprehension_elements
{ {
$$ = new Expression(EXPRESSION_TYPE_LC, $5); $$ = new ExpressionLc($5);
$$->call_funcname = "let"; $$->call_funcname = "let";
$$->call_arguments = *$3; $$->call_arguments = *$3;
delete $3; delete $3;
@ -477,7 +466,7 @@ list_comprehension_elements:
/* transform for(i=...,j=...) -> for(i=...) for(j=...) */ /* transform for(i=...,j=...) -> for(i=...) for(j=...) */
for (int i = $3->size()-1; i >= 0; i--) { for (int i = $3->size()-1; i >= 0; i--) {
Expression *e = new Expression(EXPRESSION_TYPE_LC, $$); Expression *e = new ExpressionLc($$);
e->call_funcname = "for"; e->call_funcname = "for";
e->call_arguments.push_back((*$3)[i]); e->call_arguments.push_back((*$3)[i]);
$$ = e; $$ = e;
@ -486,7 +475,7 @@ list_comprehension_elements:
} }
| TOK_IF '(' expr ')' list_comprehension_elements_or_expr | TOK_IF '(' expr ')' list_comprehension_elements_or_expr
{ {
$$ = new Expression(EXPRESSION_TYPE_LC, $3, $5); $$ = new ExpressionLc($3, $5);
$$->call_funcname = "if"; $$->call_funcname = "if";
} }
; ;
@ -504,7 +493,7 @@ optional_commas:
vector_expr: vector_expr:
expr expr
{ {
$$ = new Expression(EXPRESSION_TYPE_VECTOR, $1); $$ = new ExpressionVector($1);
} }
| vector_expr ',' optional_commas expr | vector_expr ',' optional_commas expr
{ {