The Battle for Wesnoth  1.19.7+dev
lua_kernel_base.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include <sstream>
19 #include <string>
20 #include <vector>
21 #include <functional>
22 #include <cstdint>
23 
24 struct lua_State;
25 class config;
26 
28 public:
30  virtual ~lua_kernel_base();
31 
32  /** Runs a [lua] tag. Doesn't throw lua_error.*/
33  void run_lua_tag(const config& cfg);
34 
35  /** Runs a plain script. Doesn't throw lua_error.*/
36  void run(char const *prog, const std::string& name, int nArgs = 0);
37 
38  /** Runs a plain script, but reports errors by throwing lua_error.*/
39  void throwing_run(char const * prog, const std::string& name, int nArgs, bool in_interpreter = false);
40 
41  /** Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.*/
42  void interactive_run(char const * prog);
43 
44  /** Loads the `package` library into lua environment. Only in allow in `unsafe` modes. */
45  void load_package();
46  /** Loads the "core" library into the Lua environment. Without this, most Wesnoth Lua won't work.
47  * Cannot be called from the constructor because it needs to call virtual functions.
48  */
49  void load_core();
50 
51  /** Get tab completion strings */
52  std::vector<std::string> get_global_var_names();
53  std::vector<std::string> get_attribute_names(const std::string & var_path);
54 
55  /** User-visible name of the lua kernel that they are talking to */
56  virtual std::string my_name() { return "Basic Lua Kernel"; }
57 
58  /** Access / manipulate logging of lua kernel activities */
59  const std::stringstream & get_log() { cmd_log_.log_ << std::flush; return cmd_log_.log_; }
60  void add_log(const char* str) { cmd_log_ << str; }
61  void clear_log() { cmd_log_.log_.str(""); cmd_log_.log_.clear(); }
62 
63  using external_log_type = std::function<void(const std::string &)>;
65 
66  /** Error reporting mechanisms, used by virtual methods protected_call and load_string*/
67  virtual void log_error(char const* msg, char const* context = "Lua error");
68  virtual void throw_exception(char const* msg, char const* context = "Lua error"); //throws game::lua_error
69 
70  typedef std::function<void(char const*, char const*)> error_handler;
71 
72  template<typename T>
73  static T& get_lua_kernel(lua_State *L)
74  {
75  return *static_cast<T*>(get_lua_kernel_base_ptr(L));
76  }
77 
78  virtual uint32_t get_random_seed();
79  lua_State * get_state() { return mState; }
80  void add_widget_definition(const std::string& type, const std::string& id) { registered_widget_definitions_.emplace_back(type, id); }
81 protected:
82  lua_State *mState;
83 
84  /** Log implementation */
85  struct command_log {
86 
87  std::stringstream log_;
89 
91  : log_()
92  , external_log_(nullptr)
93  {}
94 
95  inline command_log & operator<< (const std::string & str) {
96  log_ << str;
97  if (external_log_) {
98  external_log_(str);
99  }
100  return *this;
101  }
102 
103  inline command_log & operator<< (char const* str) {
104  if (str != nullptr) {
105  log_ << str;
106  if (external_log_) {
107  external_log_(str);
108  }
109  }
110  return *this;
111  }
112  };
113 
115 
116  // Print text to the command log for this lua kernel. Used as a replacement impl for lua print.
117  int intf_print(lua_State * L);
118 public:
119  void add_log_to_console(const std::string& msg);
120  // Show the interactive lua console (for debugging purposes)
121  int intf_show_lua_console(lua_State * L);
122 protected:
123  // Execute a protected call. Error handler is called in case of an error, using syntax for log_error and throw_exception above. Returns true if successful.
124  bool protected_call(int nArgs, int nRets, const error_handler&);
125  // Execute a protected call, taking a lua_State as argument. For functions pushed into the lua environment, this version should be used, or the function cannot be used by coroutines without segfaulting (since they have a different lua_State pointer). This version is called by the above version.
126  static bool protected_call(lua_State * L, int nArgs, int nRets, const error_handler&);
127  // Load a string onto the stack as a function. Returns true if successful, error handler is called if not.
128  bool load_string(char const * prog, const std::string& name, const error_handler&);
129 
130  virtual bool protected_call(int nArgs, int nRets); // select default error handler polymorphically
131  virtual bool load_string(char const * prog, const std::string& name); // select default error handler polymorphically
132 
133  // dofile (using lua_fileops)
134  int intf_dofile(lua_State * L);
135 
136  // require (using lua_fileops, protected_call)
137  int intf_require(lua_State * L);
138 
139  int intf_kernel_type(lua_State* L);
140 
141  int impl_game_config_get(lua_State* L);
142  int impl_game_config_set(lua_State* L);
143  int impl_game_config_dir(lua_State* L);
144 private:
145  static lua_kernel_base*& get_lua_kernel_base_ptr(lua_State *L);
146  std::vector<std::tuple<std::string, std::string>> registered_widget_definitions_;
147 };
148 
149 std::vector<std::string> luaW_get_attributes(lua_State* L, int idx);
150 
154 };
155 #define GAME_CONFIG_GETTER(name, type, kernel_type) \
156  LATTR_VALID(name, game_config_tag, k) { return dynamic_cast<kernel_type*>(&k.ref) != nullptr; } \
157  LATTR_GETTER(name, type, game_config_tag, k)
158 #define GAME_CONFIG_SETTER(name, type, kernel_type) \
159  LATTR_VALID(name, game_config_tag, k) { return dynamic_cast<kernel_type*>(&k.ref) != nullptr; } \
160  LATTR_SETTER(name, type, game_config_tag, k)
161 
162 template<typename T> struct lua_object_traits;
163 template<> struct lua_object_traits<game_config_tag> {
164  inline static auto metatable = "game config";
165  inline static game_config_tag get(lua_State* L, int) {
166  return lua_kernel_base::get_lua_kernel<lua_kernel_base>(L);
167  }
168 };
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
void add_log(const char *str)
void load_core()
Loads the "core" library into the Lua environment.
void run(char const *prog, const std::string &name, int nArgs=0)
Runs a plain script.
virtual void log_error(char const *msg, char const *context="Lua error")
Error reporting mechanisms, used by virtual methods protected_call and load_string.
int intf_dofile(lua_State *L)
Loads and executes a Lua file.
command_log cmd_log_
bool load_string(char const *prog, const std::string &name, const error_handler &)
int impl_game_config_get(lua_State *L)
Gets some game_config data (__index metamethod).
int intf_require(lua_State *L)
Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
lua_State * mState
void throwing_run(char const *prog, const std::string &name, int nArgs, bool in_interpreter=false)
Runs a plain script, but reports errors by throwing lua_error.
int intf_kernel_type(lua_State *L)
int impl_game_config_set(lua_State *L)
Sets some game_config data (__newindex metamethod).
void load_package()
Loads the package library into lua environment.
void set_external_log(external_log_type lg)
bool protected_call(int nArgs, int nRets, const error_handler &)
void add_log_to_console(const std::string &msg)
int impl_game_config_dir(lua_State *L)
Gets a list of game_config data (__dir metamethod).
int intf_show_lua_console(lua_State *L)
std::vector< std::tuple< std::string, std::string > > registered_widget_definitions_
std::function< void(const std::string &)> external_log_type
static lua_kernel_base *& get_lua_kernel_base_ptr(lua_State *L)
std::vector< std::string > get_global_var_names()
Get tab completion strings.
std::function< void(char const *, char const *)> error_handler
void run_lua_tag(const config &cfg)
Runs a [lua] tag.
lua_State * get_state()
static T & get_lua_kernel(lua_State *L)
virtual ~lua_kernel_base()
int intf_print(lua_State *L)
Replacement print function – instead of printing to std::cout, print to the command log.
void interactive_run(char const *prog)
Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it nor...
std::vector< std::string > get_attribute_names(const std::string &var_path)
Gets all attribute names of an extended variable name.
virtual uint32_t get_random_seed()
virtual void throw_exception(char const *msg, char const *context="Lua error")
void add_widget_definition(const std::string &type, const std::string &id)
const std::stringstream & get_log()
Access / manipulate logging of lua kernel activities.
virtual std::string my_name()
User-visible name of the lua kernel that they are talking to.
std::vector< std::string > luaW_get_attributes(lua_State *L, int idx)
This function does the actual work of grabbing all the attribute names.
Definition: pump.hpp:41
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
static std::string flush(std::ostringstream &s)
Definition: reports.cpp:95
game_config_tag(lua_kernel_base &k)
lua_kernel_base & ref
command_log & operator<<(const std::string &str)
static game_config_tag get(lua_State *L, int)