The Battle for Wesnoth  1.19.8+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 binary [lua] tag. Doesn't throw lua_error.*/
36  config run_binary_lua_tag(const config& cfg);
37 
38  /** Runs a plain script. Doesn't throw lua_error.*/
39  void run(char const *prog, const std::string& name, int nArgs = 0);
40 
41  /** Runs a plain script, but reports errors by throwing lua_error.*/
42  void throwing_run(char const * prog, const std::string& name, int nArgs, bool in_interpreter = false);
43 
44  /** Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.*/
45  void interactive_run(char const * prog);
46 
47  /** Loads the `package` library into lua environment. Only in allow in `unsafe` modes. */
48  void load_package();
49  /** Loads the "core" library into the Lua environment. Without this, most Wesnoth Lua won't work.
50  * Cannot be called from the constructor because it needs to call virtual functions.
51  */
52  void load_core();
53 
54  /** Get tab completion strings */
55  std::vector<std::string> get_global_var_names();
56  std::vector<std::string> get_attribute_names(const std::string & var_path);
57 
58  /** User-visible name of the lua kernel that they are talking to */
59  virtual std::string my_name() { return "Basic Lua Kernel"; }
60 
61  /** Access / manipulate logging of lua kernel activities */
62  const std::stringstream & get_log() { cmd_log_.log_ << std::flush; return cmd_log_.log_; }
63  void add_log(const char* str) { cmd_log_ << str; }
64  void clear_log() { cmd_log_.log_.str(""); cmd_log_.log_.clear(); }
65 
66  using external_log_type = std::function<void(const std::string &)>;
68 
69  /** Error reporting mechanisms, used by virtual methods protected_call and load_string*/
70  virtual void log_error(char const* msg, char const* context = "Lua error");
71  virtual void throw_exception(char const* msg, char const* context = "Lua error"); //throws game::lua_error
72 
73  typedef std::function<void(char const*, char const*)> error_handler;
74 
75  template<typename T>
76  static T& get_lua_kernel(lua_State *L)
77  {
78  return *static_cast<T*>(get_lua_kernel_base_ptr(L));
79  }
80 
81  virtual uint32_t get_random_seed();
82  lua_State * get_state() { return mState; }
83  void add_widget_definition(const std::string& type, const std::string& id) { registered_widget_definitions_.emplace_back(type, id); }
84 protected:
85  lua_State *mState;
86 
87  /** Log implementation */
88  struct command_log {
89 
90  std::stringstream log_;
92 
94  : log_()
95  , external_log_(nullptr)
96  {}
97 
98  inline command_log & operator<< (const std::string & str) {
99  log_ << str;
100  if (external_log_) {
101  external_log_(str);
102  }
103  return *this;
104  }
105 
106  inline command_log & operator<< (char const* str) {
107  if (str != nullptr) {
108  log_ << str;
109  if (external_log_) {
110  external_log_(str);
111  }
112  }
113  return *this;
114  }
115  };
116 
118 
119  // Print text to the command log for this lua kernel. Used as a replacement impl for lua print.
120  int intf_print(lua_State * L);
121 public:
122  void add_log_to_console(const std::string& msg);
123  // Show the interactive lua console (for debugging purposes)
124  int intf_show_lua_console(lua_State * L);
125 protected:
126  // 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.
127  bool protected_call(int nArgs, int nRets, const error_handler&);
128  // 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.
129  static bool protected_call(lua_State * L, int nArgs, int nRets, const error_handler&);
130  // Load a string onto the stack as a function. Returns true if successful, error handler is called if not.
131  bool load_string(const std::string& prog, const std::string& name, const error_handler&, bool allow_unsafe = false);
132  bool load_binary(const config& func, const error_handler&);
133 
134  virtual bool protected_call(int nArgs, int nRets); // select default error handler polymorphically
135  virtual bool load_string(char const * prog, const std::string& name); // select default error handler polymorphically
136 
137  // dofile (using lua_fileops)
138  int intf_dofile(lua_State * L);
139 
140  // require (using lua_fileops, protected_call)
141  int intf_require(lua_State * L);
142 
143  int intf_kernel_type(lua_State* L);
144 
145  int impl_game_config_get(lua_State* L);
146  int impl_game_config_set(lua_State* L);
147  int impl_game_config_dir(lua_State* L);
148 private:
149  static lua_kernel_base*& get_lua_kernel_base_ptr(lua_State *L);
150  std::vector<std::tuple<std::string, std::string>> registered_widget_definitions_;
151 };
152 
153 config luaW_serialize_function(lua_State* L, int func);
154 
155 struct luafunc_serialize_error : public std::runtime_error {
156  using std::runtime_error::runtime_error;
157 };
158 
159 std::vector<std::string> luaW_get_attributes(lua_State* L, int idx);
160 
164 };
165 #define GAME_CONFIG_GETTER(name, type, kernel_type) \
166  LATTR_VALID(name, game_config_tag, k) { return dynamic_cast<kernel_type*>(&k.ref) != nullptr; } \
167  LATTR_GETTER(name, type, game_config_tag, k)
168 #define GAME_CONFIG_SETTER(name, type, kernel_type) \
169  LATTR_VALID(name, game_config_tag, k) { return dynamic_cast<kernel_type*>(&k.ref) != nullptr; } \
170  LATTR_SETTER(name, type, game_config_tag, k)
171 
172 template<typename T> struct lua_object_traits;
173 template<> struct lua_object_traits<game_config_tag> {
174  inline static auto metatable = "game config";
175  inline static game_config_tag get(lua_State* L, int) {
176  return lua_kernel_base::get_lua_kernel<lua_kernel_base>(L);
177  }
178 };
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
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_
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)
bool load_string(const std::string &prog, const std::string &name, const error_handler &, bool allow_unsafe=false)
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()
bool load_binary(const config &func, const error_handler &)
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.
config run_binary_lua_tag(const config &cfg)
Runs a binary [lua] tag.
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.
config luaW_serialize_function(lua_State *L, int func)
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)