diff options
Diffstat (limited to 'src/expr.cc')
-rw-r--r-- | src/expr.cc | 225 |
1 files changed, 122 insertions, 103 deletions
diff --git a/src/expr.cc b/src/expr.cc index 50950d0..c9eda4e 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -27,74 +27,76 @@ #include "expression.h" #include "value.h" #include "context.h" +#include <assert.h> +#include <sstream> +#include <algorithm> +#include "stl-utils.h" Expression::Expression() { - const_value = NULL; + this->const_value = NULL; } Expression::~Expression() { - for (int i=0; i < children.size(); i++) - delete children[i]; - if (const_value) - delete const_value; + std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>()); + delete this->const_value; } Value Expression::evaluate(const Context *context) const { - if (type == "!") - return ! children[0]->evaluate(context); - if (type == "&&") - return children[0]->evaluate(context) && children[1]->evaluate(context); - if (type == "||") - return children[0]->evaluate(context) || children[1]->evaluate(context); - if (type == "*") - return children[0]->evaluate(context) * children[1]->evaluate(context); - if (type == "/") - return children[0]->evaluate(context) / children[1]->evaluate(context); - if (type == "%") - return children[0]->evaluate(context) % children[1]->evaluate(context); - if (type == "+") - return children[0]->evaluate(context) + children[1]->evaluate(context); - if (type == "-") - return children[0]->evaluate(context) - children[1]->evaluate(context); - if (type == "<") - return children[0]->evaluate(context) < children[1]->evaluate(context); - if (type == "<=") - return children[0]->evaluate(context) <= children[1]->evaluate(context); - if (type == "==") - return children[0]->evaluate(context) == children[1]->evaluate(context); - if (type == "!=") - return children[0]->evaluate(context) != children[1]->evaluate(context); - if (type == ">=") - return children[0]->evaluate(context) >= children[1]->evaluate(context); - if (type == ">") - return children[0]->evaluate(context) > children[1]->evaluate(context); - if (type == "?:") { - Value v = children[0]->evaluate(context); + if (this->type == "!") + return ! this->children[0]->evaluate(context); + if (this->type == "&&") + return this->children[0]->evaluate(context) && this->children[1]->evaluate(context); + if (this->type == "||") + return this->children[0]->evaluate(context) || this->children[1]->evaluate(context); + if (this->type == "*") + return this->children[0]->evaluate(context) * this->children[1]->evaluate(context); + if (this->type == "/") + return this->children[0]->evaluate(context) / this->children[1]->evaluate(context); + if (this->type == "%") + return this->children[0]->evaluate(context) % this->children[1]->evaluate(context); + if (this->type == "+") + return this->children[0]->evaluate(context) + this->children[1]->evaluate(context); + if (this->type == "-") + return this->children[0]->evaluate(context) - this->children[1]->evaluate(context); + if (this->type == "<") + return this->children[0]->evaluate(context) < this->children[1]->evaluate(context); + if (this->type == "<=") + return this->children[0]->evaluate(context) <= this->children[1]->evaluate(context); + if (this->type == "==") + return this->children[0]->evaluate(context) == this->children[1]->evaluate(context); + if (this->type == "!=") + return this->children[0]->evaluate(context) != this->children[1]->evaluate(context); + if (this->type == ">=") + return this->children[0]->evaluate(context) >= this->children[1]->evaluate(context); + if (this->type == ">") + return this->children[0]->evaluate(context) > this->children[1]->evaluate(context); + if (this->type == "?:") { + Value v = this->children[0]->evaluate(context); if (v.type == Value::BOOL) - return children[v.b ? 1 : 2]->evaluate(context); + return this->children[v.b ? 1 : 2]->evaluate(context); return Value(); } - if (type == "[]") { - Value v1 = children[0]->evaluate(context); - Value v2 = children[1]->evaluate(context); + if (this->type == "[]") { + Value v1 = this->children[0]->evaluate(context); + Value v2 = this->children[1]->evaluate(context); if (v1.type == Value::VECTOR && v2.type == Value::NUMBER) { - int i = (int)(v2.num); - if (i >= 0 && i < v1.vec.size()) + int i = int(v2.num); + if (i >= 0 && i < int(v1.vec.size())) return *v1.vec[i]; } return Value(); } - if (type == "I") - return children[0]->evaluate(context).inv(); - if (type == "C") - return *const_value; - if (type == "R") { - Value v1 = children[0]->evaluate(context); - Value v2 = children[1]->evaluate(context); - Value v3 = children[2]->evaluate(context); + if (this->type == "I") + return this->children[0]->evaluate(context).inv(); + if (this->type == "C") + return *this->const_value; + if (this->type == "R") { + Value v1 = this->children[0]->evaluate(context); + Value v2 = this->children[1]->evaluate(context); + Value v3 = this->children[2]->evaluate(context); if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER) { Value r = Value(); r.type = Value::RANGE; @@ -105,83 +107,100 @@ Value Expression::evaluate(const Context *context) const } return Value(); } - if (type == "V") { + if (this->type == "V") { Value v; v.type = Value::VECTOR; - for (int i = 0; i < children.size(); i++) - v.vec.append(new Value(children[i]->evaluate(context))); + for (size_t i = 0; i < this->children.size(); i++) + v.append(new Value(this->children[i]->evaluate(context))); return v; } - if (type == "L") - return context->lookup_variable(var_name); - if (type == "N") + if (this->type == "L") + return context->lookup_variable(this->var_name); + if (this->type == "N") { - Value v = children[0]->evaluate(context); + Value v = this->children[0]->evaluate(context); - if (v.type == Value::VECTOR && var_name == QString("x")) + if (v.type == Value::VECTOR && this->var_name == "x") return *v.vec[0]; - if (v.type == Value::VECTOR && var_name == QString("y")) + if (v.type == Value::VECTOR && this->var_name == "y") return *v.vec[1]; - if (v.type == Value::VECTOR && var_name == QString("z")) + if (v.type == Value::VECTOR && this->var_name == "z") return *v.vec[2]; - if (v.type == Value::RANGE && var_name == QString("begin")) + if (v.type == Value::RANGE && this->var_name == "begin") return Value(v.range_begin); - if (v.type == Value::RANGE && var_name == QString("step")) + if (v.type == Value::RANGE && this->var_name == "step") return Value(v.range_step); - if (v.type == Value::RANGE && var_name == QString("end")) + if (v.type == Value::RANGE && this->var_name == "end") return Value(v.range_end); return Value(); } - if (type == "F") { - QVector<Value> argvalues; - for (int i=0; i < children.size(); i++) - argvalues.append(children[i]->evaluate(context)); - return context->evaluate_function(call_funcname, call_argnames, argvalues); + if (this->type == "F") { + std::vector<Value> argvalues; + for (size_t i=0; i < this->children.size(); i++) + argvalues.push_back(this->children[i]->evaluate(context)); + return context->evaluate_function(this->call_funcname, this->call_argnames, argvalues); } abort(); } -QString Expression::dump() const +std::string Expression::toString() const { - if (type == "*" || type == "/" || type == "%" || type == "+" || type == "-" || - type == "<" || type == "<=" || type == "==" || type == "!=" || type == ">=" || type == ">") - return QString("(%1 %2 %3)").arg(children[0]->dump(), QString(type), children[1]->dump()); - if (type == "?:") - return QString("(%1 ? %2 : %3)").arg(children[0]->dump(), children[1]->dump(), children[2]->dump()); - if (type == "[]") - return QString("(%1[%2])").arg(children[0]->dump(), children[1]->dump()); - if (type == "I") - return QString("(-%1)").arg(children[0]->dump()); - if (type == "C") - return const_value->dump(); - if (type == "R") - return QString("[%1 : %2 : %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump()); - if (type == "V") { - QString text = QString("["); - for (int i=0; i < children.size(); i++) { - if (i > 0) - text += QString(", "); - text += children[i]->dump(); + std::stringstream stream; + + if (this->type == "*" || this->type == "/" || this->type == "%" || this->type == "+" || + this->type == "-" || this->type == "<" || this->type == "<=" || this->type == "==" || + this->type == "!=" || this->type == ">=" || this->type == ">") { + stream << "(" << *this->children[0] << " " << this->type << " " << *this->children[1] << ")"; + } + else if (this->type == "?:") { + stream << "(" << *this->children[0] << " ? " << this->type << " : " << *this->children[1] << ")"; + } + else if (this->type == "[]") { + stream << "(" << *this->children[0] << "[" << *this->children[1] << "])"; + } + else if (this->type == "I") { + stream << "(-" << *this->children[0] << ")"; + } + else if (this->type == "C") { + stream << *this->const_value; + } + else if (this->type == "R") { + stream << "[" << *this->children[0] << " : " << *this->children[1] << " : " << this->children[2] << "]"; + } + else if (this->type == "V") { + stream << "["; + for (size_t i=0; i < this->children.size(); i++) { + if (i > 0) stream << ", "; + stream << *this->children[i]; } - return text + QString("]"); - } - if (type == "L") - return var_name; - if (type == "N") - return QString("(%1.%2)").arg(children[0]->dump(), var_name); - if (type == "F") { - QString text = call_funcname + QString("("); - for (int i=0; i < children.size(); i++) { - if (i > 0) - text += QString(", "); - if (!call_argnames[i].isEmpty()) - text += call_argnames[i] + QString(" = "); - text += children[i]->dump(); + stream << "]"; + } + else if (this->type == "L") { + stream << this->var_name; + } + else if (this->type == "N") { + stream << "(" << *this->children[0] << "." << this->var_name << ")"; + } + else if (this->type == "F") { + stream << this->call_funcname << "("; + for (size_t i=0; i < this->children.size(); i++) { + if (i > 0) stream << ", "; + if (!this->call_argnames[i].empty()) stream << this->call_argnames[i] << " = "; + stream << *this->children[i]; } - return text + QString(")"); + stream << ")"; } - abort(); + else { + assert(false && "Illegal expression type"); + } + + return stream.str(); } +std::ostream &operator<<(std::ostream &stream, const Expression &expr) +{ + stream << expr.toString(); + return stream; +} |