mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
* Fix #571: Add per-instance IO redirection via set_print_handler/set_println_handler The print_string and println_string functions were previously registered as static functions writing directly to stdout, making it impossible to redirect ChaiScript output to custom destinations (e.g., GUI windows, loggers, or buffers). This moves their registration from Bootstrap::bootstrap() to ChaiScript_Basic::build_eval_system() as lambdas that dispatch through configurable std::function handlers, allowing each ChaiScript instance to independently redirect its output via set_print_handler() and set_println_handler(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: add IO redirection section to cheatsheet Documents set_print_handler() and set_println_handler() with usage examples for GUI embedding and output capture. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: define println in terms of print, expose set_print_handler to ChaiScript Remove separate println_handler — println_string now dispatches through the single print handler with a newline appended. Only set_print_handler is needed to redirect all output. The set_print_handler function is also registered in the ChaiScript engine, so scripts can capture and redirect their own output. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: populate null print handler when No_IO is set When No_IO is active, the default m_print_handler is now a no-op instead of writing to stdout. The stdout handler is only installed when No_IO is not set. Users can still override the handler via set_print_handler() even with No_IO enabled. Requested by @lefticus in PR #657 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
516 lines
24 KiB
C++
516 lines
24 KiB
C++
// This file is distributed under the BSD License.
|
|
// See "license.txt" for details.
|
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
|
// http://www.chaiscript.com
|
|
|
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
|
|
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
|
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
|
|
|
#include "../utility/utility.hpp"
|
|
#include "register_function.hpp"
|
|
|
|
/// \brief Classes and functions useful for bootstrapping of ChaiScript and adding of new types
|
|
namespace chaiscript::bootstrap {
|
|
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type>
|
|
void array(const std::string &type, Module &m) {
|
|
using ReturnType = typename std::remove_extent<T>::type;
|
|
|
|
m.add(user_type<T>(), type);
|
|
m.add(fun([](T &t, size_t index) -> ReturnType & {
|
|
constexpr const auto extent = std::extent<T>::value;
|
|
if (extent > 0 && index >= extent) {
|
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
|
+ std::to_string(extent));
|
|
} else {
|
|
return t[index];
|
|
}
|
|
}),
|
|
"[]");
|
|
|
|
m.add(fun([](const T &t, size_t index) -> const ReturnType & {
|
|
constexpr const auto extent = std::extent<T>::value;
|
|
if (extent > 0 && index >= extent) {
|
|
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < "
|
|
+ std::to_string(extent));
|
|
} else {
|
|
return t[index];
|
|
}
|
|
}),
|
|
"[]");
|
|
|
|
m.add(fun([](const T &) { return std::extent<T>::value; }), "size");
|
|
}
|
|
|
|
/// \brief Adds a copy constructor for the given type to the given Model
|
|
/// \param[in] type The name of the type. The copy constructor will be named "type".
|
|
/// \param[in,out] m The Module to add the copy constructor to
|
|
/// \tparam T The type to add a copy constructor for
|
|
/// \returns The passed in Module
|
|
template<typename T>
|
|
void copy_constructor(const std::string &type, Module &m) {
|
|
m.add(constructor<T(const T &)>(), type);
|
|
}
|
|
|
|
/// \brief Add all comparison operators for the templated type. Used during bootstrap, also available to users.
|
|
/// \tparam T Type to create comparison operators for
|
|
/// \param[in,out] m module to add comparison operators to
|
|
/// \returns the passed in Module.
|
|
template<typename T>
|
|
void opers_comparison(Module &m) {
|
|
operators::equal<T>(m);
|
|
operators::greater_than<T>(m);
|
|
operators::greater_than_equal<T>(m);
|
|
operators::less_than<T>(m);
|
|
operators::less_than_equal<T>(m);
|
|
operators::not_equal<T>(m);
|
|
}
|
|
|
|
/// \brief Adds default and copy constructors for the given type
|
|
/// \param[in] type The name of the type to add the constructors for.
|
|
/// \param[in,out] m The Module to add the basic constructors to
|
|
/// \tparam T Type to generate basic constructors for
|
|
/// \returns The passed in Module
|
|
/// \sa copy_constructor
|
|
/// \sa constructor
|
|
template<typename T>
|
|
void basic_constructors(const std::string &type, Module &m) {
|
|
m.add(constructor<T()>(), type);
|
|
copy_constructor<T>(type, m);
|
|
}
|
|
|
|
/// \brief Adds a constructor for a POD type
|
|
/// \tparam T The type to add the constructor for
|
|
/// \param[in] type The name of the type
|
|
/// \param[in,out] m The Module to add the constructor to
|
|
template<typename T>
|
|
void construct_pod(const std::string &type, Module &m) {
|
|
m.add(fun([](const Boxed_Number &bn) { return bn.get_as<T>(); }), type);
|
|
}
|
|
|
|
/// Internal function for converting from a string to a value
|
|
/// uses ostream operator >> to perform the conversion
|
|
template<typename Input>
|
|
Input parse_string(const std::string &i) {
|
|
if constexpr (!std::is_same<Input, wchar_t>::value && !std::is_same<Input, char16_t>::value && !std::is_same<Input, char32_t>::value) {
|
|
std::stringstream ss(i);
|
|
Input t;
|
|
ss >> t;
|
|
return t;
|
|
} else {
|
|
throw std::runtime_error("Parsing of wide characters is not yet supported");
|
|
}
|
|
}
|
|
|
|
/// Add all common functions for a POD type. All operators, and
|
|
/// common conversions
|
|
template<typename T>
|
|
void bootstrap_pod_type(const std::string &name, Module &m) {
|
|
m.add(user_type<T>(), name);
|
|
m.add(constructor<T()>(), name);
|
|
construct_pod<T>(name, m);
|
|
|
|
m.add(fun(&parse_string<T>), "to_" + name);
|
|
m.add(fun([](const T t) { return t; }), "to_" + name);
|
|
m.add(fun([](const Boxed_Number &bn) { return bn.get_as<T>(); }), "to_" + name);
|
|
m.add(fun(&parse_string<T>), name);
|
|
}
|
|
|
|
/// "clone" function for a shared_ptr type. This is used in the case
|
|
/// where you do not want to make a deep copy of an object during cloning
|
|
/// but want to instead maintain the shared_ptr. It is needed internally
|
|
/// for handling of Proxy_Function object (that is,
|
|
/// function variables.
|
|
template<typename Type>
|
|
auto shared_ptr_clone(const std::shared_ptr<Type> &p) {
|
|
return p;
|
|
}
|
|
|
|
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
|
template<typename Type>
|
|
std::shared_ptr<std::remove_const_t<Type>> shared_ptr_unconst_clone(const std::shared_ptr<std::add_const_t<Type>> &p) {
|
|
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
|
}
|
|
|
|
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
|
/// object pointed to, instead maintains the shared_ptr concept.
|
|
/// Similar to shared_ptr_clone. Used for Proxy_Function.
|
|
template<typename Type>
|
|
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs) {
|
|
if (lhs.is_undef() || (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get()))) {
|
|
lhs.assign(Boxed_Value(rhs));
|
|
return lhs;
|
|
} else {
|
|
throw exception::bad_boxed_cast("type mismatch in pointer assignment");
|
|
}
|
|
}
|
|
|
|
/// Class consisting of only static functions. All default bootstrapping occurs
|
|
/// from this class.
|
|
class Bootstrap {
|
|
private:
|
|
/// Function allowing for assignment of an unknown type to any other value
|
|
static Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) {
|
|
if (lhs.is_undef()) {
|
|
return (lhs.assign(rhs));
|
|
} else {
|
|
throw exception::bad_boxed_cast("boxed_value has a set type already");
|
|
}
|
|
}
|
|
|
|
static void print(const std::string &s) noexcept { fwrite(s.c_str(), 1, s.size(), stdout); }
|
|
|
|
static void println(const std::string &s) noexcept { puts(s.c_str()); }
|
|
|
|
/// Add all arithmetic operators for PODs
|
|
static void opers_arithmetic_pod(Module &m) {
|
|
m.add(fun(&Boxed_Number::equals), "==");
|
|
m.add(fun(&Boxed_Number::less_than), "<");
|
|
m.add(fun(&Boxed_Number::greater_than), ">");
|
|
m.add(fun(&Boxed_Number::greater_than_equal), ">=");
|
|
m.add(fun(&Boxed_Number::less_than_equal), "<=");
|
|
m.add(fun(&Boxed_Number::not_equal), "!=");
|
|
|
|
m.add(fun(&Boxed_Number::pre_decrement), "--");
|
|
m.add(fun(&Boxed_Number::pre_increment), "++");
|
|
m.add(fun(&Boxed_Number::sum), "+");
|
|
m.add(fun(&Boxed_Number::unary_plus), "+");
|
|
m.add(fun(&Boxed_Number::unary_minus), "-");
|
|
m.add(fun(&Boxed_Number::difference), "-");
|
|
m.add(fun(&Boxed_Number::assign_bitwise_and), "&=");
|
|
m.add(fun(&Boxed_Number::assign), "=");
|
|
m.add(fun(&Boxed_Number::assign_bitwise_or), "|=");
|
|
m.add(fun(&Boxed_Number::assign_bitwise_xor), "^=");
|
|
m.add(fun(&Boxed_Number::assign_remainder), "%=");
|
|
m.add(fun(&Boxed_Number::assign_shift_left), "<<=");
|
|
m.add(fun(&Boxed_Number::assign_shift_right), ">>=");
|
|
m.add(fun(&Boxed_Number::bitwise_and), "&");
|
|
m.add(fun(&Boxed_Number::bitwise_complement), "~");
|
|
m.add(fun(&Boxed_Number::bitwise_xor), "^");
|
|
m.add(fun(&Boxed_Number::bitwise_or), "|");
|
|
m.add(fun(&Boxed_Number::assign_product), "*=");
|
|
m.add(fun(&Boxed_Number::assign_quotient), "/=");
|
|
m.add(fun(&Boxed_Number::assign_sum), "+=");
|
|
m.add(fun(&Boxed_Number::assign_difference), "-=");
|
|
m.add(fun(&Boxed_Number::quotient), "/");
|
|
m.add(fun(&Boxed_Number::shift_left), "<<");
|
|
m.add(fun(&Boxed_Number::product), "*");
|
|
m.add(fun(&Boxed_Number::remainder), "%");
|
|
m.add(fun(&Boxed_Number::shift_right), ">>");
|
|
}
|
|
|
|
/// Create a bound function object. The first param is the function to bind
|
|
/// the remaining parameters are the args to bind into the result
|
|
static Boxed_Value bind_function(const Function_Params ¶ms) {
|
|
if (params.empty()) {
|
|
throw exception::arity_error(0, 1);
|
|
}
|
|
|
|
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
|
|
|
if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1) {
|
|
throw exception::arity_error(static_cast<int>(params.size()), f->get_arity());
|
|
}
|
|
|
|
return Boxed_Value(Const_Proxy_Function(
|
|
std::make_shared<dispatch::Bound_Function>(std::move(f), std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
|
}
|
|
|
|
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept {
|
|
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
|
return pf && pf->has_guard();
|
|
}
|
|
|
|
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf) {
|
|
const auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
|
if (pf && pf->get_guard()) {
|
|
return pf->get_guard();
|
|
} else {
|
|
throw std::runtime_error("Function does not have a guard");
|
|
}
|
|
}
|
|
|
|
template<typename FunctionType>
|
|
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f, const dispatch::Proxy_Function_Base *b) {
|
|
auto v = (b->*f)();
|
|
|
|
std::vector<Boxed_Value> vbv;
|
|
|
|
for (const auto &o : v) {
|
|
vbv.push_back(const_var(o));
|
|
}
|
|
|
|
return vbv;
|
|
}
|
|
|
|
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) noexcept {
|
|
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
|
return bool(pf);
|
|
}
|
|
|
|
static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) {
|
|
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
|
if (pf) {
|
|
return pf->get_parse_tree();
|
|
} else {
|
|
throw std::runtime_error("Function does not have a parse tree");
|
|
}
|
|
}
|
|
|
|
template<typename Function>
|
|
static auto return_boxed_value_vector(const Function &f) {
|
|
return [f](const dispatch::Proxy_Function_Base *b) { return do_return_boxed_value_vector(f, b); };
|
|
}
|
|
|
|
public:
|
|
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
|
/// \param[in,out] m Module to add bootstrapped functions to
|
|
/// \param[in] t_no_io If true, skip registering print_string and println_string
|
|
static void bootstrap(Module &m, const bool t_no_io = false) {
|
|
m.add(user_type<void>(), "void");
|
|
m.add(user_type<bool>(), "bool");
|
|
m.add(user_type<Boxed_Value>(), "Object");
|
|
m.add(user_type<Boxed_Number>(), "Number");
|
|
m.add(user_type<Proxy_Function>(), "Function");
|
|
m.add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
|
|
m.add(user_type<std::exception>(), "exception");
|
|
|
|
m.add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
|
m.add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
|
|
|
|
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_param_types)), "get_param_types");
|
|
m.add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions");
|
|
|
|
m.add(fun([](const std::exception &e) { return std::string(e.what()); }), "what");
|
|
|
|
m.add(user_type<std::out_of_range>(), "out_of_range");
|
|
m.add(user_type<std::logic_error>(), "logic_error");
|
|
m.add(chaiscript::base_class<std::exception, std::logic_error>());
|
|
m.add(chaiscript::base_class<std::logic_error, std::out_of_range>());
|
|
m.add(chaiscript::base_class<std::exception, std::out_of_range>());
|
|
|
|
m.add(user_type<std::runtime_error>(), "runtime_error");
|
|
m.add(chaiscript::base_class<std::exception, std::runtime_error>());
|
|
|
|
m.add(constructor<std::runtime_error(const std::string &)>(), "runtime_error");
|
|
|
|
m.add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
|
m.add(constructor<dispatch::Dynamic_Object(const std::string &)>(), "Dynamic_Object");
|
|
m.add(constructor<dispatch::Dynamic_Object()>(), "Dynamic_Object");
|
|
m.add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
|
|
m.add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
|
m.add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
|
|
m.add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
|
|
m.add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr");
|
|
|
|
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
|
|
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)),
|
|
"get_attr");
|
|
|
|
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::method_missing)),
|
|
"method_missing");
|
|
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(
|
|
&dispatch::Dynamic_Object::method_missing)),
|
|
"method_missing");
|
|
|
|
m.add(fun(static_cast<Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
|
|
m.add(fun(static_cast<const Boxed_Value &(dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)),
|
|
"[]");
|
|
|
|
m.eval(R"chaiscript(
|
|
def Dynamic_Object::clone() {
|
|
auto &new_o = Dynamic_Object(this.get_type_name());
|
|
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
|
|
new_o;
|
|
}
|
|
|
|
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
|
{
|
|
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
|
|
}
|
|
|
|
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
|
{
|
|
var rhs_attrs := rhs.get_attrs();
|
|
var lhs_attrs := lhs.get_attrs();
|
|
|
|
if (rhs_attrs.size() != lhs_attrs.size()) {
|
|
true;
|
|
} else {
|
|
return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
|
|
}
|
|
}
|
|
|
|
def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
|
|
{
|
|
var rhs_attrs := rhs.get_attrs();
|
|
var lhs_attrs := lhs.get_attrs();
|
|
|
|
if (rhs_attrs.size() != lhs_attrs.size()) {
|
|
false;
|
|
} else {
|
|
return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
|
|
}
|
|
}
|
|
)chaiscript");
|
|
|
|
m.add(fun(&has_guard), "has_guard");
|
|
m.add(fun(&get_guard), "get_guard");
|
|
|
|
m.add(fun(&Boxed_Value::is_undef), "is_var_undef");
|
|
m.add(fun(&Boxed_Value::is_null), "is_var_null");
|
|
m.add(fun(&Boxed_Value::is_const), "is_var_const");
|
|
m.add(fun(&Boxed_Value::is_ref), "is_var_reference");
|
|
m.add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
|
|
m.add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
|
|
m.add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
|
|
m.add(fun(&Boxed_Value::is_type), "is_type");
|
|
m.add(fun(&Boxed_Value::get_attr), "get_var_attr");
|
|
m.add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
|
|
m.add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
|
|
|
|
m.add(fun(&Boxed_Value::get_type_info), "get_type_info");
|
|
m.add(user_type<Type_Info>(), "Type_Info");
|
|
m.add(constructor<Type_Info(const Type_Info &)>(), "Type_Info");
|
|
|
|
operators::equal<Type_Info>(m);
|
|
|
|
m.add(fun(&Type_Info::is_const), "is_type_const");
|
|
m.add(fun(&Type_Info::is_reference), "is_type_reference");
|
|
m.add(fun(&Type_Info::is_void), "is_type_void");
|
|
m.add(fun(&Type_Info::is_undef), "is_type_undef");
|
|
m.add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
|
m.add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
|
m.add(fun(&Type_Info::name), "cpp_name");
|
|
m.add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
|
m.add(fun(&Type_Info::bare_equal), "bare_equal");
|
|
|
|
basic_constructors<bool>("bool", m);
|
|
operators::assign<bool>(m);
|
|
operators::equal<bool>(m);
|
|
operators::not_equal<bool>(m);
|
|
|
|
m.add(fun([](const std::string &s) { return s; }), "to_string");
|
|
m.add(fun([](const bool b) { return std::string(b ? "true" : "false"); }), "to_string");
|
|
m.add(fun(&unknown_assign), "=");
|
|
m.add(fun([](const Boxed_Value &bv) { throw bv; }), "throw");
|
|
|
|
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
|
m.add(fun(&Boxed_Number::to_string), "to_string");
|
|
|
|
bootstrap_pod_type<double>("double", m);
|
|
bootstrap_pod_type<long double>("long_double", m);
|
|
bootstrap_pod_type<float>("float", m);
|
|
bootstrap_pod_type<int>("int", m);
|
|
bootstrap_pod_type<long>("long", m);
|
|
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
|
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
|
bootstrap_pod_type<long long>("long_long", m);
|
|
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
|
|
bootstrap_pod_type<size_t>("size_t", m);
|
|
bootstrap_pod_type<char>("char", m);
|
|
bootstrap_pod_type<wchar_t>("wchar_t", m);
|
|
bootstrap_pod_type<char16_t>("char16_t", m);
|
|
bootstrap_pod_type<char32_t>("char32_t", m);
|
|
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
|
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
|
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
|
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
|
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
|
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
|
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
|
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
|
|
|
operators::logical_compliment<bool>(m);
|
|
|
|
opers_arithmetic_pod(m);
|
|
|
|
m.add(fun(&Build_Info::version_major), "version_major");
|
|
m.add(fun(&Build_Info::version_minor), "version_minor");
|
|
m.add(fun(&Build_Info::version_patch), "version_patch");
|
|
m.add(fun(&Build_Info::version), "version");
|
|
m.add(fun(&Build_Info::compiler_version), "compiler_version");
|
|
m.add(fun(&Build_Info::compiler_name), "compiler_name");
|
|
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
|
m.add(fun(&Build_Info::debug_build), "debug_build");
|
|
|
|
// print_string and println_string are registered in ChaiScript_Basic::build_eval_system()
|
|
// to support per-instance IO redirection via set_print_handler.
|
|
// When No_IO is set, the functions are still registered but the default handler
|
|
// is a no-op, so users can provide their own print handlers without any stdout output.
|
|
|
|
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
|
|
|
m.add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
|
m.add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
|
m.add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
|
m.add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
|
|
m.add(fun([](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
|
|
t_lhs.assign(t_rhs);
|
|
}),
|
|
"=");
|
|
|
|
m.add(fun(&Boxed_Value::type_match), "type_match");
|
|
|
|
m.add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
|
m.add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
|
|
|
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
|
m.add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
|
|
|
m.add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
|
m.add(chaiscript::base_class<std::runtime_error, chaiscript::exception::arithmetic_error>());
|
|
m.add(chaiscript::base_class<std::exception, chaiscript::exception::arithmetic_error>());
|
|
|
|
// chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> >
|
|
// >("AST_NodeVector", m);
|
|
|
|
chaiscript::utility::add_class<chaiscript::exception::eval_error>(m,
|
|
"eval_error",
|
|
{},
|
|
{{fun(&chaiscript::exception::eval_error::reason), "reason"},
|
|
{fun(&chaiscript::exception::eval_error::pretty_print), "pretty_print"},
|
|
{fun([](const chaiscript::exception::eval_error &t_eval_error) {
|
|
std::vector<Boxed_Value> retval;
|
|
std::transform(t_eval_error.call_stack.begin(),
|
|
t_eval_error.call_stack.end(),
|
|
std::back_inserter(retval),
|
|
&chaiscript::var<const chaiscript::AST_Node_Trace &>);
|
|
return retval;
|
|
}),
|
|
"call_stack"}});
|
|
|
|
chaiscript::utility::add_class<chaiscript::File_Position>(m,
|
|
"File_Position",
|
|
{constructor<File_Position()>(), constructor<File_Position(int, int)>()},
|
|
{{fun(&File_Position::line), "line"},
|
|
{fun(&File_Position::column), "column"}});
|
|
|
|
chaiscript::utility::add_class<AST_Node>(m,
|
|
"AST_Node",
|
|
{},
|
|
{{fun(&AST_Node::text), "text"},
|
|
{fun(&AST_Node::identifier), "identifier"},
|
|
{fun(&AST_Node::filename), "filename"},
|
|
{fun(&AST_Node::start), "start"},
|
|
{fun(&AST_Node::end), "end"},
|
|
{fun(&AST_Node::to_string), "to_string"},
|
|
{fun([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
|
std::vector<Boxed_Value> retval;
|
|
const auto children = t_node.get_children();
|
|
std::transform(children.begin(),
|
|
children.end(),
|
|
std::back_inserter(retval),
|
|
&chaiscript::var<const std::reference_wrapper<chaiscript::AST_Node> &>);
|
|
return retval;
|
|
}),
|
|
"children"}});
|
|
}
|
|
};
|
|
} // namespace chaiscript::bootstrap
|
|
|
|
#endif
|