ChaiScript
chaiscript_engine.hpp
1 // This file is distributed under the BSD License.
2 // See "license.txt" for details.
3 // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 // Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 // http://www.chaiscript.com
6 
7 // This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 
10 
11 #ifndef CHAISCRIPT_ENGINE_HPP_
12 #define CHAISCRIPT_ENGINE_HPP_
13 
14 #include <cassert>
15 #include <exception>
16 #include <fstream>
17 #include <functional>
18 #include <map>
19 #include <memory>
20 #include <mutex>
21 #include <set>
22 #include <stdexcept>
23 #include <vector>
24 #include <cstring>
25 
26 #include "../chaiscript_defines.hpp"
27 #include "../chaiscript_threading.hpp"
28 #include "../dispatchkit/boxed_cast_helper.hpp"
29 #include "../dispatchkit/boxed_value.hpp"
30 #include "../dispatchkit/dispatchkit.hpp"
31 #include "../dispatchkit/type_conversions.hpp"
32 #include "../dispatchkit/proxy_functions.hpp"
33 #include "chaiscript_common.hpp"
34 
35 #if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
36 #include <unistd.h>
37 #endif
38 
39 #if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
40 #include <dlfcn.h>
41 #endif
42 
43 #if defined(CHAISCRIPT_NO_DYNLOAD)
44 #include "chaiscript_unknown.hpp"
45 #elif defined(CHAISCRIPT_WINDOWS)
46 #include "chaiscript_windows.hpp"
47 #elif _POSIX_VERSION
48 #include "chaiscript_posix.hpp"
49 #else
50 #include "chaiscript_unknown.hpp"
51 #endif
52 
53 
54 #include "../dispatchkit/exception_specification.hpp"
55 
56 namespace chaiscript
57 {
60 
61  namespace detail
62  {
63  typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
64  }
65 
66 
69 
70  mutable chaiscript::detail::threading::shared_mutex m_mutex;
71  mutable chaiscript::detail::threading::recursive_mutex m_use_mutex;
72 
73  std::set<std::string> m_used_files;
74  std::map<std::string, detail::Loadable_Module_Ptr> m_loaded_modules;
75  std::set<std::string> m_active_loaded_modules;
76 
77  std::vector<std::string> m_module_paths;
78  std::vector<std::string> m_use_paths;
79 
80  std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
81 
83 
84  std::map<std::string, std::function<Namespace&()>> m_namespace_generators;
85 
87  Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
88  {
89  try {
90  const auto p = m_parser->parse(t_input, t_filename);
91  return p->eval(chaiscript::detail::Dispatch_State(m_engine));
92  }
94  return rv.retval;
95  }
96  }
97 
98 
99 
101  Boxed_Value internal_eval_file(const std::string &t_filename) {
102  for (const auto &path : m_use_paths)
103  {
104  try {
105  const auto appendedpath = path + t_filename;
106  return do_eval(load_file(appendedpath), appendedpath, true);
107  } catch (const exception::file_not_found_error &) {
108  // failed to load, try the next path
109  } catch (const exception::eval_error &t_ee) {
110  throw Boxed_Value(t_ee);
111  }
112  }
113 
114  // failed to load by any name
115  throw exception::file_not_found_error(t_filename);
116 
117  }
118 
119 
120 
122  Boxed_Value internal_eval(const std::string &t_e) {
123  try {
124  return do_eval(t_e, "__EVAL__", true);
125  } catch (const exception::eval_error &t_ee) {
126  throw Boxed_Value(t_ee);
127  }
128  }
129 
131  chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept {
132  return m_engine;
133  }
134 
136  void build_eval_system(const ModulePtr &t_lib, const std::vector<Options> &t_opts) {
137  if (t_lib)
138  {
139  add(t_lib);
140  }
141 
142  m_engine.add(fun([this](){ m_engine.dump_system(); }), "dump_system");
143  m_engine.add(fun([this](const Boxed_Value &t_bv){ m_engine.dump_object(t_bv); }), "dump_object");
144  m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_type){ return m_engine.is_type(t_bv, t_type); }), "is_type");
145  m_engine.add(fun([this](const Boxed_Value &t_bv){ return m_engine.type_name(t_bv); }), "type_name");
146  m_engine.add(fun([this](const std::string &t_f){ return m_engine.function_exists(t_f); }), "function_exists");
147  m_engine.add(fun([this](){ return m_engine.get_function_objects(); }), "get_functions");
148  m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects");
149 
150  m_engine.add(
151  dispatch::make_dynamic_proxy_function(
152  [this](const Function_Params &t_params) {
153  return m_engine.call_exists(t_params);
154  })
155  , "call_exists");
156 
157 
158  m_engine.add(fun(
159  [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
160  Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
161  return t_fun(Function_Params{t_params}, s);
162  }), "call");
163 
164 
165  m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
166 
167  m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
168  m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type");
169 
170  m_engine.add(fun(
171  [=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
172  m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
173  }
174  ), "add_type_conversion");
175 
176 
177 
178  if (std::find(t_opts.begin(), t_opts.end(), Options::No_Load_Modules) == t_opts.end()
179  && std::find(t_opts.begin(), t_opts.end(), Options::Load_Modules) != t_opts.end())
180  {
181  m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module");
182  m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module");
183  }
184 
185  if (std::find(t_opts.begin(), t_opts.end(), Options::No_External_Scripts) == t_opts.end()
186  && std::find(t_opts.begin(), t_opts.end(), Options::External_Scripts) != t_opts.end())
187  {
188  m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use");
189  m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
190  }
191 
192  m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
193  m_engine.add(fun([this](const AST_Node &t_ast){ return eval(t_ast); }), "eval");
194 
195  m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
196  m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
197 
198 
199  m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const");
200  m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
201  m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
202 
203  // why this unused parameter to Namespace?
204  m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& /*space*/) {}, t_namespace_name); import(t_namespace_name); }), "namespace");
205  m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
206  }
207 
209  static bool skip_bom(std::ifstream &infile) {
210  size_t bytes_needed = 3;
211  char buffer[3];
212 
213  memset(buffer, '\0', bytes_needed);
214 
215  infile.read(buffer, static_cast<std::streamsize>(bytes_needed));
216 
217  if ((buffer[0] == '\xef')
218  && (buffer[1] == '\xbb')
219  && (buffer[2] == '\xbf')) {
220 
221  infile.seekg(3);
222  return true;
223  }
224 
225  infile.seekg(0);
226 
227  return false;
228  }
229 
231  static std::string load_file(const std::string &t_filename) {
232  std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
233 
234  if (!infile.is_open()) {
236  }
237 
238  auto size = infile.tellg();
239  infile.seekg(0, std::ios::beg);
240 
241  assert(size >= 0);
242 
243  if (skip_bom(infile)) {
244  size-=3; // decrement the BOM size from file size, otherwise we'll get parsing errors
245  assert(size >= 0); //and check if there's more text
246  }
247 
248  if (size == std::streampos(0))
249  {
250  return std::string();
251  } else {
252  std::vector<char> v(static_cast<size_t>(size));
253  infile.read(&v[0], static_cast<std::streamsize>(size));
254  return std::string(v.begin(), v.end());
255  }
256  }
257 
258  std::vector<std::string> ensure_minimum_path_vec(std::vector<std::string> paths)
259  {
260  if (paths.empty()) { return {""}; }
261  else { return paths; }
262  }
263 
264  public:
265 
271  std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
272  std::vector<std::string> t_module_paths = {},
273  std::vector<std::string> t_use_paths = {},
274  const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
275  : m_module_paths(ensure_minimum_path_vec(std::move(t_module_paths))),
276  m_use_paths(ensure_minimum_path_vec(std::move(t_use_paths))),
277  m_parser(std::move(parser)),
278  m_engine(*m_parser)
279  {
280 #if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__)
281  // If on Unix, add the path of the current executable to the module search path
282  // as windows would do
283 
284  union cast_union
285  {
286  Boxed_Value (ChaiScript_Basic::*in_ptr)(const std::string&);
287  void *out_ptr;
288  };
289 
290  Dl_info rInfo;
291  memset( &rInfo, 0, sizeof(rInfo) );
292  cast_union u;
293  u.in_ptr = &ChaiScript_Basic::use;
294  if ( (dladdr(static_cast<void*>(u.out_ptr), &rInfo) != 0) && (rInfo.dli_fname != nullptr) ) {
295  std::string dllpath(rInfo.dli_fname);
296  const size_t lastslash = dllpath.rfind('/');
297  if (lastslash != std::string::npos)
298  {
299  dllpath.erase(lastslash);
300  }
301 
302  // Let's see if this is a link that we should expand
303  std::vector<char> buf(2048);
304  const auto pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
305  if (pathlen > 0 && static_cast<size_t>(pathlen) < buf.size())
306  {
307  dllpath = std::string(&buf.front(), static_cast<size_t>(pathlen));
308  }
309 
310  m_module_paths.insert(m_module_paths.begin(), dllpath+"/");
311  }
312 #endif
313  build_eval_system(t_lib, t_opts);
314  }
315 
316 #ifndef CHAISCRIPT_NO_DYNLOAD
317  explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
325  std::vector<std::string> t_module_paths = {},
326  std::vector<std::string> t_use_paths = {},
327  const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options())
328  : ChaiScript_Basic({}, std::move(parser), t_module_paths, t_use_paths, t_opts)
329  {
330  try {
331  // attempt to load the stdlib
332  load_module("chaiscript_stdlib-" + Build_Info::version());
333  } catch (const exception::load_module_error &t_err) {
334  std::cout << "An error occured while trying to load the chaiscript standard library.\n"
335  << "\n"
336  << "You must either provide a standard library, or compile it in.\n"
337  << "For an example of compiling the standard library in,\n"
338  << "see: https://gist.github.com/lefticus/9456197\n"
339  << "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
340  << "\n"
341  << "\n"
342  << t_err.what();
343  throw;
344  }
345  }
346 #else // CHAISCRIPT_NO_DYNLOAD
347  explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
348  std::vector<std::string> t_module_paths = {},
349  std::vector<std::string> t_use_paths = {},
350  const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options()) = delete;
351 #endif
352 
353  parser::ChaiScript_Parser_Base &get_parser() noexcept
354  {
355  return *m_parser;
356  }
357 
358  const Boxed_Value eval(const AST_Node &t_ast)
359  {
360  try {
361  return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine));
362  } catch (const exception::eval_error &t_ee) {
363  throw Boxed_Value(t_ee);
364  }
365  }
366 
367  AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
368  {
369  auto ast = m_parser->parse(t_input, "PARSE");
370  if (t_debug_print) {
371  m_parser->debug_print(*ast);
372  }
373  return ast;
374  }
375 
376 
377  std::string get_type_name(const Type_Info &ti) const
378  {
379  return m_engine.get_type_name(ti);
380  }
381 
382  template<typename T>
383  std::string get_type_name() const
384  {
385  return get_type_name(user_type<T>());
386  }
387 
388 
394  Boxed_Value use(const std::string &t_filename)
395  {
396  for (const auto &path : m_use_paths)
397  {
398  const auto appendedpath = path + t_filename;
399  try {
400 
401  chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
402  chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
403 
404  Boxed_Value retval;
405 
406  if (m_used_files.count(appendedpath) == 0)
407  {
408  l2.unlock();
409  retval = eval_file(appendedpath);
410  l2.lock();
411  m_used_files.insert(appendedpath);
412  }
413 
414  return retval; // return, we loaded it, or it was already loaded
415  } catch (const exception::file_not_found_error &e) {
416  if (e.filename != appendedpath) {
417  // a nested file include failed
418  throw;
419  }
420  // failed to load, try the next path
421  }
422  }
423 
424  // failed to load by any name
425  throw exception::file_not_found_error(t_filename);
426  }
427 
433  ChaiScript_Basic &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
434  {
435  Name_Validator::validate_object_name(t_name);
436  m_engine.add_global_const(t_bv, t_name);
437  return *this;
438  }
439 
445  ChaiScript_Basic &add_global(const Boxed_Value &t_bv, const std::string &t_name)
446  {
447  Name_Validator::validate_object_name(t_name);
448  m_engine.add_global(t_bv, t_name);
449  return *this;
450  }
451 
452  ChaiScript_Basic &set_global(const Boxed_Value &t_bv, const std::string &t_name)
453  {
454  Name_Validator::validate_object_name(t_name);
455  m_engine.set_global(t_bv, t_name);
456  return *this;
457  }
458 
464  struct State
465  {
466  std::set<std::string> used_files;
468  std::set<std::string> active_loaded_modules;
469  };
470 
484  State get_state() const
485  {
486  chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
487  chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
488 
489  State s;
490  s.used_files = m_used_files;
491  s.engine_state = m_engine.get_state();
492  s.active_loaded_modules = m_active_loaded_modules;
493  return s;
494  }
495 
510  void set_state(const State &t_state)
511  {
512  chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
513  chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
514 
515  m_used_files = t_state.used_files;
516  m_active_loaded_modules = t_state.active_loaded_modules;
517  m_engine.set_state(t_state.engine_state);
518  }
519 
521  std::map<std::string, Boxed_Value> get_locals() const
522  {
523  return m_engine.get_locals();
524  }
525 
531  void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
532  {
533  m_engine.set_locals(t_locals);
534  }
535 
551  template<typename T>
552  ChaiScript_Basic &add(const T &t_t, const std::string &t_name)
553  {
554  Name_Validator::validate_object_name(t_name);
555  m_engine.add(t_t, t_name);
556  return *this;
557  }
558 
568  ChaiScript_Basic &add(const Type_Conversion &d)
569  {
570  m_engine.add(d);
571  return *this;
572  }
573 
578  {
579  t_p->apply(*this, this->get_eval_engine());
580  return *this;
581  }
582 
595  std::string load_module(const std::string &t_module_name)
596  {
597 #ifdef CHAISCRIPT_NO_DYNLOAD
598  throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
599 #else
600  std::vector<exception::load_module_error> errors;
601  std::string version_stripped_name = t_module_name;
602  size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
603  if (version_pos != std::string::npos)
604  {
605  version_stripped_name.erase(version_pos);
606  }
607 
608  std::vector<std::string> prefixes{"lib", "cyg", ""};
609 
610  std::vector<std::string> postfixes{".dll", ".so", ".bundle", ""};
611 
612  for (auto & elem : m_module_paths)
613  {
614  for (auto & prefix : prefixes)
615  {
616  for (auto & postfix : postfixes)
617  {
618  try {
619  const auto name = elem + prefix + t_module_name + postfix;
620  // std::cerr << "trying location: " << name << '\n';
621  load_module(version_stripped_name, name);
622  return name;
623  } catch (const chaiscript::exception::load_module_error &e) {
624  // std::cerr << "error: " << e.what() << '\n';
625  errors.push_back(e);
626  // Try next set
627  }
628  }
629  }
630  }
631 
632  throw chaiscript::exception::load_module_error(t_module_name, errors);
633 #endif
634  }
635 
643  void load_module(const std::string &t_module_name, const std::string &t_filename)
644  {
645  chaiscript::detail::threading::lock_guard<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
646 
647  if (m_loaded_modules.count(t_module_name) == 0)
648  {
649  detail::Loadable_Module_Ptr lm(new detail::Loadable_Module(t_module_name, t_filename));
650  m_loaded_modules[t_module_name] = lm;
651  m_active_loaded_modules.insert(t_module_name);
652  add(lm->m_moduleptr);
653  } else if (m_active_loaded_modules.count(t_module_name) == 0) {
654  m_active_loaded_modules.insert(t_module_name);
655  add(m_loaded_modules[t_module_name]->m_moduleptr);
656  }
657  }
658 
659 
668  Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
669  {
670  return eval(t_script, t_handler);
671  }
672 
686  template<typename T>
687  T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
688  {
689  return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
690  }
691 
693  template<typename Type>
694  decltype(auto) boxed_cast(const Boxed_Value &bv) const
695  {
696  return(m_engine.boxed_cast<Type>(bv));
697  }
698 
699 
710  Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
711  {
712  try {
713  return do_eval(t_input, t_filename);
714  } catch (Boxed_Value &bv) {
715  if (t_handler) {
716  t_handler->handle(bv, m_engine);
717  }
718  throw;
719  }
720  }
721 
727  Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
728  return eval(load_file(t_filename), t_handler, t_filename);
729  }
730 
739  template<typename T>
740  T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
741  return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
742  }
743 
747  void import(const std::string& t_namespace_name)
748  {
749  chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
750 
751  if (m_engine.get_scripting_objects().count(t_namespace_name)) {
752  throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
753  }
754  else if (m_namespace_generators.count(t_namespace_name)) {
755  m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
756  }
757  else {
758  throw std::runtime_error("No registered namespace: " + t_namespace_name);
759  }
760  }
761 
766  void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name)
767  {
768  chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
769 
770  if (!m_namespace_generators.count(t_namespace_name)) {
771  // contain the namespace object memory within the m_namespace_generators map
772  m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; }));
773  }
774  else {
775  throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
776  }
777  }
778  };
779 
780 }
781 #endif /* CHAISCRIPT_ENGINE_HPP_ */
782 
void add(const Type_Conversion &d)
Add a new conversion for upcasting to a base class.
Definition: dispatchkit.hpp:460
Definition: dispatchkit.hpp:436
Thrown if an error occurs while attempting to load a binary module.
Definition: chaiscript_common.hpp:163
void set_state(const State &t_state)
Sets the state of the system.
Definition: chaiscript_engine.hpp:510
Compile time deduced information about a type.
Definition: type_info.hpp:33
std::map< std::string, Boxed_Value > get_locals() const
Definition: dispatchkit.hpp:803
T eval(const std::string &t_input, const Exception_Handler &t_handler=Exception_Handler(), const std::string &t_filename="__EVAL__")
Evaluates a string and returns a typesafe result.
Definition: chaiscript_engine.hpp:687
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions=nullptr)
Function for extracting a value stored in a Boxed_Value object.
Definition: boxed_cast.hpp:76
Definition: type_conversions.hpp:514
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler=Exception_Handler())
Loads the file specified by filename, evaluates it, and returns the result.
Definition: chaiscript_engine.hpp:727
Definition: chaiscript_posix.hpp:14
void load_module(const std::string &t_module_name, const std::string &t_filename)
Load a binary module from a dynamic library.
Definition: chaiscript_engine.hpp:643
ChaiScript_Basic & add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
Adds a constant object that is available in all contexts and to all threads.
Definition: chaiscript_engine.hpp:433
bool is_type(const Boxed_Value &r, const std::string_view &user_typename) const noexcept
return true if the Boxed_Value matches the registered type by name
Definition: dispatchkit.hpp:1119
bool function_exists(const std::string_view &name) const
Return true if a function exists.
Definition: dispatchkit.hpp:782
Namespace chaiscript contains every API call that the average user will be concerned with...
Definition: function_params.hpp:19
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler=Exception_Handler())
Loads the file specified by filename, evaluates it, and returns the type safe result.
Definition: chaiscript_engine.hpp:740
void add_global_const(const Boxed_Value &obj, const std::string &name)
Adds a new global shared object, between all the threads.
Definition: dispatchkit.hpp:530
void register_namespace(const std::function< void(Namespace &)> &t_namespace_generator, const std::string &t_namespace_name)
Registers a namespace generator, which delays generation of the namespace until it is imported...
Definition: chaiscript_engine.hpp:766
std::map< std::string, Boxed_Value > get_function_objects() const
Get a map of all functions that can be seen from a scripting context.
Definition: dispatchkit.hpp:853
ChaiScript_Basic & add(const T &t_t, const std::string &t_name)
Adds a type, function or object to ChaiScript.
Definition: chaiscript_engine.hpp:552
dispatch::Dynamic_Object Namespace
Namespace alias to provide cleaner and more explicit syntax to users.
Definition: chaiscript_engine.hpp:59
ChaiScript_Basic(const ModulePtr &t_lib, std::unique_ptr< parser::ChaiScript_Parser_Base > &&parser, std::vector< std::string > t_module_paths={}, std::vector< std::string > t_use_paths={}, const std::vector< chaiscript::Options > &t_opts=chaiscript::default_options())
Constructor for ChaiScript.
Definition: chaiscript_engine.hpp:270
std::shared_ptr< Module > ModulePtr
Convenience typedef for Module objects to be added to the ChaiScript runtime.
Definition: dispatchkit.hpp:265
Boxed_Value call_exists(const Function_Params &params) const
Returns true if a call can be made that consists of the first parameter (the function) with the remai...
Definition: dispatchkit.hpp:1086
std::string load_module(const std::string &t_module_name)
Load a binary module from a dynamic library.
Definition: chaiscript_engine.hpp:595
Pure virtual base class for all Proxy_Function implementations Proxy_Functions are a type erasure of ...
Definition: proxy_functions.hpp:196
Definition: chaiscript_common.hpp:648
A wrapper for holding any valid C++ type.
Definition: boxed_value.hpp:27
std::shared_ptr< detail::Exception_Handler_Base > Exception_Handler
Used in the automatic unboxing of exceptions thrown during script evaluation.
Definition: exception_specification.hpp:104
void set_locals(const std::map< std::string, Boxed_Value > &t_locals)
Sets all of the locals for the current thread state.
Definition: chaiscript_engine.hpp:531
std::map< std::string, Boxed_Value > get_scripting_objects() const
Get a map of all objects that can be seen from the current scope in a scripting context.
Definition: dispatchkit.hpp:827
void add_global(Boxed_Value obj, std::string name)
Adds a new global (non-const) shared object, between all the threads.
Definition: dispatchkit.hpp:557
Boxed_Value var(T &&t)
Creates a Boxed_Value.
Definition: boxed_value.hpp:387
std::string get_type_name(const Type_Info &ti) const
Returns the registered name of a known type_info object compares the "bare_type_info" for the broades...
Definition: dispatchkit.hpp:706
std::map< std::string, Boxed_Value > get_locals() const
Definition: chaiscript_engine.hpp:521
Represents the current state of the ChaiScript system.
Definition: chaiscript_engine.hpp:464
ChaiScript_Basic & add(const Type_Conversion &d)
Add a new conversion for upcasting to a base class.
Definition: chaiscript_engine.hpp:568
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler=Exception_Handler())
Evaluates a string.
Definition: chaiscript_engine.hpp:668
Struct that doubles as both a parser ast_node and an AST node.
Definition: chaiscript_common.hpp:523
void dump_system() const
Dump all system info to stdout.
Definition: dispatchkit.hpp:1100
void dump_object(const Boxed_Value &o) const
Dump object info to stdout.
Definition: dispatchkit.hpp:1049
ChaiScript_Basic & add_global(const Boxed_Value &t_bv, const std::string &t_name)
Adds a mutable object that is available in all contexts and to all threads.
Definition: chaiscript_engine.hpp:445
void set_locals(const std::map< std::string, Boxed_Value > &t_locals)
Sets all of the locals for the current thread state.
Definition: dispatchkit.hpp:815
Boxed_Value use(const std::string &t_filename)
Loads and parses a file.
Definition: chaiscript_engine.hpp:394
Type_Info get_type(std::string_view name, bool t_throw=true) const
Returns the type info for a named type.
Definition: dispatchkit.hpp:685
Special type for returned values.
Definition: chaiscript_common.hpp:677
Definition: dynamic_object.hpp:43
decltype(auto) boxed_cast(const Boxed_Value &bv) const
casts an object while applying any Dynamic_Conversion available
Definition: dispatchkit.hpp:453
ChaiScript_Basic & add(const ModulePtr &t_p)
Adds all elements of a module to ChaiScript runtime.
Definition: chaiscript_engine.hpp:577
Definition: dispatchkit.hpp:1418
Errors generated during parsing or evaluation.
Definition: chaiscript_common.hpp:194
Proxy_Function fun(T &&t)
Creates a new Proxy_Function object from a free function, member function or data member...
Definition: register_function.hpp:88
State get_state() const
Returns a state object that represents the current state of the global system.
Definition: chaiscript_engine.hpp:484
The main object that the ChaiScript user will use.
Definition: chaiscript_engine.hpp:68
Main class for the dispatchkit.
Definition: dispatchkit.hpp:428
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler=Exception_Handler(), const std::string &t_filename="__EVAL__")
Evaluates a string.
Definition: chaiscript_engine.hpp:710
std::unique_ptr< AST_Node > AST_NodePtr
Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree.
Definition: proxy_functions.hpp:45
Errors generated when loading a file.
Definition: chaiscript_common.hpp:507
void set_global(Boxed_Value obj, std::string name)
Updates an existing global shared object or adds a new global shared object if not found...
Definition: dispatchkit.hpp:568