mirror of https://github.com/vitalif/openscad
Use class hierarchy for the different types of expressions.
parent
756f8079d8
commit
dc8f559b85
|
@ -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()
|
||||
|
|
743
src/expr.cc
743
src/expr.cc
|
@ -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();
|
||||
|
|
271
src/expression.h
271
src/expression.h
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
79
src/parser.y
79
src/parser.y
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue