formula_debugger.cpp

Go to the documentation of this file.
00001 /* $Id: formula_debugger.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Yurii Chernyi <terraninfo@terraninfo.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * Formula debugger - implementation
00019  * */
00020 
00021 
00022 #include "formula_debugger.hpp"
00023 #include "formula.hpp"
00024 #include "formula_function.hpp"
00025 #include "game_display.hpp"
00026 #include "log.hpp"
00027 #include "resources.hpp"
00028 #include "gui/dialogs/formula_debugger.hpp"
00029 #include "gui/widgets/settings.hpp"
00030 
00031 #include <boost/lexical_cast.hpp>
00032 
00033 static lg::log_domain log_formula_debugger("ai/debug/formula");
00034 #define DBG_FDB LOG_STREAM(debug, log_formula_debugger)
00035 #define LOG_FDB LOG_STREAM(info, log_formula_debugger)
00036 #define WRN_FDB LOG_STREAM(warn, log_formula_debugger)
00037 #define ERR_FDB LOG_STREAM(err, log_formula_debugger)
00038 
00039 namespace game_logic {
00040 
00041 
00042 debug_info::debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
00043     : arg_number_(arg_number), counter_(counter), level_(level), name_(name), str_(str), value_(value), evaluated_(evaluated)
00044 {
00045 }
00046 
00047 
00048 debug_info::~debug_info()
00049 {
00050 }
00051 
00052 
00053 int debug_info::level() const
00054 {
00055     return level_;
00056 }
00057 
00058 const std::string& debug_info::name() const
00059 {
00060     return name_;
00061 }
00062 
00063 
00064 int debug_info::counter() const
00065 {
00066     return counter_;
00067 }
00068 
00069 
00070 const variant& debug_info::value() const
00071 {
00072     return value_;
00073 }
00074 
00075 
00076 void debug_info::set_value(const variant &value)
00077 {
00078     value_ = value;
00079 }
00080 
00081 
00082 bool debug_info::evaluated() const
00083 {
00084     return evaluated_;
00085 }
00086 
00087 
00088 void debug_info::set_evaluated(bool evaluated)
00089 {
00090         evaluated_ = evaluated;
00091 }
00092 
00093 
00094 const std::string& debug_info::str() const
00095 {
00096     return str_;
00097 }
00098 
00099 
00100 formula_debugger::formula_debugger()
00101     : call_stack_(), counter_(0), current_breakpoint_(), breakpoints_(), execution_trace_(),arg_number_extra_debug_info(-1), f_name_extra_debug_info("")
00102 {
00103     add_breakpoint_step_into();
00104     add_breakpoint_continue_to_end();
00105 }
00106 
00107 
00108 formula_debugger::~formula_debugger()
00109 {
00110 }
00111 
00112 
00113 static void msg(const char *act, debug_info &i, const char *to="", const char *result = "")
00114 {
00115     DBG_FDB << "#" << i.counter() << act << std::endl <<"     \""<< i.name().c_str() << "\"='" << i.str().c_str() << "' " << to << result << std::endl;
00116 }
00117 
00118 
00119 void formula_debugger::add_debug_info(int arg_number, const char *f_name)
00120 {
00121     arg_number_extra_debug_info = arg_number;
00122     f_name_extra_debug_info = f_name;
00123 }
00124 
00125 
00126 const std::deque<debug_info>& formula_debugger::get_call_stack() const
00127 {
00128     return call_stack_;
00129 }
00130 
00131 
00132 const breakpoint_ptr formula_debugger::get_current_breakpoint() const
00133 {
00134     return current_breakpoint_;
00135 }
00136 
00137 const std::deque<debug_info>& formula_debugger::get_execution_trace() const
00138 {
00139     return execution_trace_;
00140 }
00141 
00142 void formula_debugger::check_breakpoints()
00143 {
00144     for( std::deque< breakpoint_ptr >::iterator b = breakpoints_.begin(); b!= breakpoints_.end(); ++b) {
00145         if ((*b)->is_break_now()){
00146             current_breakpoint_ = (*b);
00147             show_gui();
00148             current_breakpoint_ = breakpoint_ptr();
00149             if ((*b)->is_one_time_only()) {
00150                 breakpoints_.erase(b);
00151             }
00152             break;
00153         }
00154     }
00155 }
00156 
00157 void formula_debugger::show_gui()
00158 {
00159     if (resources::screen == NULL) {
00160         WRN_FDB << "do not showing debug window due to NULL gui" << std::endl;
00161         return;
00162     }
00163     if (gui2::new_widgets) {
00164         gui2::tformula_debugger debug_dialog(*this);
00165         debug_dialog.show(resources::screen->video());
00166     } else {
00167         WRN_FDB << "do not showing debug window due to disabled --new-widgets"<< std::endl;
00168     }
00169 }
00170 
00171 void formula_debugger::call_stack_push(const std::string &str)
00172 {
00173     call_stack_.push_back(debug_info(arg_number_extra_debug_info,counter_++,call_stack_.size(),f_name_extra_debug_info,str,variant(),false));
00174     arg_number_extra_debug_info = -1;
00175     f_name_extra_debug_info = "";
00176     execution_trace_.push_back(call_stack_.back());
00177 }
00178 
00179 
00180 void formula_debugger::call_stack_pop()
00181 {
00182     execution_trace_.push_back(call_stack_.back());
00183     call_stack_.pop_back();
00184 }
00185 
00186 
00187 void formula_debugger::call_stack_set_evaluated(bool evaluated)
00188 {
00189     call_stack_.back().set_evaluated(evaluated);
00190 }
00191 
00192 void formula_debugger::call_stack_set_value(const variant &v)
00193 {
00194     call_stack_.back().set_value(v);
00195 }
00196 
00197 variant formula_debugger::evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables)
00198 {
00199     call_stack_push(expression.str());
00200     check_breakpoints();
00201     msg(" evaluating expression: ",call_stack_.back());
00202     variant v = expression.execute(variables,this);
00203     call_stack_set_value(v);
00204     call_stack_set_evaluated(true);
00205     msg(" evaluated expression: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
00206     check_breakpoints();
00207     call_stack_pop();
00208     return v;
00209 }
00210 
00211 
00212 variant formula_debugger::evaluate_formula_callback(const formula &f, const formula_callable &variables)
00213 {
00214     call_stack_push(f.str());
00215     check_breakpoints();
00216     msg(" evaluating formula: ",call_stack_.back());
00217     variant v = f.execute(variables,this);
00218     call_stack_set_value(v);
00219     call_stack_set_evaluated(true);
00220     msg(" evaluated formula: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
00221     check_breakpoints();
00222     call_stack_pop();
00223     return v;
00224 }
00225 
00226 
00227 variant formula_debugger::evaluate_formula_callback(const formula &f)
00228 {
00229     call_stack_push(f.str());
00230     check_breakpoints();
00231     msg(" evaluating formula without variables: ",call_stack_.back());
00232     variant v = f.execute(this);
00233     call_stack_set_value(v);
00234     call_stack_set_evaluated(true);
00235     msg(" evaluated formula without variables: ",call_stack_.back()," to ",v.to_debug_string(NULL,true).c_str());
00236     check_breakpoints();
00237     call_stack_pop();
00238     return v;
00239 }
00240 
00241 
00242 base_breakpoint::base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
00243     : fdb_(fdb), name_(name), one_time_only_(one_time_only)
00244 {
00245 
00246 }
00247 
00248 
00249 base_breakpoint::~base_breakpoint()
00250 {
00251 }
00252 
00253 
00254 bool base_breakpoint::is_one_time_only() const
00255 {
00256     return one_time_only_;
00257 }
00258 
00259 
00260 const std::string& base_breakpoint::name() const
00261 {
00262     return name_;
00263 }
00264 
00265 class end_breakpoint : public base_breakpoint {
00266 public:
00267     end_breakpoint(formula_debugger &fdb)
00268         : base_breakpoint(fdb,"End", true)
00269     {
00270     }
00271 
00272     virtual ~end_breakpoint()
00273     {
00274     }
00275 
00276     virtual bool is_break_now() const
00277     {
00278         const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
00279         if ((call_stack.size() == 1) && (call_stack[0].evaluated()) ) {
00280             return true;
00281         }
00282         return false;
00283     }
00284 };
00285 
00286 
00287 class step_in_breakpoint : public base_breakpoint {
00288 public:
00289     step_in_breakpoint(formula_debugger &fdb)
00290         : base_breakpoint(fdb,"Step",true)
00291     {
00292     }
00293 
00294     virtual ~step_in_breakpoint()
00295     {
00296     }
00297 
00298     virtual bool is_break_now() const
00299     {
00300         const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
00301         if (call_stack.empty() || call_stack.back().evaluated()) {
00302             return false;
00303         }
00304 
00305         return true;
00306     }
00307 };
00308 
00309 
00310 class step_out_breakpoint : public base_breakpoint {
00311 public:
00312     step_out_breakpoint(formula_debugger &fdb)
00313         : base_breakpoint(fdb,"Step out",true), level_(fdb.get_call_stack().size()-1)
00314     {
00315     }
00316 
00317     virtual ~step_out_breakpoint()
00318     {
00319     }
00320 
00321     virtual bool is_break_now() const
00322     {
00323         const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
00324         if (call_stack.empty() || call_stack.back().evaluated()) {
00325             return false;
00326         }
00327 
00328         if (call_stack.size() == level_) {
00329             return true;
00330         }
00331         return false;
00332     }
00333 private:
00334     size_t level_;
00335 };
00336 
00337 
00338 class next_breakpoint : public base_breakpoint {
00339 public:
00340     next_breakpoint(formula_debugger &fdb)
00341         : base_breakpoint(fdb,"Next",true), level_(fdb.get_call_stack().size())
00342     {
00343     }
00344 
00345     virtual ~next_breakpoint()
00346     {
00347     }
00348 
00349     virtual bool is_break_now() const
00350     {
00351         const std::deque<debug_info> &call_stack = fdb_.get_call_stack();
00352         if (call_stack.empty() || call_stack.back().evaluated()) {
00353             return false;
00354         }
00355         if (call_stack.size() == level_) {
00356             return true;
00357         }
00358         return false;
00359     }
00360 private:
00361     size_t level_;
00362 };
00363 
00364 
00365 void formula_debugger::add_breakpoint_continue_to_end()
00366 {
00367     breakpoints_.push_back(breakpoint_ptr(new end_breakpoint(*this)));
00368     LOG_FDB << "added 'end' breakpoint"<< std::endl;
00369 }
00370 
00371 
00372 void formula_debugger::add_breakpoint_step_into()
00373 {
00374         breakpoints_.push_back(breakpoint_ptr(new step_in_breakpoint(*this)));
00375     LOG_FDB << "added 'step into' breakpoint"<< std::endl;
00376 }
00377 
00378 
00379 void formula_debugger::add_breakpoint_step_out()
00380 {
00381     breakpoints_.push_back(breakpoint_ptr(new step_out_breakpoint(*this)));
00382     LOG_FDB << "added 'step out' breakpoint"<< std::endl;
00383 }
00384 
00385 
00386 void formula_debugger::add_breakpoint_next()
00387 {
00388     breakpoints_.push_back(breakpoint_ptr(new next_breakpoint(*this)));
00389     LOG_FDB << "added 'next' breakpoint"<< std::endl;
00390 }
00391 
00392 
00393 } // end of namespace game_logic
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:36 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs