The Battle for Wesnoth  1.15.0-dev
debugger.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Formula debugger - implementation
18  * */
19 
20 
21 #include "formula/debugger.hpp"
22 #include "formula/formula.hpp"
23 #include "formula/function.hpp"
24 #include "game_display.hpp"
25 #include "log.hpp"
27 
28 static lg::log_domain log_formula_debugger("scripting/formula/debug");
29 #define DBG_FDB LOG_STREAM(debug, log_formula_debugger)
30 #define LOG_FDB LOG_STREAM(info, log_formula_debugger)
31 #define WRN_FDB LOG_STREAM(warn, log_formula_debugger)
32 #define ERR_FDB LOG_STREAM(err, log_formula_debugger)
33 
34 namespace wfl {
35 
36 
37 debug_info::debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
38  : arg_number_(arg_number), counter_(counter), level_(level), name_(name), str_(str), value_(value), evaluated_(evaluated)
39 {
40 }
41 
42 
44 {
45 }
46 
47 
48 int debug_info::level() const
49 {
50  return level_;
51 }
52 
53 const std::string& debug_info::name() const
54 {
55  return name_;
56 }
57 
58 
60 {
61  return counter_;
62 }
63 
64 
65 const variant& debug_info::value() const
66 {
67  return value_;
68 }
69 
70 
72 {
73  value_ = value;
74 }
75 
76 
78 {
79  return evaluated_;
80 }
81 
82 
84 {
86 }
87 
88 
89 const std::string& debug_info::str() const
90 {
91  return str_;
92 }
93 
94 
96  : call_stack_(), counter_(0), current_breakpoint_(), breakpoints_(), execution_trace_(),arg_number_extra_debug_info(-1), f_name_extra_debug_info("")
97 {
100 }
101 
102 
104 {
105 }
106 
107 
108 static void msg(const char *act, debug_info &i, const char *to="", const char *result = "")
109 {
110  DBG_FDB << "#" << i.counter() << act << std::endl <<" \""<< i.name() << "\"='" << i.str() << "' " << to << result << std::endl;
111 }
112 
113 
114 void formula_debugger::add_debug_info(int arg_number, const std::string& f_name)
115 {
116  arg_number_extra_debug_info = arg_number;
117  f_name_extra_debug_info = f_name;
118 }
119 
120 
121 const std::list<debug_info>& formula_debugger::get_call_stack() const
122 {
123  return call_stack_;
124 }
125 
126 
128 {
129  return current_breakpoint_;
130 }
131 
132 const std::list<debug_info>& formula_debugger::get_execution_trace() const
133 {
134  return execution_trace_;
135 }
136 
138 {
139  for(std::list<breakpoint_ptr>::iterator b = breakpoints_.begin(); b != breakpoints_.end(); ++b) {
140  if ((*b)->is_break_now()){
141  current_breakpoint_ = (*b);
142  show_gui();
144  if ((*b)->is_one_time_only()) {
145  b = breakpoints_.erase(b);
146  }
147  break;
148  }
149  }
150 }
151 
153 {
154  if (game_display::get_singleton() == nullptr) {
155  WRN_FDB << "do not showing debug window due to nullptr gui" << std::endl;
156  return;
157  }
158  if (game_config::debug) {
159  gui2::dialogs::formula_debugger::display(*this);
160  } else {
161  WRN_FDB << "do not showing debug window due to disabled --new-widgets"<< std::endl;
162  }
163 }
164 
165 void formula_debugger::call_stack_push(const std::string &str)
166 {
170  execution_trace_.push_back(call_stack_.back());
171 }
172 
173 
175 {
176  execution_trace_.push_back(call_stack_.back());
177  call_stack_.pop_back();
178 }
179 
180 
182 {
183  call_stack_.back().set_evaluated(evaluated);
184 }
185 
187 {
188  call_stack_.back().set_value(v);
189 }
190 
192 {
193  call_stack_push(expression.str());
195  msg(" evaluating expression: ",call_stack_.back());
196  variant v = expression.execute(variables,this);
199  msg(" evaluated expression: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
201  call_stack_pop();
202  return v;
203 }
204 
205 
207 {
208  call_stack_push(f.str());
210  msg(" evaluating formula: ",call_stack_.back());
211  variant v = f.execute(variables,this);
214  msg(" evaluated formula: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
216  call_stack_pop();
217  return v;
218 }
219 
220 
222 {
223  call_stack_push(f.str());
225  msg(" evaluating formula without variables: ",call_stack_.back());
226  variant v = f.execute(this);
229  msg(" evaluated formula without variables: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
231  call_stack_pop();
232  return v;
233 }
234 
235 
236 base_breakpoint::base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
237  : fdb_(fdb), name_(name), one_time_only_(one_time_only)
238 {
239 
240 }
241 
242 
244 {
245 }
246 
247 
249 {
250  return one_time_only_;
251 }
252 
253 
254 const std::string& base_breakpoint::name() const
255 {
256  return name_;
257 }
258 
260 public:
262  : base_breakpoint(fdb,"End", true)
263  {
264  }
265 
266  virtual ~end_breakpoint()
267  {
268  }
269 
270  virtual bool is_break_now() const
271  {
272  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
273  if ((call_stack.size() == 1) && (call_stack.front().evaluated()) ) {
274  return true;
275  }
276  return false;
277  }
278 };
279 
280 
282 public:
284  : base_breakpoint(fdb,"Step",true)
285  {
286  }
287 
289  {
290  }
291 
292  virtual bool is_break_now() const
293  {
294  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
295  if (call_stack.empty() || call_stack.back().evaluated()) {
296  return false;
297  }
298 
299  return true;
300  }
301 };
302 
303 
305 public:
307  : base_breakpoint(fdb,"Step out",true), level_(fdb.get_call_stack().size()-1)
308  {
309  }
310 
312  {
313  }
314 
315  virtual bool is_break_now() const
316  {
317  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
318  if (call_stack.empty() || call_stack.back().evaluated()) {
319  return false;
320  }
321 
322  if (call_stack.size() == level_) {
323  return true;
324  }
325  return false;
326  }
327 private:
328  std::size_t level_;
329 };
330 
331 
333 public:
335  : base_breakpoint(fdb,"Next",true), level_(fdb.get_call_stack().size())
336  {
337  }
338 
340  {
341  }
342 
343  virtual bool is_break_now() const
344  {
345  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
346  if (call_stack.empty() || call_stack.back().evaluated()) {
347  return false;
348  }
349  if (call_stack.size() == level_) {
350  return true;
351  }
352  return false;
353  }
354 private:
355  std::size_t level_;
356 };
357 
358 
360 {
361  breakpoints_.emplace_back(new end_breakpoint(*this));
362  LOG_FDB << "added 'end' breakpoint"<< std::endl;
363 }
364 
365 
367 {
368  breakpoints_.emplace_back(new step_in_breakpoint(*this));
369  LOG_FDB << "added 'step into' breakpoint"<< std::endl;
370 }
371 
372 
374 {
375  breakpoints_.emplace_back(new step_out_breakpoint(*this));
376  LOG_FDB << "added 'step out' breakpoint"<< std::endl;
377 }
378 
379 
381 {
382  breakpoints_.emplace_back(new next_breakpoint(*this));
383  LOG_FDB << "added 'next' breakpoint"<< std::endl;
384 }
385 
386 
387 } // end of namespace wfl
int level() const
Definition: debugger.cpp:48
virtual ~next_breakpoint()
Definition: debugger.cpp:339
virtual ~step_in_breakpoint()
Definition: debugger.cpp:288
virtual bool is_break_now() const
Definition: debugger.cpp:315
virtual std::string str() const =0
void add_debug_info(int arg_number, const std::string &f_name)
Definition: debugger.cpp:114
void add_breakpoint_step_out()
Definition: debugger.cpp:373
Formula AI debugger.
void call_stack_push(const std::string &str)
Definition: debugger.cpp:165
std::list< debug_info > call_stack_
Definition: debugger.hpp:144
debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
Definition: debugger.cpp:37
const std::string & str() const
Definition: formula.hpp:72
variant value_
Definition: debugger.hpp:53
std::list< breakpoint_ptr > breakpoints_
Definition: debugger.hpp:147
void set_evaluated(bool evaluated)
Definition: debugger.cpp:83
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:108
std::size_t level_
Definition: debugger.cpp:355
formula_debugger & fdb_
Definition: debugger.hpp:66
const std::string & name() const
Definition: debugger.cpp:254
std::shared_ptr< base_breakpoint > breakpoint_ptr
#define b
breakpoint_ptr current_breakpoint_
Definition: debugger.hpp:146
const breakpoint_ptr get_current_breakpoint() const
Definition: debugger.cpp:127
virtual ~base_breakpoint()
Definition: debugger.cpp:243
variant evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables)
Definition: debugger.cpp:191
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
const t_string name
std::string f_name_extra_debug_info
Definition: debugger.hpp:150
#define WRN_FDB
Definition: debugger.cpp:31
step_in_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:283
virtual ~end_breakpoint()
Definition: debugger.cpp:266
virtual ~step_out_breakpoint()
Definition: debugger.cpp:311
void set_value(const variant &value)
Definition: debugger.cpp:71
virtual ~debug_info()
Definition: debugger.cpp:43
const variant & value() const
Definition: debugger.cpp:65
static lg::log_domain log_formula_debugger("scripting/formula/debug")
int counter() const
Definition: debugger.cpp:59
std::list< debug_info > execution_trace_
Definition: debugger.hpp:148
std::string str_
Definition: debugger.hpp:52
std::string name_
Definition: debugger.hpp:51
variant evaluate_formula_callback(const formula &f, const formula_callable &variables)
Definition: debugger.cpp:206
std::string name_
Definition: debugger.hpp:67
std::size_t i
Definition: function.cpp:933
virtual bool is_break_now() const
Definition: debugger.cpp:270
virtual bool is_break_now() const
Definition: debugger.cpp:292
next_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:334
#define LOG_FDB
Definition: debugger.cpp:30
void call_stack_set_value(const variant &v)
Definition: debugger.cpp:186
bool evaluated() const
Definition: debugger.cpp:77
#define DBG_FDB
Definition: debugger.cpp:29
const bool & debug
bool is_one_time_only() const
Definition: debugger.cpp:248
virtual ~formula_debugger()
Definition: debugger.cpp:103
void add_breakpoint_continue_to_end()
Definition: debugger.cpp:359
const std::list< debug_info > & get_call_stack() const
Definition: debugger.cpp:121
#define f
Definition: contexts.hpp:43
const std::string & str() const
Definition: debugger.cpp:89
const std::string & name() const
Definition: debugger.cpp:53
Standard logging facilities (interface).
base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
Definition: debugger.cpp:236
variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: formula.cpp:261
void add_breakpoint_step_into()
Definition: debugger.cpp:366
virtual bool is_break_now() const
Definition: debugger.cpp:343
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static std::deque< std::string > call_stack
Definition: function.cpp:39
step_out_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:306
void call_stack_set_evaluated(bool evaluated)
Definition: debugger.cpp:181
const std::list< debug_info > & get_execution_trace() const
Definition: debugger.cpp:132
virtual variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const =0
static game_display * get_singleton()
end_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:261