Skip to content

Commit

Permalink
Formula engine: Improve debugger
Browse files Browse the repository at this point in the history
- Less-than characters no longer break markup
- More debug information attached to various evaluation stages
- Fixed how some components of formulas were printed
- You can now step through the assignments in where clauses
  • Loading branch information
CelticMinstrel committed Mar 18, 2016
1 parent 69024df commit a02b1c1
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 31 deletions.
65 changes: 49 additions & 16 deletions src/formula.cpp
Expand Up @@ -105,7 +105,7 @@ class list_expression : public formula_expression {
std::vector<variant> res;
res.reserve(items_.size());
for(std::vector<expression_ptr>::const_iterator i = items_.begin(); i != items_.end(); ++i) {
res.push_back((*i)->evaluate(variables,fdb));
res.push_back((*i)->evaluate(variables,add_debug_info(fdb, 0, "[list element]")));
}

return variant(&res);
Expand Down Expand Up @@ -144,6 +144,9 @@ class map_expression : public formula_expression {
std::stringstream s;
s << " [";
for(std::vector<expression_ptr>::const_iterator i = items_.begin(); ( i != items_.end() ) && ( i+1 != items_.end() ) ; i+=2) {
if(i != items_.begin()) {
s << ", ";
}
s << (*i)->str();
s << " -> ";
s << (*(i+1))->str();
Expand All @@ -158,8 +161,8 @@ class map_expression : public formula_expression {
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
std::map<variant,variant> res;
for(std::vector<expression_ptr>::const_iterator i = items_.begin(); ( i != items_.end() ) && ( i+1 != items_.end() ) ; i+=2) {
variant key = (*i)->evaluate(variables,fdb);
variant value = (*(i+1))->evaluate(variables,fdb);
variant key = (*i)->evaluate(variables,add_debug_info(fdb, 0, "key ->"));
variant value = (*(i+1))->evaluate(variables,add_debug_info(fdb, 1, "-> value"));
res[ key ] = value;
}

Expand Down Expand Up @@ -192,7 +195,7 @@ class unary_operator_expression : public formula_expression {

private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
const variant res = operand_->evaluate(variables,fdb);
const variant res = operand_->evaluate(variables,add_debug_info(fdb, 0, op_str_ + " unary"));
switch(op_) {
case NOT:
return res.as_bool() ? variant(0) : variant(1);
Expand Down Expand Up @@ -373,7 +376,7 @@ class dot_expression : public formula_expression {
}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
const variant left = left_->evaluate(variables,add_debug_info(fdb,0,"left."));
const variant left = left_->evaluate(variables,add_debug_info(fdb,0,"left ."));
if(!left.is_callable()) {
if(left.is_list()) {
list_callable list_call(left);
Expand All @@ -395,7 +398,7 @@ class dot_expression : public formula_expression {
}

dot_callable callable(variables, *left.as_callable());
return right_->evaluate(callable,add_debug_info(fdb,1,".right"));
return right_->evaluate(callable,add_debug_info(fdb,1,". right"));
}

expression_ptr left_, right_;
Expand All @@ -415,8 +418,8 @@ class square_bracket_expression : public formula_expression {
}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
const variant left = left_->evaluate(variables,fdb);
const variant key = key_->evaluate(variables,fdb);
const variant left = left_->evaluate(variables,add_debug_info(fdb,0,"base[]"));
const variant key = key_->evaluate(variables,add_debug_info(fdb,1,"[index]"));
if(left.is_list() || left.is_map()) {
return left[ key ];
} else {
Expand Down Expand Up @@ -461,13 +464,13 @@ class operator_expression : public formula_expression {
std::string str() const
{
std::stringstream s;
s << left_->str() << op_str_ << right_->str();
s << '(' << left_->str() << op_str_ << right_->str() << ')';
return s.str();
}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
const variant left = left_->evaluate(variables,add_debug_info(fdb,0,"left_OP"));
const variant right = right_->evaluate(variables,add_debug_info(fdb,1,"OP_right"));
const variant left = left_->evaluate(variables,add_debug_info(fdb,0,"left " + op_str_));
const variant right = right_->evaluate(variables,add_debug_info(fdb,1,op_str_ + " right"));
switch(op_) {
case AND:
return left.as_bool() == false ? left : right;
Expand Down Expand Up @@ -546,18 +549,20 @@ typedef std::map<std::string, variant> exp_table_evaluated;
class where_variables: public formula_callable {
public:
where_variables(const formula_callable &base,
expr_table_ptr table )
expr_table_ptr table, formula_debugger* fdb )
: formula_callable(false)
, base_(base)
, table_(table)
, evaluated_table_()
, debugger_(fdb)
{
}

private:
const formula_callable& base_;
expr_table_ptr table_;
mutable exp_table_evaluated evaluated_table_;
formula_debugger* debugger_;

void get_inputs(std::vector<formula_input>* inputs) const {
for(expr_table::const_iterator i = table_->begin(); i != table_->end(); ++i) {
Expand All @@ -572,7 +577,7 @@ class where_variables: public formula_callable {
if( ev != evaluated_table_.end())
return ev->second;

variant v = i->second->evaluate(base_);
variant v = i->second->evaluate(base_, add_debug_info(debugger_, 0, "where[" + key + "]"));
evaluated_table_[key] = v;
return v;
}
Expand Down Expand Up @@ -604,8 +609,8 @@ class where_expression: public formula_expression {
expr_table_ptr clauses_;

variant execute(const formula_callable& variables,formula_debugger *fdb) const {
where_variables wrapped_variables(variables, clauses_);
return body_->evaluate(wrapped_variables,fdb);
where_variables wrapped_variables(variables, clauses_, fdb);
return body_->evaluate(wrapped_variables,add_debug_info(fdb, 0, "... where"));
}
};

Expand Down Expand Up @@ -729,7 +734,33 @@ class string_expression : public formula_expression {

std::string str() const
{
return str_.as_string();
std::string res = str_.as_string();
int j = res.size() - 1;
for(size_t i = 0; i < subs_.size(); ++i) {
const substitution& sub = subs_[i];
for(;j >= sub.pos && j >= 0;j--) {
if(res[j] == '\'') {
res.replace(j, 1, "[']");
} else if(res[j] == '[') {
res.replace(j, 1, "[(]");
} else if(res[j] == ']') {
res.replace(j, 1, "[)]");
}
}
const std::string str = "[" + sub.calculation->str() + "]";
res.insert(sub.pos, str);
}
for(;j >= 0;j--) {
if(res[j] == '\'') {
res.replace(j, 1, "[']");
} else if(res[j] == '[') {
res.replace(j, 1, "[(]");
} else if(res[j] == ']') {
res.replace(j, 1, "[)]");
}
}

return "'" + res + "'";
}
private:
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
Expand All @@ -738,7 +769,9 @@ class string_expression : public formula_expression {
} else {
std::string res = str_.as_string();
for(size_t i=0; i < subs_.size(); ++i) {
const int j = subs_.size() - i - 1;
const substitution& sub = subs_[i];
add_debug_info(fdb, j, "[string subst]");
const std::string str = sub.calculation->evaluate(variables,fdb).string_cast();
res.insert(sub.pos, str);
}
Expand Down
4 changes: 2 additions & 2 deletions src/formula_debugger.cpp
Expand Up @@ -111,11 +111,11 @@ formula_debugger::~formula_debugger()

static void msg(const char *act, debug_info &i, const char *to="", const char *result = "")
{
DBG_FDB << "#" << i.counter() << act << std::endl <<" \""<< i.name().c_str() << "\"='" << i.str().c_str() << "' " << to << result << std::endl;
DBG_FDB << "#" << i.counter() << act << std::endl <<" \""<< i.name() << "\"='" << i.str() << "' " << to << result << std::endl;
}


void formula_debugger::add_debug_info(int arg_number, const char *f_name)
void formula_debugger::add_debug_info(int arg_number, const std::string& f_name)
{
arg_number_extra_debug_info = arg_number;
f_name_extra_debug_info = f_name;
Expand Down
6 changes: 3 additions & 3 deletions src/formula_debugger.hpp
Expand Up @@ -81,7 +81,7 @@ class formula_debugger {
virtual ~formula_debugger();


void add_debug_info(int arg_number, const char *f_name);
void add_debug_info(int arg_number, const std::string& f_name);


void call_stack_push(const std::string &str);
Expand Down Expand Up @@ -134,7 +134,7 @@ class formula_debugger {

//static functions

static formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const char *f_name)
static formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const std::string& f_name)
{
if (fdb==NULL) {
return NULL;
Expand All @@ -150,7 +150,7 @@ class formula_debugger {
std::deque< breakpoint_ptr > breakpoints_;
std::deque<debug_info> execution_trace_;
int arg_number_extra_debug_info;
const char *f_name_extra_debug_info;
std::string f_name_extra_debug_info;


};
Expand Down
2 changes: 1 addition & 1 deletion src/formula_debugger_fwd.cpp
Expand Up @@ -23,7 +23,7 @@

namespace game_logic {

formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const char *f_name)
formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const std::string& f_name)
{
if (fdb==NULL) {
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/formula_debugger_fwd.hpp
Expand Up @@ -41,7 +41,7 @@ class base_breakpoint;

typedef boost::shared_ptr<base_breakpoint> breakpoint_ptr;

formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const char *f_name);
formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const std::string& f_name);

variant evaluate_arg_callback(formula_debugger &fdb, const formula_expression &expression, const formula_callable &variables);

Expand Down
37 changes: 29 additions & 8 deletions src/gui/dialogs/formula_debugger.cpp
Expand Up @@ -26,6 +26,27 @@

#include <boost/bind.hpp>

namespace {

std::string pango_escape(std::string str) {
for(size_t i = str.size(); i > 0; i--) {
if(str[i-1] == '<') {
str.replace(i-1, 1, "&lt;");
} else if(str[i-1] == '>') {
str.replace(i-1, 1, "&gt;");
} else if(str[i-1] == '&') {
str.replace(i-1, 1, "&amp;");
} else if(str[i-1] == '"') {
str.replace(i-1, 1, "&quot;");
} else if(str[i-1] == '\'') {
str.replace(i-1, 1, "&apos;");
}
}
return str;
}

}

namespace gui2
{

Expand Down Expand Up @@ -80,8 +101,8 @@ void tformula_debugger::pre_show(twindow& window)
stack_text << indent;
}
stack_text << "#<span color=\"green\">" << i.counter()
<< "</span>: \"<span color=\"green\">" << i.name()
<< "</span>\": '" << i.str() << "' " << std::endl;
<< "</span>: \"<span color=\"green\">" << pango_escape(i.name())
<< "</span>\": (" << pango_escape(i.str()) << ") " << std::endl;
++c;
}

Expand All @@ -101,14 +122,14 @@ void tformula_debugger::pre_show(twindow& window)
}
if(!i.evaluated()) {
execution_text << "#<span color=\"green\">" << i.counter()
<< "</span>: \"<span color=\"green\">" << i.name()
<< "</span>\": '" << i.str() << "' " << std::endl;
<< "</span>: \"<span color=\"green\">" << pango_escape(i.name())
<< "</span>\": (" << pango_escape(i.str()) << ") " << std::endl;
} else {
execution_text << "#<span color=\"yellow\">" << i.counter()
<< "</span>: \"<span color=\"yellow\">" << i.name()
<< "</span>\": '" << i.str() << "' = "
<< "<span color=\"red\">"
<< i.value().to_debug_string(NULL, false)
<< "</span>: \"<span color=\"yellow\">" << pango_escape(i.name())
<< "</span>\": (" << pango_escape(i.str()) << ") = "
<< "<span color=\"orange\">"
<< pango_escape(i.value().to_debug_string(NULL, false))
<< "</span>" << std::endl;
}
}
Expand Down

0 comments on commit a02b1c1

Please sign in to comment.