Compare commits
1 Commits
attempt_gl
...
attempt_re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f10d9980b |
@@ -213,7 +213,7 @@ endif()
|
||||
include_directories(include)
|
||||
|
||||
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
|
||||
@@ -695,10 +695,11 @@
|
||||
/// Begins a function or method definition
|
||||
///
|
||||
/// ~~~~~~~~
|
||||
/// Function Definition ::= "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Function Definition ::= [annotation + CR/LF] "def" identifier "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// Method Definition ::= [annotation + CR/LF] "def" class_name "::" method_name "(" [[type] arg ("," [type] arg)*] ")" [":" guard] block
|
||||
/// ~~~~~~~~
|
||||
///
|
||||
/// annotation: meta-annotation on function, currently used as documentation. Optional.
|
||||
/// identifier: name of function. Required.
|
||||
/// args: comma-delimited list of parameter names with optional type specifiers. Optional.
|
||||
/// guards: guarding statement that act as a prerequisite for the function. Optional.
|
||||
|
||||
@@ -89,54 +89,6 @@ namespace chaiscript {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Build_Info {
|
||||
static int version_major()
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
static std::string version()
|
||||
{
|
||||
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
|
||||
}
|
||||
|
||||
static std::string compiler_id()
|
||||
{
|
||||
return compiler_name() + '-' + compiler_version();
|
||||
}
|
||||
|
||||
static std::string build_id()
|
||||
{
|
||||
return compiler_id() + (debug_build()?"-Debug":"-Release");
|
||||
}
|
||||
|
||||
static std::string compiler_version()
|
||||
{
|
||||
return chaiscript::compiler_version;
|
||||
}
|
||||
|
||||
static std::string compiler_name()
|
||||
{
|
||||
return chaiscript::compiler_name;
|
||||
}
|
||||
|
||||
static bool debug_build()
|
||||
{
|
||||
return chaiscript::debug_build;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Iter, typename Distance>
|
||||
Iter advance_copy(Iter iter, Distance distance) {
|
||||
std::advance(iter, static_cast<typename std::iterator_traits<Iter>::difference_type>(distance));
|
||||
|
||||
@@ -14,15 +14,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
#include "language/chaiscript_common.hpp"
|
||||
|
||||
//#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/operators.hpp"
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
//#include "dispatchkit/boxed_value.hpp"
|
||||
#include "dispatchkit/boxed_value.hpp"
|
||||
#include "language/chaiscript_prelude.hpp"
|
||||
#include "dispatchkit/register_function.hpp"
|
||||
#include "utility/json_wrap.hpp"
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
@@ -42,22 +38,21 @@ namespace chaiscript
|
||||
|
||||
static ModulePtr library()
|
||||
{
|
||||
// using namespace bootstrap;
|
||||
using namespace bootstrap;
|
||||
|
||||
auto lib = std::make_shared<Module>();
|
||||
bootstrap::Bootstrap::bootstrap(*lib);
|
||||
ModulePtr lib = Bootstrap::bootstrap();
|
||||
|
||||
bootstrap::standard_library::vector_type<std::vector<Boxed_Value> >("Vector", *lib);
|
||||
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||
bootstrap::standard_library::map_type<std::map<std::string, Boxed_Value> >("Map", *lib);
|
||||
bootstrap::standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair", *lib);
|
||||
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
lib->add(standard_library::string_type<std::string>("string"));
|
||||
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
bootstrap::standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future", *lib);
|
||||
lib->add(standard_library::future_type<std::future<chaiscript::Boxed_Value>>("future"));
|
||||
lib->add(chaiscript::fun([](const std::function<chaiscript::Boxed_Value ()> &t_func){ return std::async(std::launch::async, t_func);}), "async");
|
||||
#endif
|
||||
|
||||
json_wrap::library(*lib);
|
||||
lib->add(json_wrap::library());
|
||||
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ );
|
||||
|
||||
|
||||
@@ -108,9 +108,6 @@ namespace chaiscript
|
||||
|
||||
#else
|
||||
|
||||
#pragma message ("Threading without thread_local support is not well supported.")
|
||||
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
///
|
||||
|
||||
@@ -27,52 +27,45 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
};
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
return std::function<Ret (Param...)>(
|
||||
[f, o](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
|
||||
auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
|
||||
{
|
||||
return [fo, o, f](Param ...param) -> Ret {
|
||||
return (fo.*f)(o, std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename F, typename O>
|
||||
auto bind_first(const F &f, O&& o)
|
||||
{
|
||||
return bind_first(f, std::forward<O>(o), &F::operator());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,31 @@
|
||||
#ifndef CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
#define CHAISCRIPT_BOOTSTRAP_HPP_
|
||||
|
||||
#include "../utility/utility.hpp"
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "register_function.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "../utility/utility.hpp"
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -28,12 +51,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
||||
void array(const std::string &type, Module& m)
|
||||
ModulePtr array(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename std::remove_extent<T>::type ReturnType;
|
||||
const auto extent = std::extent<T>::value;
|
||||
m.add(user_type<T>(), type);
|
||||
m.add(fun(
|
||||
m->add(user_type<T>(), type);
|
||||
m->add(fun(
|
||||
[extent](T& t, size_t index)->ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
@@ -44,7 +67,7 @@ namespace chaiscript
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m.add(fun(
|
||||
m->add(fun(
|
||||
[extent](const T &t, size_t index)->const ReturnType &{
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
@@ -55,29 +78,33 @@ namespace chaiscript
|
||||
), "[]"
|
||||
);
|
||||
|
||||
m.add(fun(
|
||||
m->add(fun(
|
||||
[extent](const T &) {
|
||||
return extent;
|
||||
}), "size");
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \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
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
template<typename T>
|
||||
void copy_constructor(const std::string &type, Module& m)
|
||||
ModulePtr copy_constructor(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(constructor<T (const T &)>(), type);
|
||||
m->add(constructor<T (const T &)>(), type);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \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.
|
||||
/// \returns the passed in ModulePtr or the newly constructed one if the default params are used.
|
||||
template<typename T>
|
||||
void opers_comparison(Module& m)
|
||||
ModulePtr opers_comparison(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
operators::equal<T>(m);
|
||||
operators::greater_than<T>(m);
|
||||
@@ -85,6 +112,7 @@ namespace chaiscript
|
||||
operators::less_than<T>(m);
|
||||
operators::less_than_equal<T>(m);
|
||||
operators::not_equal<T>(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,14 +121,15 @@ namespace chaiscript
|
||||
/// \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
|
||||
/// \returns The passed in ModulePtr, or the newly constructed one if the default param is used
|
||||
/// \sa copy_constructor
|
||||
/// \sa constructor
|
||||
template<typename T>
|
||||
void basic_constructors(const std::string &type, Module& m)
|
||||
ModulePtr basic_constructors(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(constructor<T ()>(), type);
|
||||
m->add(constructor<T ()>(), type);
|
||||
copy_constructor<T>(type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// \brief Adds a constructor for a POD type
|
||||
@@ -108,12 +137,22 @@ namespace chaiscript
|
||||
/// \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)
|
||||
ModulePtr construct_pod(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(fun(&detail::construct_pod<T>), type);
|
||||
m->add(fun(&detail::construct_pod<T>), type);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// to_string function for internal use. Uses ostream operator<<
|
||||
template<typename Input>
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/// Internal function for converting from a string to a value
|
||||
/// uses ostream operator >> to perform the conversion
|
||||
template<typename Input>
|
||||
@@ -145,13 +184,14 @@ namespace chaiscript
|
||||
/// 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)
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<T>(), name);
|
||||
m.add(constructor<T()>(), name);
|
||||
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(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@@ -220,41 +260,43 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Add all arithmetic operators for PODs
|
||||
static void opers_arithmetic_pod(Module& m)
|
||||
static void opers_arithmetic_pod(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
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::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), ">>");
|
||||
|
||||
|
||||
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
|
||||
@@ -294,6 +336,26 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static void throw_exception(const Boxed_Value &bv) {
|
||||
throw bv;
|
||||
}
|
||||
|
||||
static std::string what(const std::exception &e)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/// Boolean specialization of internal to_string function
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
return "true";
|
||||
} else {
|
||||
return "false";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FunctionType>
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||
const dispatch::Proxy_Function_Base *b)
|
||||
@@ -329,7 +391,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static auto return_boxed_value_vector(const Function &f)
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return [f](const dispatch::Proxy_Function_Base *b) {
|
||||
return do_return_boxed_value_vector(f, b);
|
||||
@@ -340,56 +402,57 @@ namespace chaiscript
|
||||
public:
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
/// \returns passed in Module
|
||||
static void bootstrap(Module& m)
|
||||
/// \returns passed in ModulePtr, or newly created one if default argument is used
|
||||
static ModulePtr bootstrap(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
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(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(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
|
||||
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
|
||||
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(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::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(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(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
|
||||
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(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::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::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->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(
|
||||
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; } );
|
||||
@@ -426,37 +489,37 @@ namespace chaiscript
|
||||
}
|
||||
)chaiscript");
|
||||
|
||||
m.add(fun(&has_guard), "has_guard");
|
||||
m.add(fun(&get_guard), "get_guard");
|
||||
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::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");
|
||||
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");
|
||||
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);
|
||||
@@ -464,15 +527,15 @@ namespace chaiscript
|
||||
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 std::string &s) -> std::string { return s; }), "to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
m->add(fun(&what), "what");
|
||||
|
||||
m.add(fun([](const char c) { return std::string(1, c); }), "to_string");
|
||||
m.add(fun(&Boxed_Number::to_string), "to_string");
|
||||
m->add(fun(&to_string<char>), "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);
|
||||
@@ -496,71 +559,58 @@ namespace chaiscript
|
||||
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");
|
||||
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m.add(fun(&print), "print_string");
|
||||
m.add(fun(&println), "println_string");
|
||||
m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||
|
||||
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(
|
||||
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(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::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::base_class<std::runtime_error, 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>());
|
||||
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, 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,
|
||||
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) {
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
|
||||
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 std::shared_ptr<const chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
}), "call_stack"} }
|
||||
})), "call_stack"} }
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(m,
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
constructor<File_Position(int, int)>() },
|
||||
@@ -569,7 +619,7 @@ namespace chaiscript
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(m,
|
||||
chaiscript::utility::add_class<AST_Node>(*m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
{ {fun(&AST_Node::text), "text"},
|
||||
@@ -578,17 +628,28 @@ namespace chaiscript
|
||||
{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> {
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](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::transform(t_node.children.begin(), t_node.children.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<const std::shared_ptr<chaiscript::AST_Node> &>);
|
||||
return retval;
|
||||
}), "children"}
|
||||
})), "children"},
|
||||
{fun(&AST_Node::replace_child), "replace_child"}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
|
||||
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
|
||||
);
|
||||
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -177,20 +177,22 @@ namespace chaiscript
|
||||
|
||||
/// Add Bidir_Range support for the given ContainerType
|
||||
template<typename Bidir_Type>
|
||||
void input_range_type_impl(const std::string &type, Module& m)
|
||||
ModulePtr input_range_type_impl(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<Bidir_Type>(), type + "_Range");
|
||||
m->add(user_type<Bidir_Type>(), type + "_Range");
|
||||
|
||||
copy_constructor<Bidir_Type>(type + "_Range", m);
|
||||
|
||||
m.add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
m->add(constructor<Bidir_Type (typename Bidir_Type::container_type &)>(), "range_internal");
|
||||
|
||||
m.add(fun(&Bidir_Type::empty), "empty");
|
||||
m.add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
m.add(fun(&Bidir_Type::front), "front");
|
||||
m.add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||
m.add(fun(&Bidir_Type::back), "back");
|
||||
}
|
||||
m->add(fun(&Bidir_Type::empty), "empty");
|
||||
m->add(fun(&Bidir_Type::pop_front), "pop_front");
|
||||
m->add(fun(&Bidir_Type::front), "front");
|
||||
m->add(fun(&Bidir_Type::pop_back), "pop_back");
|
||||
m->add(fun(&Bidir_Type::back), "back");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Algorithm for inserting at a specific position into a container
|
||||
@@ -228,16 +230,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
void input_range_type(const std::string &type, Module& m)
|
||||
ModulePtr input_range_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
detail::input_range_type_impl<Bidir_Range<ContainerType> >(type,m);
|
||||
detail::input_range_type_impl<Const_Bidir_Range<ContainerType> >("Const_" + type, m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr input_range_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
input_range_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -245,11 +241,11 @@ namespace chaiscript
|
||||
/// Add random_access_container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/RandomAccessContainer.html
|
||||
template<typename ContainerType>
|
||||
void random_access_container_type(const std::string &/*type*/, Module& m)
|
||||
ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
//to throw an exception in an out of bounds condition.
|
||||
m.add(
|
||||
m->add(
|
||||
fun(
|
||||
[](ContainerType &c, int index) -> typename ContainerType::reference {
|
||||
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||
@@ -257,71 +253,25 @@ namespace chaiscript
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
|
||||
m.add(
|
||||
m->add(
|
||||
fun(
|
||||
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
|
||||
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
|
||||
/// during dispatch. reevaluate
|
||||
return c.at(static_cast<typename ContainerType::size_type>(index));
|
||||
}), "[]");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr random_access_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
random_access_container_type<ContainerType>(type, *m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add assignable concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Assignable.html
|
||||
template<typename ContainerType>
|
||||
void assignable_type(const std::string &type, Module& m)
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
copy_constructor<ContainerType>(type, m);
|
||||
operators::assign<ContainerType>(m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
assignable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add container resize concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void resizable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr resizable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
resizable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add container reserve concept to the given ContainerType
|
||||
/// http://www.cplusplus.com/reference/stl/
|
||||
template<typename ContainerType>
|
||||
void reservable_type(const std::string &/*type*/, Module& m)
|
||||
{
|
||||
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
|
||||
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr reservable_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
reservable_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -329,44 +279,33 @@ namespace chaiscript
|
||||
/// Add container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Container.html
|
||||
template<typename ContainerType>
|
||||
void container_type(const std::string &/*type*/, Module& m)
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
m->add(fun([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m->add(fun([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
return m;
|
||||
}
|
||||
template <typename ContainerType>
|
||||
ModulePtr container_type(const std::string& type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
container_type<ContainerType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add default constructable concept to the given Type
|
||||
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
|
||||
template<typename Type>
|
||||
void default_constructible_type(const std::string &type, Module& m)
|
||||
ModulePtr default_constructible_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(constructor<Type ()>(), type);
|
||||
}
|
||||
template <typename Type>
|
||||
ModulePtr default_constructible_type(const std::string& type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
default_constructible_type<Type>(type, *m);
|
||||
m->add(constructor<Type ()>(), type);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Add sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/Sequence.html
|
||||
template<typename ContainerType>
|
||||
void sequence_type(const std::string &/*type*/, Module& m)
|
||||
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(fun(&detail::insert_at<ContainerType>),
|
||||
m->add(fun(&detail::insert_at<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref_at";
|
||||
@@ -375,31 +314,27 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||
}
|
||||
template <typename ContainerType>
|
||||
ModulePtr sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
sequence_type<ContainerType>(type, *m);
|
||||
m->add(fun(&detail::erase_at<ContainerType>), "erase_at");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
void back_insertion_sequence_type(const std::string &type, Module& m)
|
||||
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
m.add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
m->add(fun(static_cast<backptr>(&ContainerType::back)), "back");
|
||||
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m.eval(
|
||||
m->eval(
|
||||
"# Pushes the second value onto the container while making a clone of the value\n"
|
||||
"def push_back(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
@@ -418,13 +353,7 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m.add(fun(&ContainerType::pop_back), "pop_back");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
back_insertion_sequence_type<ContainerType>(type, *m);
|
||||
m->add(fun(&ContainerType::pop_back), "pop_back");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -433,20 +362,20 @@ namespace chaiscript
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
void front_insertion_sequence_type(const std::string &type, Module& m)
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*pop_ptr)();
|
||||
|
||||
m.add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m.add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<front_ptr>(&ContainerType::front)), "front");
|
||||
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
|
||||
m.add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m.eval(
|
||||
m->eval(
|
||||
"# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||
"def push_front(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
@@ -464,13 +393,7 @@ namespace chaiscript
|
||||
}
|
||||
}());
|
||||
|
||||
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
front_insertion_sequence_type<ContainerType>(type, *m);
|
||||
m->add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -478,25 +401,20 @@ namespace chaiscript
|
||||
/// bootstrap a given PairType
|
||||
/// http://www.sgi.com/tech/stl/pair.html
|
||||
template<typename PairType>
|
||||
void pair_type(const std::string &type, Module& m)
|
||||
ModulePtr pair_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<PairType>(), type);
|
||||
m->add(user_type<PairType>(), type);
|
||||
|
||||
|
||||
typename PairType::first_type PairType::* f = &PairType::first;
|
||||
typename PairType::second_type PairType::* s = &PairType::second;
|
||||
|
||||
m.add(fun(f), "first");
|
||||
m.add(fun(s), "second");
|
||||
m->add(fun(f), "first");
|
||||
m->add(fun(s), "second");
|
||||
|
||||
basic_constructors<PairType>(type, m);
|
||||
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
}
|
||||
template<typename PairType>
|
||||
ModulePtr pair_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
pair_type<PairType>(type, *m);
|
||||
m->add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -506,15 +424,10 @@ namespace chaiscript
|
||||
/// http://www.sgi.com/tech/stl/PairAssociativeContainer.html
|
||||
|
||||
template<typename ContainerType>
|
||||
void pair_associative_container_type(const std::string &type, Module& m)
|
||||
ModulePtr pair_associative_container_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr pair_associative_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
pair_associative_container_type<ContainerType>(type, *m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -522,17 +435,17 @@ namespace chaiscript
|
||||
/// Add unique associative container concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
template<typename ContainerType>
|
||||
void unique_associative_container_type(const std::string &/*type*/, Module& m)
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(fun(detail::count<ContainerType>), "count");
|
||||
m->add(fun(detail::count<ContainerType>), "count");
|
||||
|
||||
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
|
||||
|
||||
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
m->add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
|
||||
m.add(fun(&detail::insert<ContainerType>), "insert");
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
m.add(fun(&detail::insert_ref<ContainerType>),
|
||||
m->add(fun(&detail::insert_ref<ContainerType>),
|
||||
[]()->std::string{
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
|
||||
return "insert_ref";
|
||||
@@ -540,12 +453,8 @@ namespace chaiscript
|
||||
return "insert";
|
||||
}
|
||||
}());
|
||||
}
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
unique_associative_container_type<ContainerType>(type, *m);
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -553,21 +462,21 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename MapType>
|
||||
void map_type(const std::string &type, Module& m)
|
||||
ModulePtr map_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<MapType>(), type);
|
||||
m->add(user_type<MapType>(), type);
|
||||
|
||||
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
|
||||
typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
|
||||
|
||||
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
m->add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
|
||||
m.add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||
m.add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
|
||||
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
|
||||
|
||||
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
|
||||
{
|
||||
m.eval(R"(
|
||||
m->eval(R"(
|
||||
def Map::`==`(Map rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
@@ -595,12 +504,7 @@ namespace chaiscript
|
||||
unique_associative_container_type<MapType>(type, m);
|
||||
pair_associative_container_type<MapType>(type, m);
|
||||
input_range_type<MapType>(type, m);
|
||||
}
|
||||
template<typename MapType>
|
||||
ModulePtr map_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
map_type<MapType>(type, *m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -608,24 +512,18 @@ namespace chaiscript
|
||||
/// hopefully working List type
|
||||
/// http://www.sgi.com/tech/stl/List.html
|
||||
template<typename ListType>
|
||||
void list_type(const std::string &type, Module& m)
|
||||
ModulePtr list_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<ListType>(), type);
|
||||
m->add(user_type<ListType>(), type);
|
||||
|
||||
front_insertion_sequence_type<ListType>(type, m);
|
||||
back_insertion_sequence_type<ListType>(type, m);
|
||||
sequence_type<ListType>(type, m);
|
||||
resizable_type<ListType>(type, m);
|
||||
container_type<ListType>(type, m);
|
||||
default_constructible_type<ListType>(type, m);
|
||||
assignable_type<ListType>(type, m);
|
||||
input_range_type<ListType>(type, m);
|
||||
}
|
||||
template<typename ListType>
|
||||
ModulePtr list_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
list_type<ListType>(type, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -633,22 +531,20 @@ namespace chaiscript
|
||||
/// Create a vector type with associated concepts
|
||||
/// http://www.sgi.com/tech/stl/Vector.html
|
||||
template<typename VectorType>
|
||||
void vector_type(const std::string &type, Module& m)
|
||||
ModulePtr vector_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<VectorType>(), type);
|
||||
m->add(user_type<VectorType>(), type);
|
||||
|
||||
typedef typename VectorType::reference (VectorType::*frontptr)();
|
||||
typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const;
|
||||
|
||||
m.add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m.add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
m->add(fun(static_cast<frontptr>(&VectorType::front)), "front");
|
||||
m->add(fun(static_cast<constfrontptr>(&VectorType::front)), "front");
|
||||
|
||||
|
||||
back_insertion_sequence_type<VectorType>(type, m);
|
||||
sequence_type<VectorType>(type, m);
|
||||
random_access_container_type<VectorType>(type, m);
|
||||
resizable_type<VectorType>(type, m);
|
||||
reservable_type<VectorType>(type, m);
|
||||
container_type<VectorType>(type, m);
|
||||
default_constructible_type<VectorType>(type, m);
|
||||
assignable_type<VectorType>(type, m);
|
||||
@@ -656,7 +552,7 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
m.eval(R"(
|
||||
m->eval(R"(
|
||||
def Vector::`==`(Vector rhs) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
@@ -677,21 +573,16 @@ namespace chaiscript
|
||||
} )"
|
||||
);
|
||||
}
|
||||
}
|
||||
template<typename VectorType>
|
||||
ModulePtr vector_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
vector_type<VectorType>(type, *m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// Add a String container
|
||||
/// http://www.sgi.com/tech/stl/basic_string.html
|
||||
template<typename String>
|
||||
void string_type(const std::string &type, Module& m)
|
||||
ModulePtr string_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<String>(), type);
|
||||
m->add(user_type<String>(), type);
|
||||
operators::addition<String>(m);
|
||||
operators::assign_sum<String>(m);
|
||||
opers_comparison<String>(m);
|
||||
@@ -703,7 +594,7 @@ namespace chaiscript
|
||||
input_range_type<String>(type, m);
|
||||
|
||||
//Special case: add push_back to string (which doesn't support other back_insertion operations
|
||||
m.add(fun(&String::push_back),
|
||||
m->add(fun(&String::push_back),
|
||||
[]()->std::string{
|
||||
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
|
||||
return "push_back_ref";
|
||||
@@ -713,26 +604,21 @@ namespace chaiscript
|
||||
}());
|
||||
|
||||
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
|
||||
m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of");
|
||||
m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of");
|
||||
|
||||
m.add(fun([](String *s) { s->clear(); } ), "clear");
|
||||
m.add(fun([](const String *s) { return s->empty(); } ), "empty");
|
||||
m.add(fun([](const String *s) { return s->size(); } ), "size");
|
||||
m->add(fun([](String *s) { s->clear(); } ), "clear");
|
||||
m->add(fun([](const String *s) { return s->empty(); } ), "empty");
|
||||
m->add(fun([](const String *s) { return s->size(); } ), "size");
|
||||
|
||||
m->add(fun([](const String *s) { return s->c_str(); } ), "c_str");
|
||||
m->add(fun([](const String *s) { return s->data(); } ), "data");
|
||||
m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
|
||||
|
||||
m.add(fun([](const String *s) { return s->c_str(); } ), "c_str");
|
||||
m.add(fun([](const String *s) { return s->data(); } ), "data");
|
||||
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
|
||||
}
|
||||
template<typename String>
|
||||
ModulePtr string_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
string_type<String>(type, *m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -741,19 +627,14 @@ namespace chaiscript
|
||||
/// Add a MapType container
|
||||
/// http://www.sgi.com/tech/stl/Map.html
|
||||
template<typename FutureType>
|
||||
void future_type(const std::string &type, Module& m)
|
||||
ModulePtr future_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(user_type<FutureType>(), type);
|
||||
m->add(user_type<FutureType>(), type);
|
||||
|
||||
m->add(fun([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m->add(fun(&FutureType::get), "get");
|
||||
m->add(fun(&FutureType::wait), "wait");
|
||||
|
||||
m.add(fun([](const FutureType &t) { return t.valid(); }), "valid");
|
||||
m.add(fun(&FutureType::get), "get");
|
||||
m.add(fun(&FutureType::wait), "wait");
|
||||
}
|
||||
template<typename FutureType>
|
||||
ModulePtr future_type(const std::string &type)
|
||||
{
|
||||
auto m = std::make_shared<Module>();
|
||||
future_type<FutureType>(type, *m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
|
||||
{
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !(*t_conversions)->convertable_type<Type>())) {
|
||||
try {
|
||||
return(detail::Cast_Helper<Type>::cast(bv, t_conversions));
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
@@ -84,11 +84,11 @@ namespace chaiscript
|
||||
try {
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// try going the other way
|
||||
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));
|
||||
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
@@ -29,50 +29,21 @@ namespace chaiscript
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||
if (ob.get_type_info() == ti) {
|
||||
return ptr;
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
|
||||
if (!ob.is_const() && ob.get_type_info() == ti) {
|
||||
return ptr;
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
|
||||
if (ob.get_type_info().bare_equal_type_info(ti)) {
|
||||
return throw_if_null(ptr);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
|
||||
if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
|
||||
return throw_if_null(ptr);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic Cast_Helper_Inner, for casting to any type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef typename std::add_const<Result>::type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
auto p = throw_if_null(ob.get_const_ptr());
|
||||
return *static_cast<const Result *>(p);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,9 +57,15 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return static_cast<const Result *>(ob.get_const_ptr());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,9 +73,15 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
||||
{
|
||||
return static_cast<Result *>(ob.get_ptr());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,9 +100,17 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef const Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
auto p = throw_if_null(ob.get_const_ptr());
|
||||
return *static_cast<const Result *>(p);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,9 +120,16 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,7 +137,9 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@@ -149,7 +149,9 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -175,7 +177,10 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<std::shared_ptr<Result> &>
|
||||
{
|
||||
static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
|
||||
static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
|
||||
typedef Boxed_Value::Sentinel<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
|
||||
return ob.pointer_sentinel(res);
|
||||
@@ -199,7 +204,9 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef Boxed_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@@ -209,7 +216,9 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value &>
|
||||
{
|
||||
static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef std::reference_wrapper<Boxed_Value> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||
}
|
||||
@@ -263,9 +272,11 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Cast_Helper
|
||||
{
|
||||
static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -162,17 +162,17 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::equals:
|
||||
case Operators::equals:
|
||||
return const_var(t == u);
|
||||
case Operators::Opers::less_than:
|
||||
case Operators::less_than:
|
||||
return const_var(t < u);
|
||||
case Operators::Opers::greater_than:
|
||||
case Operators::greater_than:
|
||||
return const_var(t > u);
|
||||
case Operators::Opers::less_than_equal:
|
||||
case Operators::less_than_equal:
|
||||
return const_var(t <= u);
|
||||
case Operators::Opers::greater_than_equal:
|
||||
case Operators::greater_than_equal:
|
||||
return const_var(t >= u);
|
||||
case Operators::Opers::not_equal:
|
||||
case Operators::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -184,10 +184,10 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::pre_increment:
|
||||
case Operators::pre_increment:
|
||||
++t;
|
||||
break;
|
||||
case Operators::Opers::pre_decrement:
|
||||
case Operators::pre_decrement:
|
||||
--t;
|
||||
break;
|
||||
default:
|
||||
@@ -202,20 +202,20 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::assign:
|
||||
case Operators::assign:
|
||||
t = u;
|
||||
break;
|
||||
case Operators::Opers::assign_product:
|
||||
case Operators::assign_product:
|
||||
t *= u;
|
||||
break;
|
||||
case Operators::Opers::assign_sum:
|
||||
case Operators::assign_sum:
|
||||
t += u;
|
||||
break;
|
||||
case Operators::Opers::assign_quotient:
|
||||
case Operators::assign_quotient:
|
||||
check_divide_by_zero(u);
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::Opers::assign_difference:
|
||||
case Operators::assign_difference:
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
@@ -230,23 +230,23 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::assign_bitwise_and:
|
||||
case Operators::assign_bitwise_and:
|
||||
t &= u;
|
||||
break;
|
||||
case Operators::Opers::assign_bitwise_or:
|
||||
case Operators::assign_bitwise_or:
|
||||
t |= u;
|
||||
break;
|
||||
case Operators::Opers::assign_shift_left:
|
||||
case Operators::assign_shift_left:
|
||||
t <<= u;
|
||||
break;
|
||||
case Operators::Opers::assign_shift_right:
|
||||
case Operators::assign_shift_right:
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::Opers::assign_remainder:
|
||||
case Operators::assign_remainder:
|
||||
check_divide_by_zero(u);
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::Opers::assign_bitwise_xor:
|
||||
case Operators::assign_bitwise_xor:
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
@@ -260,7 +260,7 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::bitwise_complement:
|
||||
case Operators::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -272,18 +272,18 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::shift_left:
|
||||
case Operators::shift_left:
|
||||
return const_var(t << u);
|
||||
case Operators::Opers::shift_right:
|
||||
case Operators::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::Opers::remainder:
|
||||
case Operators::remainder:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t % u);
|
||||
case Operators::Opers::bitwise_and:
|
||||
case Operators::bitwise_and:
|
||||
return const_var(t & u);
|
||||
case Operators::Opers::bitwise_or:
|
||||
case Operators::bitwise_or:
|
||||
return const_var(t | u);
|
||||
case Operators::Opers::bitwise_xor:
|
||||
case Operators::bitwise_xor:
|
||||
return const_var(t ^ u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -295,9 +295,9 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::unary_minus:
|
||||
case Operators::unary_minus:
|
||||
return const_var(-t);
|
||||
case Operators::Opers::unary_plus:
|
||||
case Operators::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -309,14 +309,14 @@ namespace chaiscript
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::sum:
|
||||
case Operators::sum:
|
||||
return const_var(t + u);
|
||||
case Operators::Opers::quotient:
|
||||
case Operators::quotient:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t / u);
|
||||
case Operators::Opers::product:
|
||||
case Operators::product:
|
||||
return const_var(t * u);
|
||||
case Operators::Opers::difference:
|
||||
case Operators::difference:
|
||||
return const_var(t - u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -328,16 +328,16 @@ namespace chaiscript
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -349,12 +349,12 @@ namespace chaiscript
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -366,11 +366,11 @@ namespace chaiscript
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -381,9 +381,9 @@ namespace chaiscript
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@@ -502,7 +502,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
explicit Boxed_Number(Boxed_Value v)
|
||||
Boxed_Number(Boxed_Value v)
|
||||
: bv(std::move(v))
|
||||
{
|
||||
validate_boxed_number(bv);
|
||||
@@ -645,6 +645,71 @@ namespace chaiscript
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::equals, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator>=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator<=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
bool operator!=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, this->bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
Boxed_Number operator--()
|
||||
{
|
||||
return oper(Operators::pre_decrement, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator++()
|
||||
{
|
||||
return oper(Operators::pre_increment, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator+(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator+() const
|
||||
{
|
||||
return oper(Operators::unary_plus, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator-() const
|
||||
{
|
||||
return oper(Operators::unary_minus, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator-(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
@@ -659,165 +724,266 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Value &v)
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
bv = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// cppcheck-suppress operatorEq
|
||||
Boxed_Number operator=(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::assign, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator^=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator&(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_and, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator~() const
|
||||
{
|
||||
return oper(Operators::bitwise_complement, this->bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator^(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_xor, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator|(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::bitwise_or, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_product, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator/=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator+=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_sum, this->bv, t_rhs.bv);
|
||||
}
|
||||
Boxed_Number operator-=(const Boxed_Number &t_rhs)
|
||||
{
|
||||
return oper(Operators::assign_difference, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator/(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::quotient, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator<<(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_left, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator*(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::product, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator%(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::remainder, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
Boxed_Number operator>>(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
return oper(Operators::shift_right, this->bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool equals(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::equals, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::equals, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::less_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::greater_than, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool greater_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::greater_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool less_than_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::less_than_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static bool not_equal(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return boxed_cast<bool>(oper(Operators::Opers::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
return boxed_cast<bool>(oper(Operators::not_equal, t_lhs.bv, t_rhs.bv));
|
||||
}
|
||||
|
||||
static Boxed_Number pre_decrement(Boxed_Number t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::pre_decrement, t_lhs.bv));
|
||||
return oper(Operators::pre_decrement, t_lhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number pre_increment(Boxed_Number t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::pre_increment, t_lhs.bv));
|
||||
return oper(Operators::pre_increment, t_lhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::sum, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::sum, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_plus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::unary_plus, t_lhs.bv));
|
||||
return oper(Operators::unary_plus, t_lhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number unary_minus(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::unary_minus, t_lhs.bv));
|
||||
return oper(Operators::unary_minus, t_lhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::difference, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::difference, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_and(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_or(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_bitwise_xor(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_remainder(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_remainder, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_remainder, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_left(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_left, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_shift_left, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_shift_right(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_shift_right, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_shift_right, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_and(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_and, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::bitwise_and, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_complement(const Boxed_Number &t_lhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_complement, t_lhs.bv, Boxed_Value(0)));
|
||||
return oper(Operators::bitwise_complement, t_lhs.bv, Boxed_Value(0));
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_xor(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_xor, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::bitwise_xor, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number bitwise_or(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::bitwise_or, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::bitwise_or, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_product(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_product, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_product, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_quotient(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_quotient, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_quotient, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static Boxed_Number assign_sum(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_sum, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_sum, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
static Boxed_Number assign_difference(Boxed_Number t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::assign_difference, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::assign_difference, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number quotient(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::quotient, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::quotient, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_left(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::shift_left, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::shift_left, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number product(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::product, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::product, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number remainder(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::remainder, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::remainder, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
static const Boxed_Number shift_right(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs)
|
||||
{
|
||||
return Boxed_Number(oper(Operators::Opers::shift_right, t_lhs.bv, t_rhs.bv));
|
||||
return oper(Operators::shift_right, t_lhs.bv, t_rhs.bv);
|
||||
}
|
||||
|
||||
|
||||
@@ -843,7 +1009,9 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
static Boxed_Number cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
|
||||
@@ -226,39 +226,48 @@ namespace chaiscript
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Sentinel {
|
||||
Sentinel(std::shared_ptr<T> &ptr, Data &data)
|
||||
: m_ptr(ptr), m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
~Sentinel()
|
||||
{
|
||||
// save new pointer data
|
||||
m_data.get().m_data_ptr = m_ptr.get().get();
|
||||
m_data.get().m_const_data_ptr = m_ptr.get().get();
|
||||
}
|
||||
|
||||
Sentinel& operator=(Sentinel&&s) {
|
||||
m_ptr = std::move(s.m_ptr);
|
||||
m_data = std::move(s.m_data);
|
||||
}
|
||||
|
||||
Sentinel(Sentinel &&s)
|
||||
: m_ptr(std::move(s.m_ptr)),
|
||||
m_data(std::move(s.m_data))
|
||||
{
|
||||
}
|
||||
|
||||
operator std::shared_ptr<T>&() const
|
||||
{
|
||||
return m_ptr.get();
|
||||
}
|
||||
|
||||
Sentinel &operator=(const Sentinel &) = delete;
|
||||
Sentinel(Sentinel&) = delete;
|
||||
|
||||
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||
std::reference_wrapper<Data> m_data;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
|
||||
Sentinel<T> pointer_sentinel(std::shared_ptr<T> &ptr) const
|
||||
{
|
||||
struct Sentinel {
|
||||
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
||||
: m_ptr(t_ptr), m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
~Sentinel()
|
||||
{
|
||||
// save new pointer data
|
||||
m_data.get().m_data_ptr = m_ptr.get().get();
|
||||
m_data.get().m_const_data_ptr = m_ptr.get().get();
|
||||
}
|
||||
|
||||
Sentinel& operator=(Sentinel&&s) = default;
|
||||
Sentinel(Sentinel &&s) = default;
|
||||
|
||||
operator std::shared_ptr<T>&() const
|
||||
{
|
||||
return m_ptr.get();
|
||||
}
|
||||
|
||||
Sentinel &operator=(const Sentinel &) = delete;
|
||||
Sentinel(Sentinel&) = delete;
|
||||
|
||||
std::reference_wrapper<std::shared_ptr<T>> m_ptr;
|
||||
std::reference_wrapper<Data> m_data;
|
||||
};
|
||||
|
||||
return Sentinel(ptr, *(m_data.get()));
|
||||
return Sentinel<T>(ptr, *(m_data.get()));
|
||||
}
|
||||
|
||||
bool is_null() const noexcept
|
||||
|
||||
@@ -13,53 +13,6 @@ namespace chaiscript {
|
||||
namespace dispatch {
|
||||
namespace detail {
|
||||
|
||||
template<typename Class, typename ... Param>
|
||||
struct Constructor
|
||||
{
|
||||
template<typename ... Inner>
|
||||
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
|
||||
return std::make_shared<Class>(std::forward<Inner>(inner)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Const_Caller
|
||||
{
|
||||
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(const Class &o, Inner&& ... inner) const {
|
||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
Ret (Class::*m_func)(Param...) const;
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Fun_Caller
|
||||
{
|
||||
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Inner&& ... inner) const {
|
||||
return (m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
Ret(*m_func)(Param...);
|
||||
};
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
struct Caller
|
||||
{
|
||||
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
|
||||
|
||||
template<typename ... Inner>
|
||||
Ret operator()(Class &o, Inner&& ... inner) const {
|
||||
return (o.*m_func)(std::forward<Inner>(inner)...);
|
||||
}
|
||||
|
||||
Ret (Class::*m_func)(Param...);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Arity
|
||||
|
||||
@@ -37,9 +37,6 @@ class Boxed_Number;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript {
|
||||
namespace parser {
|
||||
class ChaiScript_Parser_Base;
|
||||
}
|
||||
namespace dispatch {
|
||||
class Dynamic_Proxy_Function;
|
||||
class Proxy_Function_Base;
|
||||
@@ -48,7 +45,6 @@ struct Placeholder_Object;
|
||||
} // namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/// \namespace chaiscript::dispatch
|
||||
/// \brief Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use to the end user.
|
||||
|
||||
@@ -182,6 +178,12 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const std::shared_ptr<Module> &m)
|
||||
{
|
||||
m->apply(*this, *this);
|
||||
return *m;
|
||||
}
|
||||
|
||||
template<typename Eval, typename Engine>
|
||||
void apply(Eval &t_eval, Engine &t_engine) const
|
||||
{
|
||||
@@ -314,6 +316,11 @@ namespace chaiscript
|
||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||
}
|
||||
|
||||
std::string annotation() const override
|
||||
{
|
||||
return "Multiple method dispatch function wrapper.";
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
@@ -380,6 +387,7 @@ namespace chaiscript
|
||||
typedef std::vector<Scope> StackData;
|
||||
|
||||
Stack_Holder()
|
||||
: call_depth(0)
|
||||
{
|
||||
stacks.reserve(2);
|
||||
stacks.emplace_back(1);
|
||||
@@ -390,7 +398,7 @@ namespace chaiscript
|
||||
std::vector<StackData> stacks;
|
||||
|
||||
std::vector<std::vector<Boxed_Value>> call_params;
|
||||
int call_depth = 0;
|
||||
int call_depth;
|
||||
};
|
||||
|
||||
/// Main class for the dispatchkit. Handles management
|
||||
@@ -410,24 +418,28 @@ namespace chaiscript
|
||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
std::set<std::string> m_reserved_words
|
||||
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
|
||||
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"};
|
||||
std::set<std::string> m_reserved_words;
|
||||
|
||||
State &operator=(const State &) = default;
|
||||
State() = default;
|
||||
State(const State &) = default;
|
||||
};
|
||||
|
||||
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
||||
: m_stack_holder(this),
|
||||
m_parser(parser)
|
||||
Dispatch_Engine()
|
||||
: m_stack_holder(this)
|
||||
{
|
||||
}
|
||||
|
||||
~Dispatch_Engine()
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||
template<typename Type>
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
|
||||
return(chaiscript::boxed_cast<Type>(bv, &state));
|
||||
return chaiscript::boxed_cast<Type>(bv, &state);
|
||||
}
|
||||
|
||||
/// Add a new conversion for upcasting to a base class
|
||||
@@ -880,6 +892,12 @@ namespace chaiscript
|
||||
return rets;
|
||||
}
|
||||
|
||||
void add_reserved_word(const std::string &name)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
const Type_Conversions &conversions() const
|
||||
{
|
||||
@@ -1046,7 +1064,11 @@ namespace chaiscript
|
||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
||||
{
|
||||
std::vector<Type_Info> params = f.second->get_param_types();
|
||||
std::string annotation = f.second->annotation();
|
||||
|
||||
if (annotation.size() > 0) {
|
||||
std::cout << annotation;
|
||||
}
|
||||
dump_type(params.front());
|
||||
std::cout << " " << f.first << "(";
|
||||
|
||||
@@ -1237,11 +1259,6 @@ namespace chaiscript
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
parser::ChaiScript_Parser_Base &get_parser()
|
||||
{
|
||||
return m_parser.get();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
|
||||
@@ -1338,6 +1355,10 @@ namespace chaiscript
|
||||
|
||||
if (rt.bare_equal(boxed_type))
|
||||
{
|
||||
if (lt.bare_equal(boxed_pod_type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1467,7 +1488,6 @@ namespace chaiscript
|
||||
|
||||
Type_Conversions m_conversions;
|
||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
std::reference_wrapper<parser::ChaiScript_Parser_Base> m_parser;
|
||||
|
||||
mutable std::atomic_uint_fast32_t m_method_missing_loc;
|
||||
|
||||
@@ -1522,4 +1542,3 @@ namespace chaiscript
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -98,6 +98,12 @@ namespace chaiscript
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
std::string annotation() const override
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
@@ -213,6 +219,11 @@ namespace chaiscript
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
std::string annotation() const override
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
|
||||
@@ -81,7 +81,9 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -96,7 +98,9 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -111,7 +115,9 @@ namespace chaiscript
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
|
||||
@@ -141,22 +141,6 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
/*
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
|
||||
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
|
||||
(funcs[0]);
|
||||
|
||||
if (pfi)
|
||||
{
|
||||
return pfi->internal_function();
|
||||
}
|
||||
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
*/
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,19 @@ class Boxed_Number;
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
template<typename T> std::shared_ptr<dispatch::Proxy_Function_Base> fun(const T &t);
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
std::shared_ptr<dispatch::Proxy_Function_Base> assignable_fun(
|
||||
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
|
||||
std::shared_ptr<std::function<Ret (Param...)>> t_ptr
|
||||
);
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
template<class T, class U> class Proxy_Function_Callable_Impl;
|
||||
template<class T> class Assignable_Proxy_Function_Impl;
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
@@ -53,7 +61,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
|
||||
chaiscript::fun(f)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -68,7 +76,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
|
||||
assignable_fun(std::ref(*f), f)
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -88,36 +96,17 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(f),
|
||||
std::shared_ptr<std::function<Ret>>())
|
||||
assignable_fun(std::ref(f), std::shared_ptr<std::function<Ret>>())
|
||||
);
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const std::function<Ret> &f) {
|
||||
return Boxed_Value(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
|
||||
chaiscript::fun(f)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *&>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p, true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret *>
|
||||
{
|
||||
@@ -164,14 +153,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret>
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<Ret &>
|
||||
@@ -180,6 +161,11 @@ namespace chaiscript
|
||||
{
|
||||
return Boxed_Value(std::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
||||
@@ -16,202 +16,447 @@ namespace chaiscript
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign(L l, R r) -> L&
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_xor(L l, R r) -> decltype((l^=r))
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_difference(L l, R r) -> decltype(( l -= r))
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_product(L l, R r) -> decltype(( l *= r ))
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign_sum(L l, R r) -> L&
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto prefix_decrement(L l) -> decltype(( --l ))
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto prefix_increment(L l) -> decltype(( ++l ))
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto equal(L l, R r) -> decltype(( l == r ))
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto greater_than(L l, R r) -> decltype(( l > r ))
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto less_than(L l, R r) -> decltype(( l < r ))
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto logical_compliment(L l) -> decltype(( !l ))
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto not_equal(L l, R r) -> decltype(( l != r ))
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto addition(L l, R r) -> decltype(( l + r ))
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto unary_plus(L l) -> decltype(( +l ))
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto subtraction(L l, R r) -> decltype(( l - r ))
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto unary_minus(L l) -> decltype(( -l ))
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
return (-l);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_and(L l, R r) -> decltype(( l & r ))
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
auto bitwise_compliment(L l) -> decltype(( ~l ))
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto bitwise_or(L l, R r) -> decltype(( l | r ))
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto division(L l, R r) -> decltype(( l / r ))
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto left_shift(L l, R r) -> decltype(( l << r ))
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto multiplication(L l, R r) -> decltype(( l * r ))
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto remainder(L l, R r) -> decltype(( l % r ))
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto right_shift(L l, R r) -> decltype(( l >> r ))
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
void assign(Module& m)
|
||||
ModulePtr assign(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs = rhs;}), "=");
|
||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_bitwise_and(Module& m)
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs &= rhs;}), "&=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_xor(Module& m)
|
||||
ModulePtr assign_xor(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs ^= rhs;}), "^=");
|
||||
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_bitwise_or(Module& m)
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs |= rhs;}), "|=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_difference(Module& m)
|
||||
ModulePtr assign_difference(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs -= rhs;}), "-=");
|
||||
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_left_shift(Module& m)
|
||||
ModulePtr assign_left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "<<=");
|
||||
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_product(Module& m)
|
||||
ModulePtr assign_product(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs <<= rhs;}), "*=");
|
||||
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_quotient(Module& m)
|
||||
ModulePtr assign_quotient(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs /= rhs;}), "/=");
|
||||
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_remainder(Module& m)
|
||||
ModulePtr assign_remainder(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs %= rhs;}), "%=");
|
||||
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_right_shift(Module& m)
|
||||
ModulePtr assign_right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs >>= rhs;}), ">>=");
|
||||
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assign_sum(Module& m)
|
||||
ModulePtr assign_sum(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs, const T&rhs)->T&{return lhs += rhs;}), "+=");
|
||||
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void prefix_decrement(Module& m)
|
||||
ModulePtr prefix_decrement(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return --lhs;}), "--");
|
||||
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void prefix_increment(Module& m)
|
||||
ModulePtr prefix_increment(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](T &lhs)->T&{return ++lhs;}), "++");
|
||||
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void equal(Module& m)
|
||||
ModulePtr equal(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs==rhs;}), "==");
|
||||
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void greater_than(Module& m)
|
||||
ModulePtr greater_than(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>rhs;}), ">");
|
||||
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void greater_than_equal(Module& m)
|
||||
ModulePtr greater_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>=rhs;}), ">=");
|
||||
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void less_than(Module& m)
|
||||
ModulePtr less_than(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<rhs;}), "<");
|
||||
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void less_than_equal(Module& m)
|
||||
ModulePtr less_than_equal(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<=rhs;}), "<=");
|
||||
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void logical_compliment(Module& m)
|
||||
ModulePtr logical_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return !lhs;}), "!");
|
||||
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void not_equal(Module& m)
|
||||
ModulePtr not_equal(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs!=rhs;}), "!=");
|
||||
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void addition(Module& m)
|
||||
ModulePtr addition(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs+rhs;}), "+");
|
||||
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void unary_plus(Module& m)
|
||||
ModulePtr unary_plus(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return +lhs;}), "+");
|
||||
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void subtraction(Module& m)
|
||||
ModulePtr subtraction(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs-rhs;}), "-");
|
||||
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void unary_minus(Module& m)
|
||||
ModulePtr unary_minus(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return -lhs;}), "-");
|
||||
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_and(Module& m)
|
||||
ModulePtr bitwise_and(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs&rhs;}), "&");
|
||||
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_compliment(Module& m)
|
||||
ModulePtr bitwise_compliment(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs){return ~lhs;}), "~");
|
||||
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_xor(Module& m)
|
||||
ModulePtr bitwise_xor(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs^rhs;}), "^");
|
||||
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void bitwise_or(Module& m)
|
||||
ModulePtr bitwise_or(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs|rhs;}), "|");
|
||||
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void division(Module& m)
|
||||
ModulePtr division(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs/rhs;}), "/");
|
||||
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void left_shift(Module& m)
|
||||
ModulePtr left_shift(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs<<rhs;}), "<<");
|
||||
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void multiplication(Module& m)
|
||||
ModulePtr multiplication(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs*rhs;}), "*");
|
||||
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void remainder(Module& m)
|
||||
ModulePtr remainder(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs%rhs;}), "%");
|
||||
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void right_shift(Module& m)
|
||||
ModulePtr right_shift(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
m.add(chaiscript::fun([](const T &lhs, const T &rhs){return lhs>>rhs;}), ">>");
|
||||
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,32 @@ namespace chaiscript
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Class, typename ... Params >
|
||||
Proxy_Function build_constructor_(Class (*)(Params...))
|
||||
template<typename Class, typename ... Params, size_t ... I >
|
||||
Proxy_Function build_constructor_(Class (*)(Params...), std::index_sequence<I...>)
|
||||
{
|
||||
auto call = dispatch::detail::Constructor<Class, Params...>();
|
||||
return [](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func()
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<std::shared_ptr<Class>>(), user_type<Params>()...})
|
||||
{
|
||||
}
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Params...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return Handle_Return<std::shared_ptr<Class>>::handle(std::make_shared<Class>(boxed_cast<Params>(params[I], &t_conversions)...));
|
||||
}
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>();
|
||||
}();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +63,7 @@ namespace chaiscript
|
||||
Proxy_Function constructor()
|
||||
{
|
||||
T *f = nullptr;
|
||||
return (dispatch::detail::build_constructor_(f));
|
||||
return dispatch::detail::build_constructor_(f, std::make_index_sequence<dispatch::detail::Arity<T>::arity>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,15 +21,34 @@
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "proxy_functions_detail.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "callable_traits.hpp"
|
||||
#include "handle_return.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
struct arity_error;
|
||||
/**
|
||||
* Exception thrown when there is a mismatch in number of
|
||||
* parameters during Proxy_Function execution
|
||||
*/
|
||||
struct arity_error : std::range_error
|
||||
{
|
||||
arity_error(int t_got, int t_expected)
|
||||
: std::range_error("Function dispatch arity mismatch"),
|
||||
got(t_got), expected(t_expected)
|
||||
{
|
||||
}
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
|
||||
virtual ~arity_error() noexcept {}
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
};
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
@@ -181,15 +200,20 @@ namespace chaiscript
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
|
||||
|
||||
if (m_arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (m_arity > 1) {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
|
||||
} else if (static_cast<size_t>(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else if (m_arity > 1) {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
|
||||
} else {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
||||
}
|
||||
} else {
|
||||
return compare_type_to_param(m_types[1], vals[0], t_conversions);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +223,8 @@ namespace chaiscript
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
@@ -299,10 +325,11 @@ namespace chaiscript
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_param_types), t_arity),
|
||||
m_param_types(std::move(t_param_types)),
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -335,6 +362,11 @@ namespace chaiscript
|
||||
return m_parsenode;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const override
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const
|
||||
@@ -374,6 +406,7 @@ namespace chaiscript
|
||||
Param_Types m_param_types;
|
||||
Proxy_Function m_guard;
|
||||
AST_NodePtr m_parsenode;
|
||||
std::string m_description;
|
||||
};
|
||||
|
||||
|
||||
@@ -387,11 +420,13 @@ namespace chaiscript
|
||||
int t_arity=-1,
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
Param_Types t_param_types = Param_Types(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Dynamic_Proxy_Function(
|
||||
t_arity,
|
||||
std::move(t_parsenode),
|
||||
std::move(t_param_types),
|
||||
std::move(t_description),
|
||||
std::move(t_guard)
|
||||
),
|
||||
m_f(std::move(t_f))
|
||||
@@ -490,6 +525,10 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const override
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
|
||||
@@ -534,6 +573,53 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
std::string annotation() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
const auto *t_other = dynamic_cast<const Proxy_Function_Impl_Base *>(&t_func);
|
||||
return
|
||||
t_other != nullptr &&
|
||||
t_other->m_types.size() == m_types.size() &&
|
||||
[this, &t_other](){
|
||||
auto begin1 = std::begin(m_types);
|
||||
const auto end1 = std::end(m_types);
|
||||
auto begin2 = std::begin(t_other->m_types);
|
||||
|
||||
while (begin1 != end1) {
|
||||
if (*begin1 != *begin2) {
|
||||
return false;
|
||||
}
|
||||
if (begin1->is_const() != begin2->is_const()) {
|
||||
return false;
|
||||
}
|
||||
++begin1;
|
||||
++begin2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename ... Param>
|
||||
static bool compare_types_with_cast_impl(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
try {
|
||||
std::vector<Boxed_Value>::size_type i = 0;
|
||||
(void)i; (void)params; (void)t_conversions;
|
||||
// this is ok because the order of evaluation of initializer lists is well defined
|
||||
(void)std::initializer_list<int>{(boxed_cast<Param>(params[i++], &t_conversions), 0)...};
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return static_cast<int>(vals.size()) == get_arity()
|
||||
@@ -544,40 +630,6 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// For any callable object
|
||||
template<typename Func, typename Callable>
|
||||
class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Callable_Impl(Callable f)
|
||||
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||
m_f(std::move(f))
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
Callable m_f;
|
||||
};
|
||||
|
||||
|
||||
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
@@ -589,47 +641,6 @@ namespace chaiscript
|
||||
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
|
||||
};
|
||||
|
||||
template<typename Func>
|
||||
class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
|
||||
: Assignable_Proxy_Function(detail::build_param_type_list(static_cast<Func *>(nullptr))),
|
||||
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr))
|
||||
{
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
{
|
||||
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||
}
|
||||
|
||||
std::function<Func> internal_function() const
|
||||
{
|
||||
return m_f.get();
|
||||
}
|
||||
|
||||
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
|
||||
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f.get(), params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::reference_wrapper<std::function<Func>> m_f;
|
||||
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
|
||||
};
|
||||
|
||||
|
||||
/// Attribute getter Proxy_Function implementation
|
||||
@@ -667,6 +678,11 @@ namespace chaiscript
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
}
|
||||
|
||||
std::string annotation() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
@@ -697,13 +713,13 @@ namespace chaiscript
|
||||
template<typename Type>
|
||||
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
|
||||
@@ -882,7 +898,7 @@ namespace chaiscript
|
||||
for (const auto &func : ordered_funcs )
|
||||
{
|
||||
try {
|
||||
if (func.first == i && (i == 0 || func.second->filter(plist, t_conversions)))
|
||||
if (func.first == i && func.second->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
}
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions_State;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
/**
|
||||
* Exception thrown when there is a mismatch in number of
|
||||
* parameters during Proxy_Function execution
|
||||
*/
|
||||
struct arity_error : std::range_error
|
||||
{
|
||||
arity_error(int t_got, int t_expected)
|
||||
: std::range_error("Function dispatch arity mismatch"),
|
||||
got(t_got), expected(t_expected)
|
||||
{
|
||||
}
|
||||
|
||||
arity_error(const arity_error &) = default;
|
||||
|
||||
virtual ~arity_error() noexcept {}
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
};
|
||||
}
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to return a list of all param types
|
||||
* it contains.
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
||||
{
|
||||
/// \note somehow this is responsible for a large part of the code generation
|
||||
return { user_type<Ret>(), user_type<Params>()... };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
try {
|
||||
std::vector<Boxed_Value>::size_type i = 0;
|
||||
(void)i;
|
||||
(void)params; (void)t_conversions;
|
||||
// this is ok because the order of evaluation of initializer lists is well defined
|
||||
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
|
||||
std::index_sequence<I...>, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
(void)params; (void)t_conversions;
|
||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||
}
|
||||
|
||||
|
||||
/// Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
/// The function attempts to unbox each parameter to the expected type.
|
||||
/// if any unboxing fails the execution of the function fails and
|
||||
/// the bad_boxed_cast is passed up to the caller.
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||
}
|
||||
|
||||
template<typename Callable, typename ... Params>
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "bind_first.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include "function_call.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -35,45 +37,396 @@ namespace chaiscript
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
//
|
||||
//
|
||||
template<typename ... Param, size_t ... I>
|
||||
Proxy_Function assignable_fun(
|
||||
std::reference_wrapper<std::function<void (Param...)>> t_func,
|
||||
std::shared_ptr<std::function<void (Param...)>> t_ptr,
|
||||
std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func, t_ptr](){
|
||||
class Func final : public dispatch::Assignable_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Func(std::reference_wrapper<std::function<void (Param...)>> t_f, std::shared_ptr<std::function<void (Param...)>> t_p)
|
||||
: Assignable_Proxy_Function({user_type<void>(), user_type<Param>()...}),
|
||||
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p))
|
||||
{
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
|
||||
m_f.get() = dispatch::functor<void (Param...)>(t_rhs, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
m_f(boxed_cast<Param>(params.at(I), &t_conversions)...);
|
||||
return dispatch::detail::Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<std::function<void (Param...)>> m_f;
|
||||
std::shared_ptr<std::function<void (Param...)>> m_shared_ptr_holder;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func, t_ptr);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Param, size_t ... I>
|
||||
Proxy_Function assignable_fun(
|
||||
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
|
||||
std::shared_ptr<std::function<Ret (Param...)>> t_ptr,
|
||||
std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func, t_ptr](){
|
||||
class Func final : public dispatch::Assignable_Proxy_Function
|
||||
{
|
||||
public:
|
||||
Func(std::reference_wrapper<std::function<Ret (Param...)>> t_f, std::shared_ptr<std::function<Ret (Param...)>> t_p)
|
||||
: Assignable_Proxy_Function({user_type<Ret>(), user_type<Param>()...}),
|
||||
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p))
|
||||
{
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
|
||||
m_f.get() = dispatch::functor<Ret (Param...)>(t_rhs, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return dispatch::detail::Handle_Return<Ret>::handle(m_f(boxed_cast<Param>(params.at(I), &t_conversions)...));
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<std::function<Ret (Param...)>> m_f;
|
||||
std::shared_ptr<std::function<Ret (Param...)>> m_shared_ptr_holder;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func, t_ptr);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function assignable_fun(
|
||||
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
|
||||
std::shared_ptr<std::function<Ret (Param...)>> t_ptr
|
||||
)
|
||||
{
|
||||
return assignable_fun(std::move(t_func), std::move(t_ptr), std::make_index_sequence<sizeof...(Param)>());
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(const T &t_func, void (*)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(const T &func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
m_f(boxed_cast<Param>(params[I], &t_conversions)...);
|
||||
return dispatch::detail::Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
private:
|
||||
T m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename T, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(const T &t_func, Ret (*)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(const T &func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return dispatch::detail::Handle_Return<Ret>::handle(m_f(boxed_cast<Param>(params.at(I), &t_conversions)...));
|
||||
}
|
||||
|
||||
private:
|
||||
T m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Proxy_Function fun(const T &t)
|
||||
{
|
||||
typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
|
||||
Signature *f = nullptr;
|
||||
return fun(t, f, std::make_index_sequence<dispatch::detail::Arity<Signature>::arity>());
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...))
|
||||
template<typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(void (*t_func)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
(*m_f)(boxed_cast<Param>(params[I], &t_conversions)...);
|
||||
return dispatch::detail::Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(Ret (*t_func)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return dispatch::detail::Handle_Return<Ret>::handle((*m_f)(boxed_cast<Param>(params[I], &t_conversions)...));
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename Class, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(void (Class::*t_func)(Param...) const, std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<const Class &>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<const Class &, Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
const Class &o = static_cast<const Class &>(boxed_cast<const Class &>(params[0], &t_conversions));
|
||||
(o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...);
|
||||
return dispatch::detail::Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) const, std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<const Class &>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<const Class &, Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
const Class &o = static_cast<const Class &>(boxed_cast<const Class &>(params[0], &t_conversions));
|
||||
return dispatch::detail::Handle_Return<Ret>::handle((o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...));
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
|
||||
template<typename Class, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(void (Class::*t_func)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Class &>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Class &, Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
Class &o = static_cast<Class &>(boxed_cast<Class &>(params[0], &t_conversions));
|
||||
(o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...);
|
||||
return dispatch::detail::Handle_Return<void>::handle();
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param, size_t ... I>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...), std::index_sequence<I...>)
|
||||
{
|
||||
return [t_func](){
|
||||
class Func final : public dispatch::Proxy_Function_Impl_Base
|
||||
{
|
||||
public:
|
||||
Func(decltype(t_func) func)
|
||||
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Class &>(), user_type<Param>()...}),
|
||||
m_f(func)
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return compare_types_with_cast_impl<Class &, Param...>(params, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
Class &o = static_cast<Class &>(boxed_cast<Class &>(params[0], &t_conversions));
|
||||
return dispatch::detail::Handle_Return<Ret>::handle((o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...));
|
||||
}
|
||||
|
||||
private:
|
||||
decltype(t_func) m_f;
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
|
||||
}();
|
||||
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
|
||||
{
|
||||
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
|
||||
return fun(t_func, std::make_index_sequence<sizeof...(Param)>());
|
||||
}
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...))
|
||||
{
|
||||
return fun(func, std::make_index_sequence<sizeof...(Param)>());
|
||||
}
|
||||
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...))
|
||||
{
|
||||
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
|
||||
|
||||
return fun(t_func, std::make_index_sequence<sizeof...(Param)>());
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
|
||||
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
|
||||
{
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace chaiscript
|
||||
class Type_Info
|
||||
{
|
||||
public:
|
||||
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
|
||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
constexpr Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
||||
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||
@@ -53,6 +53,11 @@ namespace chaiscript
|
||||
|| *ti.m_type_info == *m_type_info;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const Type_Info &ti) const noexcept
|
||||
{
|
||||
return !(*this == ti);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const std::type_info &ti) const noexcept
|
||||
{
|
||||
return !is_undef() && (*m_type_info) == ti;
|
||||
@@ -121,7 +126,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
@@ -136,9 +143,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> >
|
||||
{
|
||||
// typedef T type;
|
||||
typedef T type;
|
||||
|
||||
static constexpr Type_Info get()
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -156,7 +163,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -169,7 +178,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -182,7 +193,9 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@@ -204,7 +217,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type(const T &/*t*/)
|
||||
Type_Info user_type(const T &/*t*/)
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
@@ -219,7 +232,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type()
|
||||
Type_Info user_type()
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
struct Operators {
|
||||
enum class Opers
|
||||
enum Opers
|
||||
{
|
||||
boolean_flag,
|
||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||
@@ -31,7 +31,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
static const char *to_string(Opers t_oper) {
|
||||
static const char *opers[] = {
|
||||
const char *opers[] = {
|
||||
"",
|
||||
"==", "<", ">", "<=", ">=", "!=",
|
||||
"",
|
||||
@@ -46,80 +46,80 @@ namespace chaiscript
|
||||
"+", "/", "*", "-", "+", "-",
|
||||
""
|
||||
};
|
||||
return opers[static_cast<int>(t_oper)];
|
||||
return opers[t_oper];
|
||||
}
|
||||
|
||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||
{
|
||||
if (t_str == "==")
|
||||
{
|
||||
return Opers::equals;
|
||||
return equals;
|
||||
} else if (t_str == "<") {
|
||||
return Opers::less_than;
|
||||
return less_than;
|
||||
} else if (t_str == ">") {
|
||||
return Opers::greater_than;
|
||||
return greater_than;
|
||||
} else if (t_str == "<=") {
|
||||
return Opers::less_than_equal;
|
||||
return less_than_equal;
|
||||
} else if (t_str == ">=") {
|
||||
return Opers::greater_than_equal;
|
||||
return greater_than_equal;
|
||||
} else if (t_str == "!=") {
|
||||
return Opers::not_equal;
|
||||
return not_equal;
|
||||
} else if (t_str == "=") {
|
||||
return Opers::assign;
|
||||
return assign;
|
||||
} else if (t_str == "++") {
|
||||
return Opers::pre_increment;
|
||||
return pre_increment;
|
||||
} else if (t_str == "--") {
|
||||
return Opers::pre_decrement;
|
||||
return pre_decrement;
|
||||
} else if (t_str == "*=") {
|
||||
return Opers::assign_product;
|
||||
return assign_product;
|
||||
} else if (t_str == "+=") {
|
||||
return Opers::assign_sum;
|
||||
return assign_sum;
|
||||
} else if (t_str == "-=") {
|
||||
return Opers::assign_difference;
|
||||
return assign_difference;
|
||||
} else if (t_str == "&=") {
|
||||
return Opers::assign_bitwise_and;
|
||||
return assign_bitwise_and;
|
||||
} else if (t_str == "|=") {
|
||||
return Opers::assign_bitwise_or;
|
||||
return assign_bitwise_or;
|
||||
} else if (t_str == "<<=") {
|
||||
return Opers::assign_shift_left;
|
||||
return assign_shift_left;
|
||||
} else if (t_str == ">>=") {
|
||||
return Opers::assign_shift_right;
|
||||
return assign_shift_right;
|
||||
} else if (t_str == "%=") {
|
||||
return Opers::assign_remainder;
|
||||
return assign_remainder;
|
||||
} else if (t_str == "^=") {
|
||||
return Opers::assign_bitwise_xor;
|
||||
return assign_bitwise_xor;
|
||||
} else if (t_str == "<<") {
|
||||
return Opers::shift_left;
|
||||
return shift_left;
|
||||
} else if (t_str == ">>") {
|
||||
return Opers::shift_right;
|
||||
return shift_right;
|
||||
} else if (t_str == "%") {
|
||||
return Opers::remainder;
|
||||
return remainder;
|
||||
} else if (t_str == "&") {
|
||||
return Opers::bitwise_and;
|
||||
return bitwise_and;
|
||||
} else if (t_str == "|") {
|
||||
return Opers::bitwise_or;
|
||||
return bitwise_or;
|
||||
} else if (t_str == "^") {
|
||||
return Opers::bitwise_xor;
|
||||
return bitwise_xor;
|
||||
} else if (t_str == "~") {
|
||||
return Opers::bitwise_complement;
|
||||
return bitwise_complement;
|
||||
} else if (t_str == "+") {
|
||||
if (t_is_unary) {
|
||||
return Opers::unary_plus;
|
||||
return unary_plus;
|
||||
} else {
|
||||
return Opers::sum;
|
||||
return sum;
|
||||
}
|
||||
} else if (t_str == "-") {
|
||||
if (t_is_unary) {
|
||||
return Opers::unary_minus;
|
||||
return unary_minus;
|
||||
} else {
|
||||
return Opers::difference;
|
||||
return difference;
|
||||
}
|
||||
} else if (t_str == "/") {
|
||||
return Opers::quotient;
|
||||
return quotient;
|
||||
} else if (t_str == "*") {
|
||||
return Opers::product;
|
||||
return product;
|
||||
} else {
|
||||
return Opers::invalid;
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,26 +32,28 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Types of AST nodes available to the parser and eval
|
||||
enum class AST_Node_Type { Id, Caching_Id, Fun_Call, Arg_List, Equation, Var_Decl,
|
||||
Array_Call, Dot_Access,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Try, Catch, Finally, Method, Attr_Decl,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
|
||||
class AST_Node_Type {
|
||||
public:
|
||||
enum Type { Error, Int, Float, Id, Char, Str, Eol, Fun_Call, Arg_List, Variable, Equation, Var_Decl,
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
|
||||
};
|
||||
};
|
||||
|
||||
enum class Operator_Precidence { Ternary_Cond, Logical_Or, Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, Equality, Comparison, Shift, Addition, Multiplication };
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Helper lookup to get the name of each node type
|
||||
const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
|
||||
static const char * const ast_node_types[] = { "Id", "Caching_Id", "Fun_Call", "Arg_List", "Equation", "Var_Decl",
|
||||
"Array_Call", "Dot_Access",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
|
||||
|
||||
return ast_node_types[static_cast<int>(ast_node_type)];
|
||||
/// Helper lookup to get the name of each node type
|
||||
const char *ast_node_type_to_string(int ast_node_type) {
|
||||
const char *ast_node_types[] = { "Internal Parser Error", "Int", "Float", "Id", "Char", "Str", "Eol", "Fun_Call", "Arg_List", "Variable", "Equation", "Var_Decl",
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,36 +101,6 @@ namespace chaiscript
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
namespace exception
|
||||
{
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
: std::runtime_error(format_error(t_name, t_errors))
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() noexcept = default;
|
||||
|
||||
static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Error loading module '" << t_name << "'\n"
|
||||
<< " The following locations were searched:\n";
|
||||
|
||||
for (const auto &err : t_errors) {
|
||||
ss << " " << err.what() << "\n";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Errors generated during parsing or evaluation
|
||||
struct eval_error : std::runtime_error {
|
||||
@@ -189,12 +161,12 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() noexcept = default;
|
||||
virtual ~eval_error() noexcept {}
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static AST_Node_Type id(const T& t)
|
||||
static int id(const T& t)
|
||||
{
|
||||
return t->identifier;
|
||||
}
|
||||
@@ -462,9 +434,11 @@ namespace chaiscript
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||
public:
|
||||
const AST_Node_Type identifier;
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
std::vector<AST_NodePtr> children;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
const std::string &filename() const {
|
||||
return *location.filename;
|
||||
@@ -478,22 +452,19 @@ namespace chaiscript
|
||||
return location.end;
|
||||
}
|
||||
|
||||
std::string pretty_print() const
|
||||
virtual std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (auto & elem : this->get_children()) {
|
||||
oss << elem->pretty_print() << ' ';
|
||||
for (auto & elem : this->children) {
|
||||
oss << elem->pretty_print();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
virtual std::vector<AST_NodePtr> get_children() const = 0;
|
||||
virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
|
||||
|
||||
|
||||
/// Prints the contents of an AST node, including its children, recursively
|
||||
std::string to_string(const std::string &t_prepend = "") const {
|
||||
@@ -502,12 +473,21 @@ namespace chaiscript
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
|
||||
|
||||
for (auto & elem : this->get_children()) {
|
||||
for (auto & elem : this->children) {
|
||||
oss << elem->to_string(t_prepend + " ");
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const
|
||||
{
|
||||
try {
|
||||
return eval_internal(t_e);
|
||||
} catch (exception::eval_error &ee) {
|
||||
ee.call_stack.push_back(shared_from_this());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_bool_condition(const Boxed_Value &t_bv) {
|
||||
try {
|
||||
@@ -519,47 +499,33 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
virtual ~AST_Node() = default;
|
||||
AST_Node(AST_Node &&) = default;
|
||||
AST_Node &operator=(AST_Node &&) = default;
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
AST_Node& operator=(const AST_Node &) = delete;
|
||||
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
|
||||
{
|
||||
std::replace(children.begin(), children.end(), t_child, t_new_child);
|
||||
}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
protected:
|
||||
AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
|
||||
: identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc))
|
||||
AST_Node(std::string t_ast_node_text, int t_id, Parse_Location t_loc,
|
||||
std::vector<AST_NodePtr> t_children = std::vector<AST_NodePtr>()) :
|
||||
identifier(t_id), text(std::move(t_ast_node_text)),
|
||||
location(std::move(t_loc)),
|
||||
children(std::move(t_children))
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const
|
||||
{
|
||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||
}
|
||||
|
||||
private:
|
||||
// Copy and assignment explicitly unimplemented
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
AST_Node& operator=(const AST_Node &) = delete;
|
||||
};
|
||||
|
||||
namespace parser {
|
||||
class ChaiScript_Parser_Base
|
||||
{
|
||||
public:
|
||||
virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
|
||||
virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0;
|
||||
virtual void *get_tracer_ptr() = 0;
|
||||
virtual ~ChaiScript_Parser_Base() = default;
|
||||
ChaiScript_Parser_Base() = default;
|
||||
ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
|
||||
ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
|
||||
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||
|
||||
template<typename T>
|
||||
T &get_tracer()
|
||||
{
|
||||
// to do type check this somehow?
|
||||
return *static_cast<T*>(get_tracer_ptr());
|
||||
}
|
||||
|
||||
protected:
|
||||
ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
|
||||
};
|
||||
}
|
||||
|
||||
namespace eval
|
||||
{
|
||||
@@ -588,83 +554,77 @@ namespace chaiscript
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Scope_Push_Pop
|
||||
{
|
||||
Scope_Push_Pop(Scope_Push_Pop &&) = default;
|
||||
Scope_Push_Pop& operator=(Scope_Push_Pop &&) = default;
|
||||
Scope_Push_Pop(const Scope_Push_Pop &) = delete;
|
||||
Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete;
|
||||
|
||||
Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_scope(m_ds.stack_holder());
|
||||
m_ds.get()->new_scope(m_ds.get().stack_holder());
|
||||
}
|
||||
|
||||
~Scope_Push_Pop()
|
||||
{
|
||||
m_ds->pop_scope(m_ds.stack_holder());
|
||||
m_ds.get()->pop_scope(m_ds.get().stack_holder());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new function call and pops it on destruction
|
||||
struct Function_Push_Pop
|
||||
{
|
||||
Function_Push_Pop(Function_Push_Pop &&) = default;
|
||||
Function_Push_Pop& operator=(Function_Push_Pop &&) = default;
|
||||
Function_Push_Pop(const Function_Push_Pop &) = delete;
|
||||
Function_Push_Pop& operator=(const Function_Push_Pop &) = delete;
|
||||
|
||||
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
|
||||
}
|
||||
|
||||
~Function_Push_Pop()
|
||||
{
|
||||
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
|
||||
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
|
||||
}
|
||||
|
||||
void save_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
m_ds->save_function_params(t_params);
|
||||
m_ds.get()->save_function_params(t_params);
|
||||
}
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_ds->save_function_params(std::move(t_params));
|
||||
m_ds.get()->save_function_params(std::move(t_params));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
};
|
||||
|
||||
/// Creates a new scope then pops it on destruction
|
||||
struct Stack_Push_Pop
|
||||
{
|
||||
Stack_Push_Pop(Stack_Push_Pop &&) = default;
|
||||
Stack_Push_Pop& operator=(Stack_Push_Pop &&) = default;
|
||||
Stack_Push_Pop(const Stack_Push_Pop &) = delete;
|
||||
Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete;
|
||||
|
||||
Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds->new_stack(m_ds.stack_holder());
|
||||
m_ds.get()->new_stack(m_ds.get().stack_holder());
|
||||
}
|
||||
|
||||
~Stack_Push_Pop()
|
||||
{
|
||||
m_ds->pop_stack(m_ds.stack_holder());
|
||||
m_ds.get()->pop_stack(m_ds.get().stack_holder());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const chaiscript::detail::Dispatch_State &m_ds;
|
||||
std::reference_wrapper<const chaiscript::detail::Dispatch_State> m_ds;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,15 +33,14 @@
|
||||
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#include "chaiscript_windows.hpp"
|
||||
#elif _POSIX_VERSION
|
||||
#include "chaiscript_posix.hpp"
|
||||
#else
|
||||
#include "chaiscript_unknown.hpp"
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -50,9 +49,205 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
load_module_error(const load_module_error &) = default;
|
||||
virtual ~load_module_error() noexcept {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if defined(_POSIX_VERSION) && !defined(__CYGWIN__)
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(const DLModule &); // Explicitly unimplemented copy constructor
|
||||
DLModule &operator=(const DLModule &); // Explicitly unimplemented assignment operator
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p)
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#else
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
typedef LPTSTR StringType;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
0, nullptr ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
|
||||
#else
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
}
|
||||
|
||||
@@ -70,16 +265,19 @@ namespace chaiscript
|
||||
std::vector<std::string> m_module_paths;
|
||||
std::vector<std::string> m_use_paths;
|
||||
|
||||
std::unique_ptr<parser::ChaiScript_Parser_Base> m_parser;
|
||||
|
||||
chaiscript::detail::Dispatch_Engine m_engine;
|
||||
|
||||
/// Evaluates the given string in by parsing it and running the results through the evaluator
|
||||
Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false)
|
||||
{
|
||||
try {
|
||||
const auto p = m_parser->parse(t_input, t_filename);
|
||||
return p->eval(m_engine);
|
||||
parser::ChaiScript_Parser parser;
|
||||
if (parser.parse(t_input, t_filename)) {
|
||||
//parser.show_match_stack();
|
||||
return parser.optimized_ast()->eval(m_engine);
|
||||
} else {
|
||||
return Boxed_Value();
|
||||
}
|
||||
}
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
@@ -88,6 +286,8 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Evaluates the given file and looks in the 'use' paths
|
||||
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths)
|
||||
@@ -125,6 +325,27 @@ namespace chaiscript
|
||||
|
||||
/// Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
m_engine.add_reserved_word("def");
|
||||
m_engine.add_reserved_word("fun");
|
||||
m_engine.add_reserved_word("while");
|
||||
m_engine.add_reserved_word("for");
|
||||
m_engine.add_reserved_word("if");
|
||||
m_engine.add_reserved_word("else");
|
||||
m_engine.add_reserved_word("&&");
|
||||
m_engine.add_reserved_word("||");
|
||||
m_engine.add_reserved_word(",");
|
||||
m_engine.add_reserved_word("auto");
|
||||
m_engine.add_reserved_word("return");
|
||||
m_engine.add_reserved_word("break");
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("class");
|
||||
m_engine.add_reserved_word("attr");
|
||||
m_engine.add_reserved_word("var");
|
||||
m_engine.add_reserved_word("global");
|
||||
m_engine.add_reserved_word("GLOBAL");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
if (t_lib)
|
||||
{
|
||||
add(t_lib);
|
||||
@@ -176,10 +397,16 @@ namespace chaiscript
|
||||
m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval");
|
||||
m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval");
|
||||
m_engine.add(fun(&parse), "parse");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse");
|
||||
m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse");
|
||||
|
||||
m_engine.add(fun(&ChaiScript::version_major), "version_major");
|
||||
m_engine.add(fun(&ChaiScript::version_minor), "version_minor");
|
||||
m_engine.add(fun(&ChaiScript::version_patch), "version_patch");
|
||||
m_engine.add(fun(&ChaiScript::version), "version");
|
||||
m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version");
|
||||
m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name");
|
||||
m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id");
|
||||
m_engine.add(fun(&ChaiScript::debug_build), "debug_build");
|
||||
|
||||
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");
|
||||
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
|
||||
@@ -218,10 +445,7 @@ namespace chaiscript
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
|
||||
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
|
||||
m_engine(*m_parser)
|
||||
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
{
|
||||
@@ -245,9 +469,7 @@ namespace chaiscript
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript( std::vector<std::string> t_modulepaths = std::vector<std::string>(),
|
||||
std::vector<std::string> t_usepaths = std::vector<std::string>())
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)),
|
||||
m_parser(std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer<optimizer::Block, optimizer::Caching_Id, optimizer::Constant_Fold, optimizer::If, optimizer::Return, optimizer::For_Loop>>>()),
|
||||
m_engine(*m_parser)
|
||||
: m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths))
|
||||
{
|
||||
if (m_module_paths.empty())
|
||||
{
|
||||
@@ -294,21 +516,8 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
|
||||
try {
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + Build_Info::version());
|
||||
} catch (const exception::load_module_error &t_err) {
|
||||
std::cout << "An error occured while trying to load the chaiscript standard library.\n"
|
||||
<< "\n"
|
||||
<< "You must either provide a standard library, or compile it in.\n"
|
||||
<< "For an example of compiling the standard library in,\n"
|
||||
<< "see: https://gist.github.com/lefticus/9456197\n"
|
||||
<< "Compiling the stdlib in is the recommended and MOST SUPPORTED method.\n"
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< t_err.what();
|
||||
throw;
|
||||
}
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib-" + version());
|
||||
|
||||
build_eval_system(ModulePtr());
|
||||
}
|
||||
@@ -323,16 +532,65 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false)
|
||||
static AST_NodePtr parse(const std::string &t_input)
|
||||
{
|
||||
const auto ast = m_parser->parse(t_input, "PARSE");
|
||||
if (t_debug_print) {
|
||||
m_parser->debug_print(ast);
|
||||
parser::ChaiScript_Parser parser;
|
||||
if (parser.parse(t_input, "PARSE")) {
|
||||
//parser.show_match_stack();
|
||||
return parser.optimized_ast();
|
||||
} else {
|
||||
throw chaiscript::exception::eval_error("Unknown error while parsing");
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
|
||||
static int version_major()
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
|
||||
static std::string version()
|
||||
{
|
||||
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
|
||||
}
|
||||
|
||||
static std::string compiler_id()
|
||||
{
|
||||
return compiler_name() + '-' + compiler_version();
|
||||
}
|
||||
|
||||
static std::string build_id()
|
||||
{
|
||||
return compiler_id() + (debug_build()?"-Debug":"-Release");
|
||||
}
|
||||
|
||||
static std::string compiler_version()
|
||||
{
|
||||
return chaiscript::compiler_version;
|
||||
}
|
||||
|
||||
static std::string compiler_name()
|
||||
{
|
||||
return chaiscript::compiler_name;
|
||||
}
|
||||
|
||||
static bool debug_build()
|
||||
{
|
||||
return chaiscript::debug_build;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
return m_engine.get_type_name(ti);
|
||||
@@ -547,7 +805,7 @@ namespace chaiscript
|
||||
{
|
||||
std::vector<exception::load_module_error> errors;
|
||||
std::string version_stripped_name = t_module_name;
|
||||
size_t version_pos = version_stripped_name.find("-" + Build_Info::version());
|
||||
size_t version_pos = version_stripped_name.find("-"+version());
|
||||
if (version_pos != std::string::npos)
|
||||
{
|
||||
version_stripped_name.erase(version_pos);
|
||||
@@ -577,7 +835,21 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
throw chaiscript::exception::load_module_error(t_module_name, errors);
|
||||
std::string errstring;
|
||||
|
||||
for (std::vector<exception::load_module_error>::const_iterator itr = errors.begin();
|
||||
itr != errors.end();
|
||||
++itr)
|
||||
{
|
||||
if (!errstring.empty())
|
||||
{
|
||||
errstring += "; ";
|
||||
}
|
||||
|
||||
errstring += itr->what();
|
||||
}
|
||||
|
||||
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
}
|
||||
|
||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||
@@ -614,7 +886,14 @@ namespace chaiscript
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
return eval(t_script, t_handler);
|
||||
try {
|
||||
return do_eval(t_script);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Evaluates a string and returns a typesafe result.
|
||||
@@ -633,14 +912,21 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
return m_engine.boxed_cast<T>(eval(t_input, t_handler, t_filename));
|
||||
try {
|
||||
return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief casts an object while applying any Dynamic_Conversion available
|
||||
template<typename Type>
|
||||
decltype(auto) boxed_cast(const Boxed_Value &bv) const
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
return(m_engine.boxed_cast<Type>(bv));
|
||||
return m_engine.boxed_cast<Type>(bv);
|
||||
}
|
||||
|
||||
|
||||
@@ -672,7 +958,14 @@ namespace chaiscript
|
||||
/// \return result of the script execution
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
return eval(load_file(t_filename), t_handler, t_filename);
|
||||
try {
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
|
||||
@@ -685,7 +978,14 @@ namespace chaiscript
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
|
||||
try {
|
||||
return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv, m_engine);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,284 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
|
||||
#define CHAISCRIPT_OPTIMIZER_HPP_
|
||||
|
||||
#include "chaiscript_eval.hpp"
|
||||
|
||||
|
||||
namespace chaiscript {
|
||||
namespace optimizer {
|
||||
|
||||
template<typename ... T>
|
||||
struct Optimizer : T...
|
||||
{
|
||||
Optimizer() = default;
|
||||
Optimizer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Tracer>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||
(void)std::initializer_list<int>{ (p = T::optimize(p), 0)... };
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
auto child_at(const eval::AST_Node_Impl_Ptr<T> &node, const size_t offset) {
|
||||
if (node->identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
|
||||
} else {
|
||||
return node->children[offset];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto child_count(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children.size();
|
||||
} else {
|
||||
return node->children.size();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Callable>
|
||||
auto make_compiled_node(const eval::AST_Node_Impl_Ptr<T> &original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
|
||||
{
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(original_node, std::move(children), std::move(callable));
|
||||
}
|
||||
|
||||
|
||||
struct Return {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &p)
|
||||
{
|
||||
if (p->identifier == AST_Node_Type::Def
|
||||
&& !p->children.empty())
|
||||
{
|
||||
auto &last_child = p->children.back();
|
||||
if (last_child->identifier == AST_Node_Type::Block) {
|
||||
auto &block_last_child = last_child->children.back();
|
||||
if (block_last_child->identifier == AST_Node_Type::Return) {
|
||||
if (block_last_child->children.size() == 1) {
|
||||
last_child->children.back() = block_last_child->children[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool contains_var_decl_in_scope(const T &node)
|
||||
{
|
||||
if (node->identifier == AST_Node_Type::Var_Decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto num = child_count(node);
|
||||
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
const auto &child = child_at(node, i);
|
||||
if (child->identifier != AST_Node_Type::Block
|
||||
&& contains_var_decl_in_scope(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Block {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Block
|
||||
&& node->children.size() == 1
|
||||
&& !contains_var_decl_in_scope(node))
|
||||
{
|
||||
return node->children[0];
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct If {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::If
|
||||
&& node->children.size() >= 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
const auto condition = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||
if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
|
||||
if (boxed_cast<bool>(condition)) {
|
||||
return node->children[1];
|
||||
} else if (node->children.size() == 3) {
|
||||
return node->children[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
struct Caching_Id {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
if (node->identifier == AST_Node_Type::Id)
|
||||
{
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Caching_Id_AST_Node<T>>(node->text, node->location);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Constant_Fold {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &node) {
|
||||
|
||||
if (node->identifier == AST_Node_Type::Binary
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Constant
|
||||
&& node->children[1]->identifier == AST_Node_Type::Constant)
|
||||
{
|
||||
try {
|
||||
const auto &oper = node->text;
|
||||
const auto parsed = Operators::to_operator(oper);
|
||||
if (parsed != Operators::Opers::invalid) {
|
||||
const auto lhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[0])->m_value;
|
||||
const auto rhs = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1])->m_value;
|
||||
if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
|
||||
const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
|
||||
const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &) {
|
||||
//failure to fold, that's OK
|
||||
}
|
||||
} else if (node->identifier == AST_Node_Type::Fun_Call
|
||||
&& node->children.size() == 2
|
||||
&& node->children[0]->identifier == AST_Node_Type::Id
|
||||
&& node->children[1]->identifier == AST_Node_Type::Arg_List
|
||||
&& node->children[1]->children.size() == 1
|
||||
&& node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
|
||||
|
||||
const auto arg = std::dynamic_pointer_cast<eval::Constant_AST_Node<T>>(node->children[1]->children[0])->m_value;
|
||||
if (arg.get_type_info().is_arithmetic()) {
|
||||
const auto &fun_name = node->children[0]->text;
|
||||
|
||||
const auto make_constant = [&node, &fun_name](auto val){
|
||||
const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
|
||||
return chaiscript::make_shared<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(val));
|
||||
};
|
||||
|
||||
if (fun_name == "double") {
|
||||
return make_constant(Boxed_Number(arg).get_as<double>());
|
||||
} else if (fun_name == "int") {
|
||||
return make_constant(Boxed_Number(arg).get_as<int>());
|
||||
} else if (fun_name == "float") {
|
||||
return make_constant(Boxed_Number(arg).get_as<float>());
|
||||
} else if (fun_name == "long") {
|
||||
return make_constant(Boxed_Number(arg).get_as<long>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
struct For_Loop {
|
||||
template<typename T>
|
||||
auto optimize(const eval::AST_Node_Impl_Ptr<T> &for_node) {
|
||||
|
||||
if (for_node->identifier != AST_Node_Type::For) {
|
||||
return for_node;
|
||||
}
|
||||
|
||||
const auto eq_node = child_at(for_node, 0);
|
||||
const auto binary_node = child_at(for_node, 1);
|
||||
const auto prefix_node = child_at(for_node, 2);
|
||||
|
||||
if (eq_node->identifier == AST_Node_Type::Equation
|
||||
&& child_count(eq_node) == 2
|
||||
&& child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl
|
||||
&& child_at(eq_node, 1)->identifier == AST_Node_Type::Constant
|
||||
&& binary_node->identifier == AST_Node_Type::Binary
|
||||
&& binary_node->text == "<"
|
||||
&& child_count(binary_node) == 2
|
||||
&& child_at(binary_node, 0)->identifier == AST_Node_Type::Id
|
||||
&& child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text
|
||||
&& child_at(binary_node, 1)->identifier == AST_Node_Type::Constant
|
||||
&& prefix_node->identifier == AST_Node_Type::Prefix
|
||||
&& prefix_node->text == "++"
|
||||
&& child_count(prefix_node) == 1
|
||||
&& child_at(prefix_node, 0)->identifier == AST_Node_Type::Id
|
||||
&& child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text)
|
||||
{
|
||||
const Boxed_Value &begin = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(eq_node, 1))->m_value;
|
||||
const Boxed_Value &end = std::dynamic_pointer_cast<const eval::Constant_AST_Node<T>>(child_at(binary_node, 1))->m_value;
|
||||
const std::string &id = child_at(prefix_node, 0)->text;
|
||||
|
||||
if (begin.get_type_info().bare_equal(user_type<int>())
|
||||
&& end.get_type_info().bare_equal(user_type<int>())) {
|
||||
|
||||
const auto start_int = boxed_cast<int>(begin);
|
||||
const auto end_int = boxed_cast<int>(end);
|
||||
|
||||
const auto body = child_at(for_node, 3);
|
||||
|
||||
return make_compiled_node(for_node, {body},
|
||||
[id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
|
||||
assert(children.size() == 1);
|
||||
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
|
||||
|
||||
int i = start_int;
|
||||
t_ss.add_object(id, var(&i));
|
||||
|
||||
try {
|
||||
for (; i < end_int; ++i) {
|
||||
try {
|
||||
// Body of Loop
|
||||
children[0]->eval(t_ss);
|
||||
} catch (eval::detail::Continue_Loop &) {
|
||||
// we got a continue exception, which means all of the remaining
|
||||
// loop implementation is skipped and we just need to continue to
|
||||
// the next iteration step
|
||||
}
|
||||
}
|
||||
} catch (eval::detail::Break_Loop &) {
|
||||
// loop broken
|
||||
}
|
||||
|
||||
return void_var();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return for_node;
|
||||
}
|
||||
} else {
|
||||
return for_node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,81 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_POSIX_HPP_
|
||||
#define CHAISCRIPT_POSIX_HPP_
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(dlopen(t_filename.c_str(), RTLD_NOW))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(DLModule &&) = default;
|
||||
DLModule &operator=(DLModule &&) = default;
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
dlclose(m_data);
|
||||
}
|
||||
|
||||
void *m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(cast_symbol(dlsym(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p)
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_TRACER_HPP_
|
||||
#define CHAISCRIPT_TRACER_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
namespace eval {
|
||||
|
||||
struct Noop_Tracer
|
||||
{
|
||||
template<typename T>
|
||||
static void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... T>
|
||||
struct Tracer : T...
|
||||
{
|
||||
Tracer() = default;
|
||||
Tracer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
}
|
||||
|
||||
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
(void)std::initializer_list<int>{ (T::trace(ds, node), 0)... };
|
||||
}
|
||||
|
||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UNKNOWN_HPP_
|
||||
#define CHAISCRIPT_UNKNOWN_HPP_
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_WINDOWS_HPP_
|
||||
#define CHAISCRIPT_WINDOWS_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct Loadable_Module
|
||||
{
|
||||
template<typename T>
|
||||
static std::wstring to_wstring(const T &t_str)
|
||||
{
|
||||
return std::wstring(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string to_string(const T &t_str)
|
||||
{
|
||||
return std::string(t_str.begin(), t_str.end());
|
||||
}
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
template<typename T>
|
||||
static std::wstring to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_wstring(t_str);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
static std::string to_proper_string(const T &t_str)
|
||||
{
|
||||
return to_string(t_str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string get_error_message(DWORD t_err)
|
||||
{
|
||||
typedef LPTSTR StringType;
|
||||
|
||||
#if defined(_UNICODE) || defined(UNICODE)
|
||||
std::wstring retval = L"Unknown Error";
|
||||
#else
|
||||
std::string retval = "Unknown Error";
|
||||
#endif
|
||||
StringType lpMsgBuf = nullptr;
|
||||
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
t_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<StringType>(&lpMsgBuf),
|
||||
0, nullptr ) != 0 && lpMsgBuf)
|
||||
{
|
||||
retval = lpMsgBuf;
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
|
||||
return to_string(retval);
|
||||
}
|
||||
|
||||
struct DLModule
|
||||
{
|
||||
DLModule(const std::string &t_filename)
|
||||
: m_data(LoadLibrary(to_proper_string(t_filename).c_str()))
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
DLModule(DLModule &&) = default;
|
||||
DLModule &operator=(DLModule &&) = default;
|
||||
DLModule(const DLModule &) = delete;
|
||||
DLModule &operator=(const DLModule &) = delete;
|
||||
|
||||
~DLModule()
|
||||
{
|
||||
FreeLibrary(m_data);
|
||||
}
|
||||
|
||||
HMODULE m_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct DLSym
|
||||
{
|
||||
DLSym(DLModule &t_mod, const std::string &t_symbol)
|
||||
: m_symbol(reinterpret_cast<T>(GetProcAddress(t_mod.m_data, t_symbol.c_str())))
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(get_error_message(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
Loadable_Module(const std::string &t_module_name, const std::string &t_filename)
|
||||
: m_dlmodule(t_filename), m_func(m_dlmodule, "create_chaiscript_module_" + t_module_name),
|
||||
m_moduleptr(m_func.m_symbol())
|
||||
{
|
||||
}
|
||||
|
||||
DLModule m_dlmodule;
|
||||
DLSym<Create_Module_Func> m_func;
|
||||
ModulePtr m_moduleptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
|
||||
static Module& library(Module& m)
|
||||
static ModulePtr library(ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
|
||||
m.add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||
m.add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||
m->add(chaiscript::fun([](const std::string &t_str) { return from_json(t_str); }), "from_json");
|
||||
m->add(chaiscript::fun(&json_wrap::to_json), "to_json");
|
||||
|
||||
return m;
|
||||
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../language/chaiscript_common.hpp"
|
||||
#include "../dispatchkit/register_function.hpp"
|
||||
#include "../chaiscript.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/type_info.hpp"
|
||||
#include "../dispatchkit/operators.hpp"
|
||||
|
||||
|
||||
@@ -77,9 +78,10 @@ namespace chaiscript
|
||||
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
||||
|
||||
using namespace chaiscript::bootstrap::operators;
|
||||
equal<Enum>(t_module);
|
||||
not_equal<Enum>(t_module);
|
||||
assign<Enum>(t_module);
|
||||
t_module.add([](){
|
||||
// add some comparison and assignment operators
|
||||
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
|
||||
}());
|
||||
|
||||
t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "==");
|
||||
t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "==");
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
auto module = std::make_shared<chaiscript::Module>();
|
||||
chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List", *module);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector", *module);
|
||||
|
||||
auto module = chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
module->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector"));
|
||||
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
||||
return module;
|
||||
}
|
||||
|
||||
@@ -189,9 +189,9 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
|
||||
|
||||
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
|
||||
chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5", *m);
|
||||
chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5", *m);
|
||||
chaiscript::bootstrap::array<int[5]>("IntArray_5", *m);
|
||||
m->add(chaiscript::bootstrap::array<int[2][3][5]>("IntArray_2_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[3][5]>("IntArray_3_5"));
|
||||
m->add(chaiscript::bootstrap::array<int[5]>("IntArray_5"));
|
||||
|
||||
// member that is a function
|
||||
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
assert_equal(`==`, `==`);
|
||||
assert_not_equal(`==`, `<`);
|
||||
assert_equal(`<`.get_arity(), 2);
|
||||
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
|
||||
assert_equal(get_arity.get_contained_functions().size(), 0);
|
||||
assert_equal(get_arity.get_arity(), 1);
|
||||
assert_equal(get_arity.get_param_types().size(), 2);
|
||||
|
||||
@@ -10,6 +10,7 @@ def test_function(a)
|
||||
|
||||
// test_function tests
|
||||
assert_equal(test_function.get_arity(), 1);
|
||||
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
|
||||
assert_equal(test_function.get_contained_functions().size(), 0);
|
||||
assert_equal(test_function.get_param_types().size(), 2);
|
||||
|
||||
|
||||
36
unittests/3.x/reflection_test.chai
Normal file
36
unittests/3.x/reflection_test.chai
Normal file
@@ -0,0 +1,36 @@
|
||||
var parser := ChaiScript_Parser()
|
||||
var parse_success = parser.parse("3 + 4", "INPUT")
|
||||
var a := parser.ast()
|
||||
|
||||
assert_equal(eval(a), 7)
|
||||
|
||||
var childs := a.children.front().children
|
||||
var node := childs[0]
|
||||
|
||||
var parser2 := ChaiScript_Parser()
|
||||
parser2.parse("9", "INPUT")
|
||||
|
||||
|
||||
a.children.front().replace_child(childs[0], parser2.ast())
|
||||
|
||||
assert_equal(eval(a), 13)
|
||||
assert_equal(node.filename, "INPUT")
|
||||
|
||||
|
||||
|
||||
def my_fun()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
assert_equal(true, my_fun.has_parse_tree());
|
||||
assert_equal(false, `+`.has_parse_tree());
|
||||
|
||||
assert_throws("Function does not have a parse tree", fun() { `+`.get_parse_tree(); } );
|
||||
|
||||
var parsetree := my_fun.get_parse_tree();
|
||||
|
||||
assert_equal(1, eval(parsetree));
|
||||
|
||||
print(parsetree.text());
|
||||
@@ -1,6 +1,7 @@
|
||||
assert_equal(`==`, `==`);
|
||||
assert_not_equal(`==`, `<`);
|
||||
assert_equal(`<`.get_arity(), 2);
|
||||
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
|
||||
assert_equal(get_arity.get_contained_functions().size(), 0);
|
||||
assert_equal(get_arity.get_arity(), 1);
|
||||
assert_equal(get_arity.get_param_types().size(), 2);
|
||||
|
||||
@@ -10,6 +10,7 @@ def test_function(a)
|
||||
|
||||
// test_function tests
|
||||
assert_equal(test_function.get_arity(), 1);
|
||||
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
|
||||
assert_equal(test_function.get_contained_functions().size(), 0);
|
||||
assert_equal(test_function.get_param_types().size(), 2);
|
||||
|
||||
|
||||
@@ -16,8 +16,3 @@ def f() {
|
||||
|
||||
f();
|
||||
|
||||
|
||||
global &h = v;
|
||||
assert_true(h == v)
|
||||
v = 3;
|
||||
assert_true(h == 3)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
load_module("stl_extra");
|
||||
|
||||
auto list = List();
|
||||
|
||||
list.resize(2);
|
||||
assert_equal(list.size(), 2);
|
||||
|
||||
list.resize(6, "AAA");
|
||||
assert_equal(list.back(), "AAA");
|
||||
|
||||
list.resize(0);
|
||||
assert_equal(list.size(), 0);
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
auto a = parse("3 + 4")
|
||||
auto& parser = ChaiScript_Parser()
|
||||
auto parse_success = parser.parse("3 + 4", "INPUT")
|
||||
auto& a = parser.ast()
|
||||
|
||||
assert_equal(eval(a), 7)
|
||||
|
||||
assert_equal(1, a.children.size());
|
||||
assert_equal("3 + 4", a.children[0].text());
|
||||
auto& childs = a.children.front().children
|
||||
auto& node = childs[0]
|
||||
|
||||
auto& parser2 = ChaiScript_Parser()
|
||||
parser2.parse("9", "INPUT")
|
||||
|
||||
|
||||
a.children.front().replace_child(childs[0], parser2.ast())
|
||||
|
||||
assert_equal(eval(a), 13)
|
||||
assert_equal(node.filename, "INPUT")
|
||||
|
||||
|
||||
|
||||
def my_fun()
|
||||
{
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
load_module("stl_extra");
|
||||
|
||||
auto uint16v = u16vector();
|
||||
|
||||
uint16v.reserve(5);
|
||||
assert_true(uint16v.capacity() >= 5);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
load_module("stl_extra");
|
||||
|
||||
auto uint16v = u16vector();
|
||||
|
||||
uint16v.resize(2);
|
||||
assert_equal(uint16v.size(), 2);
|
||||
|
||||
uint16v.resize(6, 3);
|
||||
assert_equal(uint16v[5], 3);
|
||||
|
||||
uint16v.resize(0);
|
||||
assert_equal(uint16v.size(), 0);
|
||||
|
||||
Reference in New Issue
Block a user