summaryrefslogtreecommitdiff
path: root/src/expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/expr.cc')
-rw-r--r--src/expr.cc55
1 files changed, 42 insertions, 13 deletions
diff --git a/src/expr.cc b/src/expr.cc
index 75fc47a..4355400 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -26,19 +26,34 @@
#include "expression.h"
#include "value.h"
-#include "context.h"
+#include "evalcontext.h"
#include <assert.h>
#include <sstream>
#include <algorithm>
#include "stl-utils.h"
+#include "printutils.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
-Expression::Expression()
+Expression::Expression() : recursioncount(0)
{
}
-Expression::Expression(const Value &val) : const_value(val), type("C")
+Expression::Expression(const std::string &type,
+ Expression *left, Expression *right)
+ : type(type), recursioncount(0)
+{
+ this->children.push_back(left);
+ this->children.push_back(right);
+}
+
+Expression::Expression(const std::string &type, Expression *expr)
+ : type(type), recursioncount(0)
+{
+ this->children.push_back(expr);
+}
+
+Expression::Expression(const Value &val) : const_value(val), type("C"), recursioncount(0)
{
}
@@ -47,6 +62,18 @@ Expression::~Expression()
std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
}
+class FuncRecursionGuard
+{
+public:
+ FuncRecursionGuard(const Expression &e) : expr(e) {
+ expr.recursioncount++;
+ }
+ ~FuncRecursionGuard() { expr.recursioncount--; }
+ bool recursion_detected() const { return (expr.recursioncount > 100); }
+private:
+ const Expression &expr;
+};
+
Value Expression::evaluate(const Context *context) const
{
if (this->type == "!")
@@ -127,13 +154,14 @@ Value Expression::evaluate(const Context *context) const
return Value();
}
if (this->type == "F") {
- Value::VectorType argvalues;
- std::transform(this->children.begin(), this->children.end(),
- std::back_inserter(argvalues),
- boost::bind(&Expression::evaluate, _1, context));
- // 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);
+ FuncRecursionGuard g(*this);
+ if (g.recursion_detected()) {
+ PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname);
+ return Value();
+ }
+
+ EvalContext c(context, this->call_arguments);
+ return context->evaluate_function(this->call_funcname, &c);
}
abort();
}
@@ -178,10 +206,11 @@ std::string Expression::toString() const
}
else if (this->type == "F") {
stream << this->call_funcname << "(";
- for (size_t i=0; i < this->children.size(); i++) {
+ for (size_t i=0; i < this->call_arguments.size(); i++) {
+ const Assignment &arg = this->call_arguments[i];
if (i > 0) stream << ", ";
- if (!this->call_argnames[i].empty()) stream << this->call_argnames[i] << " = ";
- stream << *this->children[i];
+ if (!arg.first.empty()) stream << arg.first << " = ";
+ stream << *arg.second;
}
stream << ")";
}
contact: Jan Huwald // Impressum