Formula AI Debugger (uses --new-widgets )
This commit is contained in:
parent
40b0ee8f1a
commit
498c4f8977
22 changed files with 1186 additions and 67 deletions
|
@ -1,4 +1,6 @@
|
|||
Version 1.7.3+svn:
|
||||
* AI:
|
||||
* Formula AI debugger (uses -new-widgets)
|
||||
* Language and i18n:
|
||||
* Updated translations:
|
||||
* Miscellaneous and bugfixes:
|
||||
|
|
228
data/gui/default/window/formula_debugger.cfg
Normal file
228
data/gui/default/window/formula_debugger.cfg
Normal file
|
@ -0,0 +1,228 @@
|
|||
#textdomain wesnoth-lib
|
||||
###
|
||||
### Definition of the window to control formula debugger.
|
||||
###
|
||||
|
||||
[window]
|
||||
id = "formula_debugger"
|
||||
description = "Formula debugger dialog."
|
||||
|
||||
[resolution]
|
||||
definition = "default"
|
||||
automatic_placement = "true"
|
||||
vertical_placement = "center"
|
||||
horizontal_placement = "center"
|
||||
|
||||
[grid]
|
||||
[row] #header
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[label]
|
||||
definition = "title"
|
||||
label = _ "Formula debugger"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
[spacer]
|
||||
definition = "default"
|
||||
[/spacer]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #menu
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
|
||||
[label]
|
||||
definition = "default"
|
||||
label= _ "Welcome"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[label]
|
||||
id="state"
|
||||
definition = "default"
|
||||
label= _ "state"
|
||||
[/label]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #stack-title
|
||||
grow_factor = 2
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[label]
|
||||
definition = "default"
|
||||
label= _ "Call stack"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
horizontal_alignment="center"
|
||||
[label]
|
||||
definition = "default"
|
||||
label = _ "Actions"
|
||||
[/label]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #stack-main
|
||||
grow_factor = 2
|
||||
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
vertical_alignment = "top"
|
||||
horizontal_alignment = "left"
|
||||
[scroll_label]
|
||||
id = "stack"
|
||||
definition = "default"
|
||||
[/scroll_label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "center"
|
||||
vertical_alignment = "top"
|
||||
[grid]
|
||||
[row]
|
||||
grow_factor=0
|
||||
[column]
|
||||
grow_factor=0
|
||||
[button]
|
||||
id = "step"
|
||||
definition = "default"
|
||||
label = _ "Step operation"
|
||||
[/button]
|
||||
[/column][/row]
|
||||
[row]
|
||||
grow_factor=0
|
||||
[column]
|
||||
grow_factor=0
|
||||
[button]
|
||||
id = "next"
|
||||
definition = "default"
|
||||
label = _ "Next operation"
|
||||
[/button]
|
||||
[/column][/row]
|
||||
[row]
|
||||
grow_factor=0
|
||||
grow_factor=0
|
||||
[column]
|
||||
[button]
|
||||
id = "stepout"
|
||||
definition = "default"
|
||||
label = _ "Step out"
|
||||
[/button]
|
||||
[/column][/row]
|
||||
[row]
|
||||
grow_factor=0
|
||||
[column]
|
||||
grow_factor=0
|
||||
[button]
|
||||
id = "continue"
|
||||
definition = "default"
|
||||
label = _ "Continue"
|
||||
[/button]
|
||||
[/column][/row]
|
||||
[/grid]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #trace-title
|
||||
grow_factor = 0
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[label]
|
||||
definition = "default"
|
||||
label= _ "Execution trace"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
horizontal_alignment="center"
|
||||
[spacer]
|
||||
definition = "default"
|
||||
[/spacer]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #trace-main
|
||||
grow_factor = 6
|
||||
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[scroll_label]
|
||||
id = "execution"
|
||||
definition = "default"
|
||||
[/scroll_label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[spacer]
|
||||
definition = "default"
|
||||
[/spacer]
|
||||
[/column]
|
||||
[/row]
|
||||
|
||||
[row] #status
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 7
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_alignment = "left"
|
||||
[spacer]
|
||||
definition = "default"
|
||||
[/spacer]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
[button]
|
||||
id = "cancel"
|
||||
definition = "default"
|
||||
label = _ "Quit"
|
||||
[/button]
|
||||
[/column]
|
||||
[/row]
|
||||
[/grid]
|
||||
[/resolution]
|
||||
[/window]
|
|
@ -188,6 +188,8 @@
|
|||
<Unit filename="..\..\src\formula_callable.hpp" />
|
||||
<Unit filename="..\..\src\formula_debugger.cpp" />
|
||||
<Unit filename="..\..\src\formula_debugger.hpp" />
|
||||
<Unit filename="..\..\src\formula_debugger_fwd.cpp" />
|
||||
<Unit filename="..\..\src\formula_debugger_fwd.hpp" />
|
||||
<Unit filename="..\..\src\formula_function.cpp" />
|
||||
<Unit filename="..\..\src\formula_function.hpp" />
|
||||
<Unit filename="..\..\src\formula_string_utils.cpp" />
|
||||
|
@ -285,6 +287,8 @@
|
|||
<Unit filename="..\..\src\gui\dialogs\editor_settings.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\field-fwd.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\field.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\formula_debugger.cpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\formula_debugger.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_delete.cpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_delete.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_load.cpp" />
|
||||
|
|
|
@ -217,6 +217,8 @@
|
|||
<Unit filename="..\..\src\formula_callable.hpp" />
|
||||
<Unit filename="..\..\src\formula_debugger.cpp" />
|
||||
<Unit filename="..\..\src\formula_debugger.hpp" />
|
||||
<Unit filename="..\..\src\formula_debugger_fwd.cpp" />
|
||||
<Unit filename="..\..\src\formula_debugger_fwd.hpp" />
|
||||
<Unit filename="..\..\src\formula_function.cpp" />
|
||||
<Unit filename="..\..\src\formula_function.hpp" />
|
||||
<Unit filename="..\..\src\formula_string_utils.cpp" />
|
||||
|
@ -314,6 +316,8 @@
|
|||
<Unit filename="..\..\src\gui\dialogs\editor_settings.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\field-fwd.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\field.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\formula_debugger.cpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\formula_debugger.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_delete.cpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_delete.hpp" />
|
||||
<Unit filename="..\..\src\gui\dialogs\game_load.cpp" />
|
||||
|
|
|
@ -357,6 +357,10 @@
|
|||
RelativePath="..\..\src\formula_debugger.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\formula_debugger_fwd.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\formula_function.cpp"
|
||||
>
|
||||
|
@ -1871,6 +1875,34 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gui\dialogs\formula_debugger.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\Gui\Dialogs\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\Gui\Dialogs\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug (fast)|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\Gui\Dialogs\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gui\dialogs\game_delete.cpp"
|
||||
>
|
||||
|
@ -4828,6 +4860,10 @@
|
|||
RelativePath="..\..\src\formula_debugger.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\formula_debugger_fwd.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\formula_function.hpp"
|
||||
>
|
||||
|
@ -5358,6 +5394,10 @@
|
|||
RelativePath="..\..\src\gui\dialogs\field.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gui\dialogs\formula_debugger.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\gui\dialogs\game_load.hpp"
|
||||
>
|
||||
|
|
|
@ -265,6 +265,7 @@ SET(wesnoth-main_SRC
|
|||
floating_textbox.cpp
|
||||
formula.cpp
|
||||
formula_debugger.cpp
|
||||
formula_debugger_fwd.cpp
|
||||
formula_function.cpp
|
||||
formula_tokenizer.cpp
|
||||
formula_string_utils.cpp
|
||||
|
@ -303,6 +304,7 @@ SET(wesnoth-main_SRC
|
|||
gui/dialogs/addon_list.cpp
|
||||
gui/dialogs/campaign_selection.cpp
|
||||
gui/dialogs/dialog.cpp
|
||||
gui/dialogs/formula_debugger.cpp
|
||||
gui/dialogs/game_load.cpp
|
||||
gui/dialogs/game_delete.cpp
|
||||
gui/dialogs/game_save.cpp
|
||||
|
|
|
@ -86,6 +86,7 @@ wesnoth_source = \
|
|||
floating_textbox.cpp \
|
||||
formula.cpp \
|
||||
formula_debugger.cpp \
|
||||
formula_debugger_fwd.cpp \
|
||||
formula_function.cpp \
|
||||
formula_tokenizer.cpp \
|
||||
formula_string_utils.cpp \
|
||||
|
@ -124,6 +125,7 @@ wesnoth_source = \
|
|||
gui/dialogs/addon_list.cpp \
|
||||
gui/dialogs/campaign_selection.cpp \
|
||||
gui/dialogs/dialog.cpp \
|
||||
gui/dialogs/formula_debugger.cpp \
|
||||
gui/dialogs/game_load.cpp \
|
||||
gui/dialogs/game_delete.cpp \
|
||||
gui/dialogs/game_save.cpp \
|
||||
|
|
|
@ -191,6 +191,7 @@ wesnoth_sources = Split("""
|
|||
floating_textbox.cpp
|
||||
formula.cpp
|
||||
formula_debugger.cpp
|
||||
formula_debugger_fwd.cpp
|
||||
formula_function.cpp
|
||||
formula_tokenizer.cpp
|
||||
formula_string_utils.cpp
|
||||
|
@ -283,6 +284,7 @@ wesnoth_sources = Split("""
|
|||
gui/dialogs/addon_list.cpp
|
||||
gui/dialogs/campaign_selection.cpp
|
||||
gui/dialogs/dialog.cpp
|
||||
gui/dialogs/formula_debugger.cpp
|
||||
gui/dialogs/game_load.cpp
|
||||
gui/dialogs/game_delete.cpp
|
||||
gui/dialogs/game_save.cpp
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../manager.hpp"
|
||||
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../formula_debugger.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "../../menu_events.hpp"
|
||||
|
||||
|
|
|
@ -387,8 +387,8 @@ public:
|
|||
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,formula_debugger::add_debug_info(fdb,0,"nearest_loc:location")))->loc();
|
||||
variant items = args()[1]->evaluate(variables,formula_debugger::add_debug_info(fdb,1,"nearest_loc:locations"));
|
||||
const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,add_debug_info(fdb,0,"nearest_loc:location")))->loc();
|
||||
variant items = args()[1]->evaluate(variables,add_debug_info(fdb,1,"nearest_loc:locations"));
|
||||
int best = 1000000;
|
||||
int best_i = -1;
|
||||
|
||||
|
@ -615,7 +615,7 @@ public:
|
|||
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,formula_debugger::add_debug_info(fdb,0,"nearest_keep:location")))->loc();
|
||||
const map_location loc = convert_variant<location_callable>(args()[0]->evaluate(variables,add_debug_info(fdb,0,"nearest_keep:location")))->loc();
|
||||
int best = 1000000;
|
||||
int best_i = -1;
|
||||
|
||||
|
@ -1235,7 +1235,7 @@ public:
|
|||
{}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
variant res = args()[0]->evaluate(variables,formula_debugger::add_debug_info(fdb,0,"unit_moves:unit_location"));
|
||||
variant res = args()[0]->evaluate(variables,add_debug_info(fdb,0,"unit_moves:unit_location"));
|
||||
std::vector<variant> vars;
|
||||
if(res.is_null()) {
|
||||
return variant(&vars);
|
||||
|
|
118
src/formula.cpp
118
src/formula.cpp
|
@ -16,7 +16,7 @@
|
|||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
//#include "foreach.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "formula_callable.hpp"
|
||||
#include "formula_function.hpp"
|
||||
#include "map_utils.hpp"
|
||||
|
@ -29,6 +29,7 @@ void formula_callable::set_value(const std::string& key, const variant& /*value*
|
|||
std::cerr << "ERROR: cannot set key '" << key << "' on object\n";
|
||||
}
|
||||
|
||||
|
||||
map_formula_callable::map_formula_callable(
|
||||
const formula_callable* fallback) :
|
||||
formula_callable(false),
|
||||
|
@ -72,6 +73,10 @@ public:
|
|||
: symbols_(symbols)
|
||||
{}
|
||||
|
||||
virtual std::string str() const
|
||||
{
|
||||
return "{function_list_expression()}";
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& /*variables*/, formula_debugger * /*fdb*/) const {
|
||||
std::vector<variant> res;
|
||||
|
@ -105,6 +110,25 @@ private:
|
|||
}
|
||||
|
||||
std::vector<expression_ptr> items_;
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << '[';
|
||||
bool first_item = true;
|
||||
foreach(expression_ptr a , items_) {
|
||||
if (!first_item) {
|
||||
s << ',';
|
||||
} else {
|
||||
first_item = false;
|
||||
}
|
||||
s << a->str();
|
||||
}
|
||||
s << ']';
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class map_expression : public formula_expression {
|
||||
|
@ -113,6 +137,20 @@ public:
|
|||
: items_(items)
|
||||
{}
|
||||
|
||||
virtual std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "{map_expression:(";
|
||||
for(std::vector<expression_ptr>::const_iterator i = items_.begin(); ( i != items_.end() ) && ( i+1 != items_.end() ) ; i+=2) {
|
||||
s << "[";
|
||||
s << (*i)->str();
|
||||
s << "] -> [";
|
||||
s << (*(i+1))->str();
|
||||
s << "]";
|
||||
}
|
||||
s << ")";
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
std::map<variant,variant> res;
|
||||
|
@ -131,7 +169,7 @@ private:
|
|||
class unary_operator_expression : public formula_expression {
|
||||
public:
|
||||
unary_operator_expression(const std::string& op, expression_ptr arg) :
|
||||
op_(),
|
||||
op_(),op_str_(op),
|
||||
operand_(arg)
|
||||
{
|
||||
if(op == "not") {
|
||||
|
@ -142,6 +180,13 @@ public:
|
|||
throw formula_error("Illegal unary operator: '" + op + "'" , "", "", 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string str() const {
|
||||
std::stringstream s;
|
||||
s << op_str_ << '('<< operand_->str() << ')';
|
||||
return s.str();
|
||||
}
|
||||
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const variant res = operand_->evaluate(variables,fdb);
|
||||
|
@ -155,6 +200,7 @@ private:
|
|||
}
|
||||
enum OP { NOT, SUB };
|
||||
OP op_;
|
||||
std::string op_str_;
|
||||
expression_ptr operand_;
|
||||
};
|
||||
|
||||
|
@ -192,6 +238,7 @@ public:
|
|||
return variant();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class dot_callable : public formula_callable {
|
||||
|
@ -221,9 +268,15 @@ public:
|
|||
dot_expression(expression_ptr left, expression_ptr right)
|
||||
: left_(left), right_(right)
|
||||
{}
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << left_->str() << "." << right_->str();
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const variant left = left_->evaluate(variables,formula_debugger::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);
|
||||
|
@ -235,7 +288,7 @@ private:
|
|||
}
|
||||
|
||||
dot_callable callable(variables, *left.as_callable());
|
||||
return right_->evaluate(callable,formula_debugger::add_debug_info(fdb,1,".right"));
|
||||
return right_->evaluate(callable,add_debug_info(fdb,1,".right"));
|
||||
}
|
||||
|
||||
expression_ptr left_, right_;
|
||||
|
@ -246,6 +299,13 @@ public:
|
|||
square_bracket_expression(expression_ptr left, expression_ptr key)
|
||||
: left_(left), key_(key)
|
||||
{}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << left_->str() << '[' << key_->str() << ']';
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
const variant left = left_->evaluate(variables,fdb);
|
||||
|
@ -264,7 +324,7 @@ class operator_expression : public formula_expression {
|
|||
public:
|
||||
operator_expression(const std::string& op, expression_ptr left,
|
||||
expression_ptr right)
|
||||
: op_(OP(op[0])), left_(left), right_(right)
|
||||
: op_(OP(op[0])), op_str_(op), left_(left), right_(right)
|
||||
{
|
||||
if(op == ">=") {
|
||||
op_ = GTE;
|
||||
|
@ -287,10 +347,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
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,formula_debugger::add_debug_info(fdb,0,"left_OP"));
|
||||
const variant right = right_->evaluate(variables,formula_debugger::add_debug_info(fdb,1,"OP_right"));
|
||||
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"));
|
||||
switch(op_) {
|
||||
case AND:
|
||||
return left.as_bool() == false ? left : right;
|
||||
|
@ -346,6 +412,7 @@ private:
|
|||
ADD='+', SUB='-', MUL='*', DIV='/', ADDL, SUBL, MULL, DIVL, DICE='d', POW='^', MOD='%' };
|
||||
|
||||
OP op_;
|
||||
std::string op_str_;
|
||||
expression_ptr left_, right_;
|
||||
};
|
||||
|
||||
|
@ -391,6 +458,18 @@ public:
|
|||
: body_(body), clauses_(clauses)
|
||||
{}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "{where:(";
|
||||
s << body_->str();
|
||||
foreach (const expr_table::value_type &a, *clauses_) {
|
||||
s << ", [" << a.first << "] -> ["<< a.second->str()<<"]";
|
||||
}
|
||||
s << ")}";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
private:
|
||||
expression_ptr body_;
|
||||
expr_table_ptr clauses_;
|
||||
|
@ -406,6 +485,10 @@ class identifier_expression : public formula_expression {
|
|||
public:
|
||||
explicit identifier_expression(const std::string& id) : id_(id)
|
||||
{}
|
||||
std::string str() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger * /*fdb*/) const {
|
||||
return variables.query_value(id_);
|
||||
|
@ -416,6 +499,9 @@ private:
|
|||
class null_expression : public formula_expression {
|
||||
public:
|
||||
explicit null_expression() {};
|
||||
std::string str() const {
|
||||
return "";
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& /*variables*/, formula_debugger * /*fdb*/) const {
|
||||
return variant();
|
||||
|
@ -427,6 +513,12 @@ class integer_expression : public formula_expression {
|
|||
public:
|
||||
explicit integer_expression(int i) : i_(i)
|
||||
{}
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << i_;
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& /*variables*/, formula_debugger * /*fdb*/) const {
|
||||
return variant(i_);
|
||||
|
@ -439,6 +531,13 @@ class decimal_expression : public formula_expression {
|
|||
public:
|
||||
explicit decimal_expression(int i, int f) : i_(i), f_(f)
|
||||
{}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << i_ << '.' << f_;
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& /*variables*/, formula_debugger * /*fdb*/) const {
|
||||
return variant(i_ * 1000 + f_, variant::DECIMAL_VARIANT );
|
||||
|
@ -474,6 +573,11 @@ public:
|
|||
|
||||
str_ = variant(str);
|
||||
}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
return str_.as_string();
|
||||
}
|
||||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
if(subs_.empty()) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "formula_debugger.hpp"
|
||||
#include "formula_debugger_fwd.hpp"
|
||||
#include "formula_fwd.hpp"
|
||||
#include "formula_tokenizer.hpp"
|
||||
#include "variant.hpp"
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
variant evaluate(const formula_callable& variables, formula_debugger *fdb = NULL) const
|
||||
{
|
||||
if (fdb!=NULL) {
|
||||
return fdb->evaluate_formula_callback(*this,variables);
|
||||
return evaluate_formula_callback(*fdb,*this,variables);
|
||||
} else {
|
||||
return execute(variables,fdb);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public:
|
|||
variant evaluate(formula_debugger *fdb = NULL) const
|
||||
{
|
||||
if (fdb!=NULL) {
|
||||
return fdb->evaluate_formula_callback(*this);
|
||||
return evaluate_formula_callback(*fdb,*this);
|
||||
} else {
|
||||
return execute(fdb);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,11 @@
|
|||
#include "formula_debugger.hpp"
|
||||
#include "formula.hpp"
|
||||
#include "formula_function.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "log.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "gui/dialogs/formula_debugger.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
@ -33,14 +37,9 @@ static lg::log_domain log_formula_debugger("ai/debug/formula");
|
|||
|
||||
namespace game_logic {
|
||||
|
||||
debug_info::debug_info()
|
||||
: arg_number_(-1),f_name_(""),valid_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
debug_info::debug_info(int arg_number, const char *f_name, bool valid)
|
||||
: arg_number_(arg_number), f_name_(f_name), valid_(valid)
|
||||
debug_info::debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
|
||||
: arg_number_(arg_number), counter_(counter), level_(level), name_(name), str_(str), value_(value), evaluated_(evaluated)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -50,25 +49,58 @@ debug_info::~debug_info()
|
|||
}
|
||||
|
||||
|
||||
const char* debug_info::name()
|
||||
int debug_info::level() const
|
||||
{
|
||||
if (valid_ && (f_name_!=NULL) ) {
|
||||
return f_name_;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return level_;
|
||||
}
|
||||
|
||||
const std::string& debug_info::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
void debug_info::invalidate()
|
||||
int debug_info::counter() const
|
||||
{
|
||||
valid_ = false;
|
||||
return counter_;
|
||||
}
|
||||
|
||||
|
||||
const variant& debug_info::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
|
||||
void debug_info::set_value(const variant &value)
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
|
||||
bool debug_info::evaluated() const
|
||||
{
|
||||
return evaluated_;
|
||||
}
|
||||
|
||||
|
||||
void debug_info::set_evaluated(bool evaluated)
|
||||
{
|
||||
evaluated_ = evaluated;
|
||||
}
|
||||
|
||||
|
||||
const std::string& debug_info::str() const
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
|
||||
formula_debugger::formula_debugger()
|
||||
: counter_(0), info_()
|
||||
: call_stack_(), counter_(0), current_breakpoint_(), breakpoints_(), execution_trace_(),arg_number_extra_debug_info(-1), f_name_extra_debug_info("")
|
||||
{
|
||||
add_breakpoint_step_into();
|
||||
add_breakpoint_continue_to_end();
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,52 +109,284 @@ formula_debugger::~formula_debugger()
|
|||
}
|
||||
|
||||
|
||||
static void msg(int counter, const char *act, const char *name, const char *formula_str, const char *to="", const char *result = "")
|
||||
static void msg(const char *act, debug_info &i, const char *to="", const char *result = "")
|
||||
{
|
||||
DBG_FDB << "#" << counter << act << std::endl <<" \""<< name << "\"='" << formula_str << "' " << to << result << std::endl;
|
||||
DBG_FDB << "#" << i.counter() << act << std::endl <<" \""<< i.name().c_str() << "\"='" << i.str().c_str() << "' " << to << result << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::add_debug_info(int arg_number, const char *f_name)
|
||||
{
|
||||
info_ = debug_info(arg_number,f_name, true);
|
||||
arg_number_extra_debug_info = arg_number;
|
||||
f_name_extra_debug_info = f_name;
|
||||
}
|
||||
|
||||
|
||||
const std::deque<debug_info>& formula_debugger::get_call_stack() const
|
||||
{
|
||||
return call_stack_;
|
||||
}
|
||||
|
||||
|
||||
const breakpoint_ptr formula_debugger::get_current_breakpoint() const
|
||||
{
|
||||
return current_breakpoint_;
|
||||
}
|
||||
|
||||
const std::deque<debug_info>& formula_debugger::get_execution_trace() const
|
||||
{
|
||||
return execution_trace_;
|
||||
}
|
||||
|
||||
void formula_debugger::check_breakpoints()
|
||||
{
|
||||
for( std::deque< breakpoint_ptr >::iterator b = breakpoints_.begin(); b!= breakpoints_.end(); b++) {
|
||||
if ((*b)->is_break_now()){
|
||||
current_breakpoint_ = (*b);
|
||||
show_gui();
|
||||
current_breakpoint_ = breakpoint_ptr();
|
||||
if ((*b)->is_one_time_only()) {
|
||||
breakpoints_.erase(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void formula_debugger::show_gui()
|
||||
{
|
||||
if (resources::screen == NULL) {
|
||||
WRN_FDB << "do not showing debug window due to NULL gui" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (gui2::new_widgets) {
|
||||
gui2::tformula_debugger debug_dialog(*this);
|
||||
debug_dialog.show(resources::screen->video());
|
||||
} else {
|
||||
WRN_FDB << "do not showing debug window due to disabled --new-widgets"<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void formula_debugger::call_stack_push(const std::string &str)
|
||||
{
|
||||
call_stack_.push_back(debug_info(arg_number_extra_debug_info,counter_++,call_stack_.size(),f_name_extra_debug_info,str,variant(),false));
|
||||
arg_number_extra_debug_info = -1;
|
||||
f_name_extra_debug_info = "";
|
||||
execution_trace_.push_back(call_stack_.back());
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::call_stack_pop()
|
||||
{
|
||||
execution_trace_.push_back(call_stack_.back());
|
||||
call_stack_.pop_back();
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::call_stack_set_evaluated(bool evaluated)
|
||||
{
|
||||
call_stack_.back().set_evaluated(evaluated);
|
||||
}
|
||||
|
||||
void formula_debugger::call_stack_set_value(const variant &v)
|
||||
{
|
||||
call_stack_.back().set_value(v);
|
||||
}
|
||||
|
||||
variant formula_debugger::evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables)
|
||||
{
|
||||
int counter = counter_++;
|
||||
debug_info i = info_;
|
||||
info_.invalidate();
|
||||
msg(counter," evaluating expression: ",i.name(),"");
|
||||
variant v = expression.execute(variables,this); //work-in-progress
|
||||
msg(counter," evaluated expression: ",i.name(),""," to ",v.to_debug_string(NULL,true).c_str());
|
||||
call_stack_push(expression.str());
|
||||
check_breakpoints();
|
||||
msg(" evaluating expression: ",call_stack_.back());
|
||||
variant v = expression.execute(variables,this);
|
||||
call_stack_set_value(v);
|
||||
call_stack_set_evaluated(true);
|
||||
msg(" evaluated expression: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
|
||||
check_breakpoints();
|
||||
call_stack_pop();
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
variant formula_debugger::evaluate_formula_callback(const formula &f, const formula_callable &variables)
|
||||
{
|
||||
int counter = counter_++;
|
||||
debug_info i = info_;
|
||||
info_.invalidate();
|
||||
msg(counter," evaluating formula: ",i.name(),f.str().c_str());
|
||||
variant v = f.execute(variables,this); //work-in-progress
|
||||
msg(counter," evaluated formula: ",i.name(),f.str().c_str()," to ",v.to_debug_string(NULL,true).c_str());
|
||||
call_stack_push(f.str());
|
||||
check_breakpoints();
|
||||
msg(" evaluating formula: ",call_stack_.back());
|
||||
variant v = f.execute(variables,this);
|
||||
call_stack_set_value(v);
|
||||
call_stack_set_evaluated(true);
|
||||
msg(" evaluated formula: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
|
||||
check_breakpoints();
|
||||
call_stack_pop();
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
variant formula_debugger::evaluate_formula_callback(const formula &f)
|
||||
{
|
||||
int counter = counter_++;
|
||||
debug_info i = info_;
|
||||
info_.invalidate();
|
||||
msg(counter," evaluating formula without variables: ",i.name(),f.str().c_str());
|
||||
variant v = f.execute(this); //work-in-progress
|
||||
msg(counter," evaluating formula without variables: ",i.name(),f.str().c_str(),v.to_debug_string(NULL,true).c_str());
|
||||
call_stack_push(f.str());
|
||||
check_breakpoints();
|
||||
msg(" evaluating formula without variables: ",call_stack_.back());
|
||||
variant v = f.execute(this);
|
||||
call_stack_set_value(v);
|
||||
call_stack_set_evaluated(true);
|
||||
msg(" evaluated formula without variables: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
|
||||
check_breakpoints();
|
||||
call_stack_pop();
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
base_breakpoint::base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
|
||||
: fdb_(fdb), name_(name), one_time_only_(one_time_only)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
base_breakpoint::~base_breakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool base_breakpoint::is_one_time_only() const
|
||||
{
|
||||
return one_time_only_;
|
||||
}
|
||||
|
||||
|
||||
const std::string& base_breakpoint::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
class end_breakpoint : public base_breakpoint {
|
||||
public:
|
||||
end_breakpoint(formula_debugger &fdb)
|
||||
: base_breakpoint(fdb,"End", true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~end_breakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_break_now() const
|
||||
{
|
||||
const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
|
||||
if ((call_stack.size() == 1) && (call_stack[0].evaluated()) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class step_in_breakpoint : public base_breakpoint {
|
||||
public:
|
||||
step_in_breakpoint(formula_debugger &fdb)
|
||||
: base_breakpoint(fdb,"Step",true)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~step_in_breakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_break_now() const
|
||||
{
|
||||
const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
|
||||
if (call_stack.empty() || call_stack.back().evaluated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class step_out_breakpoint : public base_breakpoint {
|
||||
public:
|
||||
step_out_breakpoint(formula_debugger &fdb)
|
||||
: base_breakpoint(fdb,"Step out",true), level_(fdb.get_call_stack().size()-1)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~step_out_breakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_break_now() const
|
||||
{
|
||||
const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
|
||||
if (call_stack.empty() || call_stack.back().evaluated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (call_stack.size() == level_) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
size_t level_;
|
||||
};
|
||||
|
||||
|
||||
class next_breakpoint : public base_breakpoint {
|
||||
public:
|
||||
next_breakpoint(formula_debugger &fdb)
|
||||
: base_breakpoint(fdb,"Next",true), level_(fdb.get_call_stack().size())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~next_breakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_break_now() const
|
||||
{
|
||||
const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
|
||||
if (call_stack.empty() || call_stack.back().evaluated()) {
|
||||
return false;
|
||||
}
|
||||
if (call_stack.size() == level_) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
size_t level_;
|
||||
};
|
||||
|
||||
|
||||
void formula_debugger::add_breakpoint_continue_to_end()
|
||||
{
|
||||
breakpoints_.push_back(breakpoint_ptr(new end_breakpoint(*this)));
|
||||
LOG_FDB << "added 'end' breakpoint"<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::add_breakpoint_step_into()
|
||||
{
|
||||
breakpoints_.push_back(breakpoint_ptr(new step_in_breakpoint(*this)));
|
||||
LOG_FDB << "added 'step into' breakpoint"<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::add_breakpoint_step_out()
|
||||
{
|
||||
breakpoints_.push_back(breakpoint_ptr(new step_out_breakpoint(*this)));
|
||||
LOG_FDB << "added 'step out' breakpoint"<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
void formula_debugger::add_breakpoint_next()
|
||||
{
|
||||
breakpoints_.push_back(breakpoint_ptr(new next_breakpoint(*this)));
|
||||
LOG_FDB << "added 'next' breakpoint"<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace game_logic
|
||||
|
|
|
@ -25,45 +25,116 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include "variant.hpp"
|
||||
#include "formula_debugger_fwd.hpp"
|
||||
#include <deque>
|
||||
|
||||
namespace game_logic {
|
||||
|
||||
class formula_expression;
|
||||
class formula_callable;
|
||||
class formula;
|
||||
class formula_debugger;
|
||||
|
||||
class debug_info {
|
||||
public:
|
||||
debug_info();
|
||||
debug_info(int arg_number, const char *f_name, bool valid);
|
||||
debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated);
|
||||
virtual ~debug_info();
|
||||
const char* name();
|
||||
void invalidate();
|
||||
int counter() const;
|
||||
int level() const;
|
||||
const std::string& name() const;
|
||||
const std::string& str() const;
|
||||
const variant& value() const;
|
||||
const std::string& value_str() const;
|
||||
bool evaluated() const;
|
||||
void set_evaluated(bool evaluated);
|
||||
void set_value(const variant &value);
|
||||
private:
|
||||
int arg_number_;
|
||||
const char *f_name_;
|
||||
bool valid_;
|
||||
int counter_;
|
||||
int level_;
|
||||
std::string name_;
|
||||
std::string str_;
|
||||
variant value_;
|
||||
bool evaluated_;
|
||||
|
||||
};
|
||||
|
||||
class base_breakpoint {
|
||||
public:
|
||||
base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only);
|
||||
virtual ~base_breakpoint();
|
||||
virtual bool is_break_now() const = 0;
|
||||
bool is_one_time_only() const;
|
||||
const std::string &name() const;
|
||||
protected:
|
||||
formula_debugger &fdb_;
|
||||
std::string name_;
|
||||
bool one_time_only_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class formula_debugger {
|
||||
public:
|
||||
formula_debugger();
|
||||
|
||||
|
||||
virtual ~formula_debugger();
|
||||
|
||||
|
||||
virtual void add_debug_info(int arg_number, const char *f_name);
|
||||
void add_debug_info(int arg_number, const char *f_name);
|
||||
|
||||
|
||||
virtual variant evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables);
|
||||
void call_stack_push(const std::string &str);
|
||||
|
||||
|
||||
void call_stack_pop();
|
||||
|
||||
|
||||
void call_stack_set_evaluated(bool evaluated);
|
||||
|
||||
|
||||
virtual variant evaluate_formula_callback(const formula &f, const formula_callable &variables);
|
||||
void call_stack_set_value(const variant &v);
|
||||
|
||||
|
||||
virtual variant evaluate_formula_callback(const formula &f);
|
||||
void check_breakpoints();
|
||||
|
||||
|
||||
const std::deque<debug_info>& get_call_stack() const;
|
||||
|
||||
|
||||
const breakpoint_ptr get_current_breakpoint() const;
|
||||
|
||||
|
||||
const std::deque<debug_info>& get_execution_trace() const;
|
||||
|
||||
|
||||
variant evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables);
|
||||
|
||||
|
||||
variant evaluate_formula_callback(const formula &f, const formula_callable &variables);
|
||||
|
||||
|
||||
variant evaluate_formula_callback(const formula &f);
|
||||
|
||||
|
||||
void show_gui();
|
||||
|
||||
|
||||
void add_breakpoint_continue_to_end();
|
||||
|
||||
|
||||
void add_breakpoint_step_into();
|
||||
|
||||
|
||||
void add_breakpoint_step_out();
|
||||
|
||||
|
||||
void add_breakpoint_next();
|
||||
|
||||
|
||||
//static functions
|
||||
|
||||
static formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const char *f_name)
|
||||
{
|
||||
if (fdb==NULL) {
|
||||
|
@ -74,8 +145,15 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::deque<debug_info> call_stack_;
|
||||
int counter_;
|
||||
debug_info info_;
|
||||
breakpoint_ptr current_breakpoint_;
|
||||
std::deque< breakpoint_ptr > breakpoints_;
|
||||
std::deque<debug_info> execution_trace_;
|
||||
int arg_number_extra_debug_info;
|
||||
const char *f_name_extra_debug_info;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
54
src/formula_debugger_fwd.cpp
Normal file
54
src/formula_debugger_fwd.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file formula_debugger_fwd.cpp
|
||||
* Formula debugger - forward declaration and add_debug_info static function
|
||||
* */
|
||||
|
||||
|
||||
#include "formula_debugger_fwd.hpp"
|
||||
#include "formula_debugger.hpp"
|
||||
|
||||
namespace game_logic {
|
||||
|
||||
formula_debugger* add_debug_info(formula_debugger *fdb, int arg_number, const char *f_name)
|
||||
{
|
||||
if (fdb==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fdb->add_debug_info(arg_number,f_name);
|
||||
return fdb;
|
||||
}
|
||||
|
||||
|
||||
variant evaluate_arg_callback(formula_debugger &fdb, const formula_expression &expression, const formula_callable &variables)
|
||||
{
|
||||
return fdb.evaluate_arg_callback(expression,variables);
|
||||
}
|
||||
|
||||
|
||||
variant evaluate_formula_callback(formula_debugger &fdb, const formula &f, const formula_callable &variables)
|
||||
{
|
||||
return fdb.evaluate_formula_callback(f,variables);
|
||||
}
|
||||
|
||||
|
||||
variant evaluate_formula_callback(formula_debugger &fdb, const formula &f)
|
||||
{
|
||||
return fdb.evaluate_formula_callback(f);
|
||||
}
|
||||
|
||||
|
||||
} // end of namespace game_logic
|
57
src/formula_debugger_fwd.hpp
Normal file
57
src/formula_debugger_fwd.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file formula_debugger_fwd.hpp
|
||||
* Formula AI debugger, forward
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FORMULA_DEBUGGER_FWD_HPP_INCLUDED
|
||||
#define FORMULA_DEBUGGER_FWD_HPP_INCLUDED
|
||||
|
||||
#include "global.hpp"
|
||||
#include "variant.hpp"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <deque>
|
||||
|
||||
|
||||
class variant;
|
||||
|
||||
namespace game_logic {
|
||||
|
||||
class formula_debugger;
|
||||
class debug_info;
|
||||
class formula_expression;
|
||||
class formula;
|
||||
class formula_callable;
|
||||
|
||||
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);
|
||||
|
||||
variant evaluate_arg_callback(formula_debugger &fdb, const formula_expression &expression, const formula_callable &variables);
|
||||
|
||||
variant evaluate_formula_callback(formula_debugger &fdb, const formula &f, const formula_callable &variables);
|
||||
|
||||
variant evaluate_formula_callback(formula_debugger &fdb, const formula &f);
|
||||
|
||||
|
||||
} // end of namespace game_logic
|
||||
|
||||
#endif
|
|
@ -29,6 +29,25 @@ static lg::log_domain log_scripting_formula("scripting/formula");
|
|||
|
||||
namespace game_logic {
|
||||
|
||||
|
||||
std::string function_expression::str() const
|
||||
{
|
||||
std::stringstream s;
|
||||
s << get_name();
|
||||
s << '(';
|
||||
bool first_arg = true;
|
||||
foreach(expression_ptr a , args()) {
|
||||
if (!first_arg) {
|
||||
s << ',';
|
||||
} else {
|
||||
first_arg = false;
|
||||
}
|
||||
s << a->str();
|
||||
}
|
||||
s << ')';
|
||||
return s.str();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class dir_function : public function_expression {
|
||||
|
@ -813,8 +832,8 @@ public:
|
|||
private:
|
||||
variant execute(const formula_callable& variables, formula_debugger *fdb) const {
|
||||
return variant(new location_callable(map_location(
|
||||
args()[0]->evaluate(variables,formula_debugger::add_debug_info(fdb,0,"loc:x")).as_int()-1,
|
||||
args()[1]->evaluate(variables,formula_debugger::add_debug_info(fdb,1,"loc:y")).as_int()-1)));
|
||||
args()[0]->evaluate(variables,add_debug_info(fdb,0,"loc:x")).as_int()-1,
|
||||
args()[1]->evaluate(variables,add_debug_info(fdb,1,"loc:y")).as_int()-1)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2008 - 2009 by David White <dave@whitevine.net>
|
||||
|
@ -21,7 +22,7 @@
|
|||
|
||||
#include "formula.hpp"
|
||||
#include "formula_callable.hpp"
|
||||
#include "formula_debugger.hpp"
|
||||
#include "formula_debugger_fwd.hpp"
|
||||
#include "variant.hpp"
|
||||
|
||||
namespace game_logic {
|
||||
|
@ -33,7 +34,7 @@ public:
|
|||
variant evaluate(const formula_callable& variables, formula_debugger *fdb = NULL) const {
|
||||
call_stack_manager manager(name_);
|
||||
if (fdb!=NULL) {
|
||||
return fdb->evaluate_arg_callback(*this,variables);
|
||||
return evaluate_arg_callback(*fdb,*this,variables);
|
||||
} else {
|
||||
return execute(variables,fdb);
|
||||
}
|
||||
|
@ -41,6 +42,7 @@ public:
|
|||
void set_name(const char* name) { name_ = name; }
|
||||
|
||||
const char* get_name() const { return name_; }
|
||||
virtual std::string str() const = 0;
|
||||
private:
|
||||
virtual variant execute(const formula_callable& variables, formula_debugger *fdb = NULL) const = 0;
|
||||
const char* name_;
|
||||
|
@ -67,7 +69,7 @@ public:
|
|||
throw formula_error("Too many arguments", "", "", 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string str() const;
|
||||
protected:
|
||||
const args_list& args() const { return args_; }
|
||||
private:
|
||||
|
|
196
src/gui/dialogs/formula_debugger.cpp
Normal file
196
src/gui/dialogs/formula_debugger.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/dialogs/formula_debugger.hpp"
|
||||
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "../../foreach.hpp"
|
||||
#include "../../formula_debugger.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
//ugly hack, should be removed as soon as boost::bind works with tbutton callbacks
|
||||
static tformula_debugger *td;
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void formula_debugger_callback_continue_function(gui2::twidget *caller)
|
||||
{
|
||||
if (td==NULL) {
|
||||
return;
|
||||
}
|
||||
td->callback_continue_button(caller);
|
||||
}
|
||||
|
||||
void formula_debugger_callback_next_function(gui2::twidget *caller)
|
||||
{
|
||||
if (td==NULL) {
|
||||
return;
|
||||
}
|
||||
td->callback_next_button(caller);
|
||||
}
|
||||
|
||||
void formula_debugger_callback_step_function(gui2::twidget *caller)
|
||||
{
|
||||
if (td==NULL) {
|
||||
return;
|
||||
}
|
||||
td->callback_step_button(caller);
|
||||
}
|
||||
|
||||
void formula_debugger_callback_stepout_function(gui2::twidget *caller)
|
||||
{
|
||||
if (td==NULL) {
|
||||
return;
|
||||
}
|
||||
td->callback_stepout_button(caller);
|
||||
}
|
||||
|
||||
} //of namespace {
|
||||
|
||||
|
||||
twindow* tformula_debugger::build_window(CVideo& video)
|
||||
{
|
||||
return build(video, get_id(FORMULA_DEBUGGER));
|
||||
}
|
||||
|
||||
void tformula_debugger::pre_show(CVideo& /*video*/, twindow& window)
|
||||
{
|
||||
//hack
|
||||
td = this;
|
||||
|
||||
// stack label
|
||||
tcontrol* stack_label =
|
||||
dynamic_cast<tcontrol*>(window.find_widget("stack", false));
|
||||
VALIDATE(stack_label, missing_widget("stack"));
|
||||
|
||||
std::stringstream stack_text;
|
||||
std::string indent = " ";
|
||||
int c = 0;
|
||||
foreach (const game_logic::debug_info &i, fdb_.get_call_stack()) {
|
||||
for (int d=0; d<c; d++) {
|
||||
stack_text << indent;
|
||||
}
|
||||
stack_text << "#<span color=\"green\">" << i.counter() <<"</span>: \"<span color=\"green\">"<< i.name() << "</span>\": '" << i.str() << "' " << std::endl;
|
||||
c++;
|
||||
}
|
||||
|
||||
stack_label->set_markup_mode(tcontrol::PANGO_MARKUP);
|
||||
stack_label->set_label(stack_text.str());
|
||||
window.keyboard_capture(stack_label);
|
||||
|
||||
// execution trace label
|
||||
|
||||
tcontrol* execution_label =
|
||||
dynamic_cast<tcontrol*>(window.find_widget("execution", false));
|
||||
VALIDATE(execution_label, missing_widget("execution"));
|
||||
|
||||
std::stringstream execution_text;
|
||||
foreach (const game_logic::debug_info &i, fdb_.get_execution_trace()) {
|
||||
for (int d=0; d<i.level(); d++) {
|
||||
execution_text << indent;
|
||||
}
|
||||
if (!i.evaluated() ) {
|
||||
execution_text << "#<span color=\"green\">" << i.counter() <<"</span>: \"<span color=\"green\">"<< i.name() << "</span>\": '" << 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,true) <<"</span>" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
execution_label->set_markup_mode(tcontrol::PANGO_MARKUP);
|
||||
execution_label->set_label(execution_text.str());
|
||||
|
||||
// state
|
||||
std::string state_str;
|
||||
bool is_end = false;
|
||||
if (!fdb_.get_current_breakpoint()) {
|
||||
state_str = "";
|
||||
} else {
|
||||
state_str = fdb_.get_current_breakpoint()->name();
|
||||
if (state_str=="End") {
|
||||
is_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
tcontrol* state_label =
|
||||
dynamic_cast<tcontrol*>(window.find_widget("state", false));
|
||||
VALIDATE(state_label, missing_widget("state"));
|
||||
state_label->set_label(state_str);
|
||||
|
||||
// callbacks
|
||||
|
||||
tbutton* step_button =
|
||||
dynamic_cast<tbutton*>(window.find_widget("step", false));
|
||||
VALIDATE(step_button, missing_widget("step"));
|
||||
|
||||
step_button->set_callback_mouse_left_click(formula_debugger_callback_step_function);
|
||||
|
||||
tbutton* stepout_button =
|
||||
dynamic_cast<tbutton*>(window.find_widget("stepout", false));
|
||||
VALIDATE(stepout_button, missing_widget("stepout"));
|
||||
stepout_button->set_callback_mouse_left_click(formula_debugger_callback_stepout_function);
|
||||
|
||||
tbutton* next_button =
|
||||
dynamic_cast<tbutton*>(window.find_widget("next", false));
|
||||
VALIDATE(next_button, missing_widget("next"));
|
||||
next_button->set_callback_mouse_left_click(formula_debugger_callback_next_function);
|
||||
|
||||
tbutton* continue_button =
|
||||
dynamic_cast<tbutton*>(window.find_widget("continue", false));
|
||||
VALIDATE(continue_button, missing_widget("continue"));
|
||||
continue_button->set_callback_mouse_left_click(formula_debugger_callback_continue_function);
|
||||
|
||||
|
||||
if (is_end) {
|
||||
step_button->set_active(false);
|
||||
stepout_button->set_active(false);
|
||||
next_button->set_active(false);
|
||||
continue_button->set_active(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void tformula_debugger::callback_continue_button(gui2::twidget* caller)
|
||||
{
|
||||
fdb_.add_breakpoint_continue_to_end();
|
||||
caller->get_window()->set_retval(twindow::OK);
|
||||
}
|
||||
|
||||
void tformula_debugger::callback_next_button(gui2::twidget* caller)
|
||||
{
|
||||
fdb_.add_breakpoint_next();
|
||||
caller->get_window()->set_retval(twindow::OK);
|
||||
}
|
||||
|
||||
void tformula_debugger::callback_step_button(gui2::twidget* caller)
|
||||
{
|
||||
fdb_.add_breakpoint_step_into();
|
||||
caller->get_window()->set_retval(twindow::OK);
|
||||
}
|
||||
|
||||
void tformula_debugger::callback_stepout_button(gui2::twidget* caller)
|
||||
{
|
||||
fdb_.add_breakpoint_step_out();
|
||||
caller->get_window()->set_retval(twindow::OK);
|
||||
}
|
||||
|
||||
} //end of namespace gui2
|
58
src/gui/dialogs/formula_debugger.hpp
Normal file
58
src/gui/dialogs/formula_debugger.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Yurii Chernyi <terraninfo@terraninfo.net>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef GUI_DIALOGS_FORMULA_DEBUGGER_HPP_INCLUDED
|
||||
#define GUI_DIALOGS_FORMULA_DEBUGGER_HPP_INCLUDED
|
||||
|
||||
#include "gui/dialogs/dialog.hpp"
|
||||
|
||||
namespace game_logic {
|
||||
class formula_debugger;
|
||||
}
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
class tformula_debugger : public tdialog
|
||||
{
|
||||
public:
|
||||
tformula_debugger(game_logic::formula_debugger &fdb) :
|
||||
fdb_(fdb)
|
||||
{}
|
||||
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
twindow* build_window(CVideo& video);
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
void pre_show(CVideo& video, twindow& window);
|
||||
|
||||
|
||||
void callback_continue_button(gui2::twidget *caller);
|
||||
|
||||
|
||||
void callback_next_button(gui2::twidget *caller);
|
||||
|
||||
|
||||
void callback_step_button(gui2::twidget *caller);
|
||||
|
||||
|
||||
void callback_stepout_button(gui2::twidget *caller);
|
||||
|
||||
private:
|
||||
game_logic::formula_debugger &fdb_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ! GUI_DIALOGS_FORMULA_DEBUGGER_HPP_INCLUDED */
|
|
@ -102,6 +102,7 @@ static void fill_window_types()
|
|||
window_type_list[LOBBY_MAIN] = "lobby_main";
|
||||
window_type_list[LOBBY_PLAYER_INFO] = "lobby_player_info";
|
||||
window_type_list[UNIT_CREATE] = "unit_create";
|
||||
window_type_list[FORMULA_DEBUGGER] = "formula_debugger";
|
||||
}
|
||||
|
||||
const std::string& get_id(const twindow_type window_type)
|
||||
|
|
|
@ -75,6 +75,7 @@ enum twindow_type {
|
|||
LOBBY_MAIN, /**< Main MP lobby screen */
|
||||
LOBBY_PLAYER_INFO, /**< MP lobby player info dialog */
|
||||
UNIT_CREATE, /**< Debug-mode unit creation dialog */
|
||||
FORMULA_DEBUGGER, /**< Formula debugger dialog */
|
||||
COUNT /**<
|
||||
* The last one to hold the number of items and as
|
||||
* sentinel.
|
||||
|
|
Loading…
Add table
Reference in a new issue