mirror of https://github.com/vitalif/openscad
Some Expression refactoring
parent
74475395f4
commit
2e8d93d5be
135
src/expr.cc
135
src/expr.cc
|
@ -67,49 +67,27 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
Expression::Expression()
|
||||
Expression::Expression() : first(NULL), second(NULL), third(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Expression(const ValuePtr &val)
|
||||
{
|
||||
const_value = val;
|
||||
}
|
||||
|
||||
Expression::Expression(const std::string &val)
|
||||
{
|
||||
var_name = val;
|
||||
}
|
||||
|
||||
Expression::Expression(const std::string &val, Expression *expr)
|
||||
{
|
||||
var_name = val;
|
||||
children.push_back(expr);
|
||||
first = expr;
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *expr)
|
||||
Expression::Expression(Expression *expr) : first(expr), second(NULL), third(NULL)
|
||||
{
|
||||
children.push_back(expr);
|
||||
first = expr;
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *left, Expression *right)
|
||||
Expression::Expression(Expression *left, Expression *right) : first(left), second(right), third(NULL)
|
||||
{
|
||||
children.push_back(left);
|
||||
children.push_back(right);
|
||||
first = left;
|
||||
second = right;
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *expr1, Expression *expr2, Expression *expr3)
|
||||
: first(expr1), second(expr2), third(expr3)
|
||||
{
|
||||
children.push_back(expr1);
|
||||
children.push_back(expr2);
|
||||
children.push_back(expr3);
|
||||
first = expr1;
|
||||
second = expr2;
|
||||
third = expr3;
|
||||
}
|
||||
|
||||
Expression::~Expression()
|
||||
|
@ -373,7 +351,7 @@ void ExpressionInvert::print(std::ostream &stream) const
|
|||
stream << "-" << *first;
|
||||
}
|
||||
|
||||
ExpressionConst::ExpressionConst(const ValuePtr &val) : Expression(val)
|
||||
ExpressionConst::ExpressionConst(const ValuePtr &val) : const_value(val)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -446,7 +424,7 @@ void ExpressionVector::print(std::ostream &stream) const
|
|||
stream << "]";
|
||||
}
|
||||
|
||||
ExpressionLookup::ExpressionLookup(const std::string &val) : Expression(val)
|
||||
ExpressionLookup::ExpressionLookup(const std::string &var_name) : var_name(var_name)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -460,7 +438,8 @@ void ExpressionLookup::print(std::ostream &stream) const
|
|||
stream << this->var_name;
|
||||
}
|
||||
|
||||
ExpressionMember::ExpressionMember(const std::string &val, Expression *expr) : Expression(val, expr)
|
||||
ExpressionMember::ExpressionMember(Expression *expr, const std::string &member)
|
||||
: Expression(expr), member(member)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -469,44 +448,47 @@ 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];
|
||||
if (this->member == "x") return v[0];
|
||||
if (this->member == "y") return v[1];
|
||||
if (this->member == "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];
|
||||
if (this->member == "begin") return v[0];
|
||||
if (this->member == "step") return v[1];
|
||||
if (this->member == "end") return v[2];
|
||||
}
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
void ExpressionMember::print(std::ostream &stream) const
|
||||
{
|
||||
stream << *first << "." << this->var_name;
|
||||
stream << *first << "." << this->member;
|
||||
}
|
||||
|
||||
ExpressionFunction::ExpressionFunction()
|
||||
ExpressionFunctionCall::ExpressionFunctionCall(const std::string &funcname,
|
||||
const AssignmentList &arglist)
|
||||
: funcname(funcname), call_arguments(arglist)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionFunction::evaluate(const Context *context) const
|
||||
ValuePtr ExpressionFunctionCall::evaluate(const Context *context) const
|
||||
{
|
||||
if (StackCheck::inst()->check()) {
|
||||
throw RecursionException("function", call_funcname);
|
||||
throw RecursionException("function", funcname);
|
||||
}
|
||||
|
||||
EvalContext c(context, this->call_arguments);
|
||||
ValuePtr result = context->evaluate_function(this->call_funcname, &c);
|
||||
ValuePtr result = context->evaluate_function(this->funcname, &c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExpressionFunction::print(std::ostream &stream) const
|
||||
void ExpressionFunctionCall::print(std::ostream &stream) const
|
||||
{
|
||||
stream << this->call_funcname << "(" << this->call_arguments << ")";
|
||||
stream << this->funcname << "(" << this->call_arguments << ")";
|
||||
}
|
||||
|
||||
ExpressionLet::ExpressionLet(Expression *expr) : Expression(expr)
|
||||
ExpressionLet::ExpressionLet(const AssignmentList &arglist, Expression *expr)
|
||||
: Expression(expr), call_arguments(arglist)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -515,7 +497,7 @@ ValuePtr ExpressionLet::evaluate(const Context *context) const
|
|||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
|
||||
return this->children[0]->evaluate(&c);
|
||||
return this->first->evaluate(&c);
|
||||
}
|
||||
|
||||
void ExpressionLet::print(std::ostream &stream) const
|
||||
|
@ -529,38 +511,23 @@ ExpressionLcExpression::ExpressionLcExpression(Expression *expr) : Expression(ex
|
|||
|
||||
ValuePtr ExpressionLcExpression::evaluate(const Context *context) const
|
||||
{
|
||||
return this->children[0]->evaluate(context);
|
||||
return this->first->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionLcExpression::print(std::ostream &stream) const
|
||||
{
|
||||
Expression const* c = this->first;
|
||||
|
||||
stream << "[";
|
||||
|
||||
do {
|
||||
if (c->call_funcname == "for") {
|
||||
stream << "for(" << c->call_arguments << ") ";
|
||||
c = c->children[0];
|
||||
} else if (c->call_funcname == "if") {
|
||||
stream << "if(" << c->children[0] << ") ";
|
||||
c = c->children[1];
|
||||
} else if (c->call_funcname == "let") {
|
||||
stream << "let(" << c->call_arguments << ") ";
|
||||
c = c->children[0];
|
||||
} else {
|
||||
assert(false && "Illegal list comprehension element");
|
||||
}
|
||||
} while (c->isListComprehension());
|
||||
|
||||
stream << *c << "]";
|
||||
stream << "[" << *this->first << "]";
|
||||
}
|
||||
|
||||
ExpressionLc::ExpressionLc(Expression *expr) : Expression(expr)
|
||||
ExpressionLc::ExpressionLc(const std::string &name,
|
||||
const AssignmentList &arglist, Expression *expr)
|
||||
: Expression(expr), name(name), call_arguments(arglist)
|
||||
{
|
||||
}
|
||||
|
||||
ExpressionLc::ExpressionLc(Expression *expr1, Expression *expr2) : Expression(expr1, expr2)
|
||||
ExpressionLc::ExpressionLc(const std::string &name,
|
||||
Expression *expr1, Expression *expr2)
|
||||
: Expression(expr1, expr2), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -573,16 +540,16 @@ 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);
|
||||
if (this->name == "if") {
|
||||
if (this->first->evaluate(context)) {
|
||||
if (this->second->isListComprehension()) {
|
||||
return this->second->evaluate(context);
|
||||
} else {
|
||||
vec.push_back((*this->children[1]->evaluate(context)));
|
||||
vec.push_back((*this->second->evaluate(context)));
|
||||
}
|
||||
}
|
||||
return ValuePtr(vec);
|
||||
} else if (this->call_funcname == "for") {
|
||||
} else if (this->name == "for") {
|
||||
EvalContext for_context(context, this->call_arguments);
|
||||
|
||||
Context assign_context(context);
|
||||
|
@ -601,30 +568,30 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
|
|||
} 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)));
|
||||
vec.push_back((*this->first->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)));
|
||||
vec.push_back((*this->first->evaluate(&c)));
|
||||
}
|
||||
}
|
||||
else if (it_values->type() != Value::UNDEFINED) {
|
||||
c.set_variable(it_name, it_values);
|
||||
vec.push_back((*this->children[0]->evaluate(&c)));
|
||||
vec.push_back((*this->first->evaluate(&c)));
|
||||
}
|
||||
if (this->children[0]->isListComprehension()) {
|
||||
if (this->first->isListComprehension()) {
|
||||
return ValuePtr(flatten(vec));
|
||||
} else {
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
} else if (this->call_funcname == "let") {
|
||||
} else if (this->name == "let") {
|
||||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
|
||||
return this->children[0]->evaluate(&c);
|
||||
return this->first->evaluate(&c);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
@ -632,7 +599,15 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
|
|||
|
||||
void ExpressionLc::print(std::ostream &stream) const
|
||||
{
|
||||
// FIXME: Implement?
|
||||
stream << this->name;
|
||||
if (this->name == "if") {
|
||||
stream << "(" << *this->first << ") " << *this->second;
|
||||
}
|
||||
else if (this->name == "for" || this->name == "let") {
|
||||
stream << "(" << this->call_arguments << ") " << *this->first;
|
||||
} else {
|
||||
assert(false && "Illegal list comprehension element");
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Expression &expr)
|
||||
|
|
|
@ -13,16 +13,7 @@ public:
|
|||
Expression *second;
|
||||
Expression *third;
|
||||
|
||||
ValuePtr const_value;
|
||||
std::string var_name;
|
||||
|
||||
std::string call_funcname;
|
||||
AssignmentList call_arguments;
|
||||
|
||||
Expression();
|
||||
Expression(const ValuePtr &val);
|
||||
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);
|
||||
|
@ -161,6 +152,7 @@ public:
|
|||
ExpressionArrayLookup(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
};
|
||||
|
||||
class ExpressionInvert : public Expression
|
||||
|
@ -177,6 +169,8 @@ public:
|
|||
ExpressionConst(const ValuePtr &val);
|
||||
ValuePtr evaluate(const class Context *) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
ValuePtr const_value;
|
||||
};
|
||||
|
||||
class ExpressionRange : public Expression
|
||||
|
@ -199,33 +193,42 @@ public:
|
|||
class ExpressionLookup : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLookup(const std::string &val);
|
||||
ExpressionLookup(const std::string &var_name);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
std::string var_name;
|
||||
};
|
||||
|
||||
class ExpressionMember : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionMember(const std::string &val, Expression *expr);
|
||||
ExpressionMember(Expression *expr, const std::string &member);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
std::string member;
|
||||
};
|
||||
|
||||
class ExpressionFunction : public Expression
|
||||
class ExpressionFunctionCall : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionFunction();
|
||||
ExpressionFunctionCall(const std::string &funcname, const AssignmentList &arglist);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
public:
|
||||
std::string funcname;
|
||||
AssignmentList call_arguments;
|
||||
};
|
||||
|
||||
class ExpressionLet : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLet(Expression *expr);
|
||||
ExpressionLet(const AssignmentList &arglist, Expression *expr);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList call_arguments;
|
||||
};
|
||||
|
||||
class ExpressionLcExpression : public Expression
|
||||
|
@ -240,8 +243,13 @@ class ExpressionLc : public Expression
|
|||
{
|
||||
virtual bool isListComprehension() const;
|
||||
public:
|
||||
ExpressionLc(Expression *expr);
|
||||
ExpressionLc(Expression *expr1, Expression *expr2);
|
||||
ExpressionLc(const std::string &name,
|
||||
const AssignmentList &arglist, Expression *expr);
|
||||
ExpressionLc(const std::string &name,
|
||||
Expression *expr1, Expression *expr2);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
std::string name;
|
||||
AssignmentList call_arguments;
|
||||
};
|
||||
|
|
22
src/parser.y
22
src/parser.y
|
@ -319,7 +319,7 @@ expr:
|
|||
}
|
||||
| expr '.' TOK_ID
|
||||
{
|
||||
$$ = new ExpressionMember($3, $1);
|
||||
$$ = new ExpressionMember($1, $3);
|
||||
free($3);
|
||||
}
|
||||
| TOK_STRING
|
||||
|
@ -333,8 +333,7 @@ expr:
|
|||
}
|
||||
| TOK_LET '(' arguments_call ')' expr %prec LET
|
||||
{
|
||||
$$ = new ExpressionLet($5);
|
||||
$$->call_arguments = *$3;
|
||||
$$ = new ExpressionLet(*$3, $5);
|
||||
delete $3;
|
||||
}
|
||||
| '[' expr ':' expr ']'
|
||||
|
@ -435,9 +434,7 @@ expr:
|
|||
}
|
||||
| TOK_ID '(' arguments_call ')'
|
||||
{
|
||||
$$ = new ExpressionFunction();
|
||||
$$->call_funcname = $1;
|
||||
$$->call_arguments = *$3;
|
||||
$$ = new ExpressionFunctionCall($1, *$3);
|
||||
free($1);
|
||||
delete $3;
|
||||
}
|
||||
|
@ -448,9 +445,7 @@ list_comprehension_elements:
|
|||
be parsed as an expression) */
|
||||
TOK_LET '(' arguments_call ')' list_comprehension_elements
|
||||
{
|
||||
$$ = new ExpressionLc($5);
|
||||
$$->call_funcname = "let";
|
||||
$$->call_arguments = *$3;
|
||||
$$ = new ExpressionLc("let", *$3, $5);
|
||||
delete $3;
|
||||
}
|
||||
| TOK_FOR '(' arguments_call ')' list_comprehension_elements_or_expr
|
||||
|
@ -459,17 +454,16 @@ list_comprehension_elements:
|
|||
|
||||
/* transform for(i=...,j=...) -> for(i=...) for(j=...) */
|
||||
for (int i = $3->size()-1; i >= 0; i--) {
|
||||
Expression *e = new ExpressionLc($$);
|
||||
e->call_funcname = "for";
|
||||
e->call_arguments.push_back((*$3)[i]);
|
||||
AssignmentList arglist;
|
||||
arglist.push_back((*$3)[i]);
|
||||
Expression *e = new ExpressionLc("for", arglist, $$);
|
||||
$$ = e;
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| TOK_IF '(' expr ')' list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = new ExpressionLc($3, $5);
|
||||
$$->call_funcname = "if";
|
||||
$$ = new ExpressionLc("if", $3, $5);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
Loading…
Reference in New Issue