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()
{
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(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("$fa", boost::shared_ptr<Expression>(new Expression(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("$fn", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.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 ExpressionConst(ValuePtr(12.0)))));
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
Value::VectorType zero3;
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
ValuePtr zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(ValuePtr(500)))));
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 ExpressionConst(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(500)))));
}
Builtins::~Builtins()

View File

@ -23,7 +23,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "expression.h"
#include "value.h"
#include "evalcontext.h"
@ -32,14 +31,10 @@
#include <algorithm>
#include "stl-utils.h"
#include "printutils.h"
#include "stackcheck.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
ExpressionEvaluator * Expression::evaluators[256];
// static initializer for the expression evaluator lookup table
ExpressionEvaluatorInit Expression::evaluatorInit;
// unnamed namespace
namespace {
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 {
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();
const_value = val;
}
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)
: recursioncount(0)
Expression::Expression(const std::string &val, Expression *expr)
{
setType(type);
this->children.push_back(left);
this->children.push_back(right);
var_name = val;
children.push_back(expr);
first = expr;
}
Expression::Expression(const unsigned char type, Expression *expr)
: recursioncount(0)
Expression::Expression(Expression *expr)
{
setType(type);
this->children.push_back(expr);
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()
@ -430,20 +116,6 @@ Expression::~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*/ {
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::stringstream stream;
/*
switch (this->type) {
case EXPRESSION_TYPE_MULTIPLY:
case EXPRESSION_TYPE_DIVISION:
@ -561,9 +238,361 @@ std::string Expression::toString() const
assert(false && "Illegal expression type");
break;
}
*/
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)
{
stream << expr.toString();

View File

@ -5,49 +5,13 @@
#include "value.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
{
public:
std::vector<Expression*> children;
Expression *first;
Expression *second;
Expression *third;
ValuePtr const_value;
std::string var_name;
@ -55,45 +19,204 @@ public:
std::string call_funcname;
AssignmentList call_arguments;
Expression();
Expression(const ValuePtr &val);
Expression(const unsigned char type);
Expression(const unsigned char type, Expression *left, Expression *right);
Expression(const unsigned char type, Expression *expr);
~Expression();
Expression(const std::string &val);
Expression(const std::string &val, Expression *expr);
Expression(Expression *expr);
Expression(Expression *left, Expression *right);
Expression(Expression *expr1, Expression *expr2, Expression *expr3);
virtual ~Expression();
void setType(const unsigned char type);
ValuePtr evaluate(const class Context *context) const;
virtual bool isListComprehension();
virtual ValuePtr evaluate(const class Context *context) const = 0;
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);
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 "stl-utils.h"
#include "printutils.h"
#include "stackcheck.h"
#include <boost/foreach.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
@ -88,21 +89,14 @@ Function::~Function()
delete expr;
}
static const char *txt = "stack usage: ";
ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
{
char _c;
bool set = ctx->setStack(&_c);
if (!expr) return ValuePtr::undefined;
Context *c = new Context(ctx);
c->setVariables(definition_arguments, evalctx);
ValuePtr result = expr->evaluate(c);
delete c;
if (set) {
std::cout << txt << ctx->stackUsage() << std::endl;
}
return result;
}

View File

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

View File

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