Compare commits

..

1 Commits

Author SHA1 Message Date
Jason Turner
41c1c490c8 Add support for *& return types 2016-04-29 08:31:59 -06:00
48 changed files with 1962 additions and 1774 deletions

View File

@@ -1,12 +1,12 @@
compilers:
- name: "clang"
version: "3.6"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.6"
version: "3.5"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "clang"
@@ -19,28 +19,17 @@ compilers:
version: "3.6"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
- name: "clang"
version: "3.7"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "clang"
build_tag: "LibC++"
version: "3.7"
skip_packaging: true
cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
- name: "gcc"
version: "4.9"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.9"
skip_packaging: true
version: "4.8"
build_tag: "NoThreads"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF
collect_performance_results: true
- name: "gcc"
version: "5"
version: "4.8"
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true
- name: "gcc"
version: "4.6"
skip_packaging: true
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON
collect_performance_results: true

View File

@@ -10,6 +10,13 @@ compilers:
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
compiler_extra_flags: /analyze
skip_packaging: true
- name: Visual Studio
version: 12
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 12
architecture: Win64
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
- name: Visual Studio
version: 14
build_type: Debug
@@ -18,4 +25,3 @@ compilers:
compiler_extra_flags: /analyze
skip_packaging: true

View File

@@ -3,8 +3,8 @@ compiler:
- gcc
env:
matrix:
- GCC_VER="4.9"
- GCC_VER="5"
- GCC_VER="4.6"
- GCC_VER="4.8"
global:
- secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU=
@@ -13,7 +13,7 @@ env:
before_install:
- export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER"
- if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi
- if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi
- if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi
- sudo pip install cpp-coveralls
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y

View File

@@ -101,9 +101,9 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
set(CPACK_PACKAGE_VERSION_MAJOR 6)
set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_PACKAGE_VERSION_MAJOR 5)
set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_PATCH 2)
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
@@ -148,13 +148,13 @@ endif()
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_LESS 4.9)
set(CPP11_FLAG "-std=c++1y")
if(GCC_VERSION VERSION_LESS 4.8)
set(CPP11_FLAG "-std=c++0x")
else()
set(CPP11_FLAG "-std=c++14")
set(CPP11_FLAG "-std=c++11")
endif()
else()
set(CPP11_FLAG "-std=c++14")
set(CPP11_FLAG "-std=c++11")
endif()
if(MSVC)
@@ -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/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/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.chai 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)
@@ -274,9 +274,6 @@ endif()
if(BUILD_MODULES)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
add_library(stl_extra MODULE src/stl_extra.cpp)
target_link_libraries(stl_extra ${LIBS})
@@ -462,6 +459,9 @@ if(BUILD_TESTING)
target_link_libraries(multifile_test ${LIBS})
add_test(NAME MultiFile_Test COMMAND multifile_test)
add_library(test_module MODULE src/test_module.cpp)
target_link_libraries(test_module ${LIBS})
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
endif()
endif()

View File

@@ -1,4 +1,4 @@
version: 5.8.x.{build}
version: 5.7.2.{build}
os: Visual Studio 2015
environment:
matrix:
@@ -14,9 +14,3 @@ build_script:
cmake --build . --config Debug
test_script:
- cmd: ctest -C Debug
notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/9ff725a985b5679d1d5d
on_build_success: true
on_build_failure: true
on_build_status_changed: false

View File

@@ -1,61 +0,0 @@
# My dict
for="for"
while="while"
def="def"
fun="fun"
if="if"
else="else"
and="&&"
or="||"
auto="auto"
var="var"
begin_block="{"
end_block="}"
empty_vec="[]"
string="string"
vector="Vector"
map="Map"
return="return"
break="break"
true="true"
false="false"
class="class"
attr="attr"
var="var"
global="global"
empty_lambda=" fun(){} "
empty_fun=" def empty_fun() {} "
continue="continue"
float=" 1.1f "
double=" 2.2 "
long_double=" 2.2ll "
unsigned=" 3u "
unsigned_long=" 4ul "
unsigned_long_long=" 4ull "
long_long=" 5ll "
attr="attr"
reference_del="auto &"
int8=" int8_t(1) "
int16=" int16_t(2) "
int32=" int32_t(3) "
int64=" int64_t(4) "
uint8=" uint8_t(1) "
uint16=" uint16_t(2) "
uint32=" uint32_t(3) "
uint64=" uint64_t(4) "
int8t="int8_t"
int16t="int16_t"
int32t="int32_t"
int64t="int64_t"
uint8t="uint8_t"
uint16t="uint16_t"
uint32t="uint32_t"
uint64t="uint64_t"

View File

@@ -1,17 +0,0 @@
Command line used to find this crash:
../../Downloads/afl-1.80b/afl-fuzz -i- -o findings -x chaiscript.dict -- ../a.out unit_test.inc @@
If you can't reproduce a bug outside of afl-fuzz, be sure to set the same
memory limit. The limit used for this fuzzing session was 50.0 MB.
Need a tool to minimize test cases before investigating the crashes or sending
them to a vendor? Check out the afl-tmin that comes with the fuzzer!
Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop
me a mail at <lcamtuf@coredump.cx> once the issues are fixed - I'd love to
add your finds to the gallery at:
http://lcamtuf.coredump.cx/afl/
Thanks :-)

View File

@@ -1,5 +0,0 @@
def greet {
return("hello")
}
fun(){ "world" }

View File

@@ -12,10 +12,17 @@
#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER)
#define CHAISCRIPT_MSVC _MSC_VER
#define CHAISCRIPT_HAS_DECLSPEC
#if _MSC_VER <= 1800
#define CHAISCRIPT_MSVC_12
#endif
#else
#define CHAISCRIPT_COMPILER_VERSION __VERSION__
#endif
#ifndef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_HAS_MAGIC_STATICS
#endif
#include <vector>
#if defined( _LIBCPP_VERSION )
@@ -44,15 +51,26 @@
#endif
#endif
#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
#if (defined(CHAISCRIPT_MSVC) && !defined(CHAISCRIPT_MSVC_12)) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
/// Currently only g++>=4.8 supports this natively
/// \todo Make this support other compilers when possible
#define CHAISCRIPT_HAS_THREAD_LOCAL
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
#define CHAISCRIPT_GCC_4_6
#endif
#if defined(__llvm__)
#define CHAISCRIPT_CLANG
#endif
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
#define CHAISCRIPT_OVERRIDE override
#else
#define CHAISCRIPT_OVERRIDE
#endif
#ifdef CHAISCRIPT_HAS_DECLSPEC
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
@@ -60,6 +78,14 @@
#define CHAISCRIPT_MODULE_EXPORT extern "C"
#endif
#ifdef CHAISCRIPT_MSVC_12
#define CHAISCRIPT_NOEXCEPT throw()
#define CHAISCRIPT_CONSTEXPR
#else
#define CHAISCRIPT_NOEXCEPT noexcept
#define CHAISCRIPT_CONSTEXPR constexpr
#endif
#ifdef _DEBUG
#define CHAISCRIPT_DEBUG true
#else
@@ -71,9 +97,9 @@
#include <cmath>
namespace chaiscript {
static const int version_major = 6;
static const int version_minor = 0;
static const int version_patch = 0;
static const int version_major = 5;
static const int version_minor = 8;
static const int version_patch = 2;
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;

View File

@@ -18,7 +18,7 @@
#include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.hpp"
#include "language/chaiscript_prelude.chai"
#include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS

View File

@@ -42,16 +42,28 @@ namespace chaiscript
#ifndef CHAISCRIPT_NO_THREADS
template<typename T>
using unique_lock = std::unique_lock<T>;
class unique_lock : public std::unique_lock<T>
{
public:
explicit unique_lock(T &t) : std::unique_lock<T>(t) {}
};
template<typename T>
using shared_lock = std::unique_lock<T>;
class shared_lock : public std::unique_lock<T>
{
public:
explicit shared_lock(T &t) : std::unique_lock<T>(t) {}
void unlock() {}
};
template<typename T>
using lock_guard = std::lock_guard<T>;
class lock_guard : public std::lock_guard<T>
{
public:
explicit lock_guard(T &t) : std::lock_guard<T>(t) {}
};
using shared_mutex = std::mutex;
class shared_mutex : public std::mutex { };
using std::mutex;

View File

@@ -21,17 +21,17 @@ namespace chaiscript {
class bad_any_cast : public std::bad_cast
{
public:
bad_any_cast() noexcept
bad_any_cast() CHAISCRIPT_NOEXCEPT
: m_what("bad any cast")
{
}
bad_any_cast(const bad_any_cast &) = default;
~bad_any_cast() noexcept override = default;
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occurred
const char * what() const noexcept override
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
}
@@ -53,10 +53,9 @@ namespace chaiscript {
Data &operator=(const Data &) = delete;
virtual ~Data() = default;
virtual ~Data() {}
virtual void *data() = 0;
const std::type_info &type() const
{
return m_type;
@@ -75,12 +74,14 @@ namespace chaiscript {
{
}
virtual void *data() override
virtual ~Data_Impl() {}
virtual void *data() CHAISCRIPT_OVERRIDE
{
return &m_data;
}
std::unique_ptr<Data> clone() const override
std::unique_ptr<Data> clone() const CHAISCRIPT_OVERRIDE
{
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
}
@@ -95,8 +96,6 @@ namespace chaiscript {
public:
// construct/copy/destruct
Any() = default;
Any(Any &&) = default;
Any &operator=(Any &&t_any) = default;
Any(const Any &t_any)
{
@@ -108,6 +107,10 @@ namespace chaiscript {
}
}
#if !defined(_MSC_VER) || _MSC_VER != 1800
Any(Any &&) = default;
Any &operator=(Any &&t_any) = default;
#endif
template<typename ValueType,
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
@@ -136,6 +139,10 @@ namespace chaiscript {
}
~Any()
{
}
// modifiers
Any & swap(Any &t_other)
{

View File

@@ -30,7 +30,7 @@ namespace chaiscript
{
public:
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
std::string t_what) noexcept
std::string t_what) CHAISCRIPT_NOEXCEPT
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
{
}
@@ -40,16 +40,16 @@ namespace chaiscript
{
}
explicit bad_boxed_cast(std::string t_what) noexcept
explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT
: to(nullptr), m_what(std::move(t_what))
{
}
bad_boxed_cast(const bad_boxed_cast &) = default;
virtual ~bad_boxed_cast() noexcept = default;
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
/// \brief Description of what error occurred
virtual const char * what() const noexcept override
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
{
return m_what.c_str();
}

View File

@@ -28,6 +28,7 @@
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"
@@ -441,7 +442,6 @@ namespace chaiscript
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");
@@ -452,42 +452,13 @@ namespace chaiscript
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""(
def Dynamic_Object::clone() {
auto &new_o = Dynamic_Object(this.get_type_name());
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
new_o;
}
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
}
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
if (rhs_attrs.size() != lhs_attrs.size()) {
true;
} else {
return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
}
}
def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
if (rhs_attrs.size() != lhs_attrs.size()) {
false;
} else {
return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
}
}
)chaiscript");
)"");
m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard");

View File

@@ -82,19 +82,21 @@ namespace chaiscript
if (t_conversions && (*t_conversions)->convertable_type<Type>())
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// 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);
} catch (...) {
try {
// try going the other way
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
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));
}
}
} else {
// If it's not convertable, just throw the error, don't waste the time on the
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}

View File

@@ -30,7 +30,7 @@ namespace chaiscript
{
arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {}
arithmetic_error(const arithmetic_error &) = default;
virtual ~arithmetic_error() noexcept = default;
virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {}
};
}
}
@@ -91,7 +91,7 @@ namespace chaiscript
{
}
static constexpr Common_Types get_common_type(size_t t_size, bool t_signed)
static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed)
{
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
:(t_size == 1)?(Common_Types::t_uint8)
@@ -509,8 +509,11 @@ namespace chaiscript
}
Boxed_Number(const Boxed_Number &) = default;
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Number(Boxed_Number &&) = default;
Boxed_Number& operator=(Boxed_Number &&) = default;
#endif
template<typename T> explicit Boxed_Number(T t)
: bv(Boxed_Value(t))

View File

@@ -62,8 +62,10 @@ namespace chaiscript
Data(const Data &) = delete;
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
Data(Data &&) = default;
Data &operator=(Data &&rhs) = default;
#endif
Type_Info m_type_info;
@@ -187,8 +189,11 @@ namespace chaiscript
{
}
#if !defined(_MSC_VER) || _MSC_VER != 1800
Boxed_Value(Boxed_Value&&) = default;
Boxed_Value& operator=(Boxed_Value&&) = default;
#endif
Boxed_Value(const Boxed_Value&) = default;
Boxed_Value& operator=(const Boxed_Value&) = default;
@@ -205,23 +210,23 @@ namespace chaiscript
return *this;
}
const Type_Info &get_type_info() const noexcept
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info;
}
/// return true if the object is uninitialized
bool is_undef() const noexcept
bool is_undef() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.is_undef();
}
bool is_const() const noexcept
bool is_const() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.is_const();
}
bool is_type(const Type_Info &ti) const noexcept
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_data->m_type_info.bare_equal(ti);
}
@@ -270,42 +275,42 @@ namespace chaiscript
return Sentinel<T>(ptr, *(m_data.get()));
}
bool is_null() const noexcept
bool is_null() const CHAISCRIPT_NOEXCEPT
{
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
}
const chaiscript::detail::Any & get() const noexcept
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_obj;
}
bool is_ref() const noexcept
bool is_ref() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_is_ref;
}
bool is_return_value() const noexcept
bool is_return_value() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_return_value;
}
void reset_return_value() const noexcept
void reset_return_value() const CHAISCRIPT_NOEXCEPT
{
m_data->m_return_value = false;
}
bool is_pointer() const noexcept
bool is_pointer() const CHAISCRIPT_NOEXCEPT
{
return !is_ref();
}
void *get_ptr() const noexcept
void *get_ptr() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_data_ptr;
}
const void *get_const_ptr() const noexcept
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_const_data_ptr;
}
@@ -345,7 +350,7 @@ namespace chaiscript
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
{
return l.get_type_info() == r.get_type_info();
}
@@ -455,14 +460,10 @@ namespace chaiscript
return detail::const_var_impl(t);
}
inline Boxed_Value void_var() {
static const auto v = Boxed_Value(Boxed_Value::Void_Type());
return v;
}
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
inline Boxed_Value const_var(bool b) {
static const auto t = detail::const_var_impl(true);
static const auto f = detail::const_var_impl(false);
static auto t = detail::const_var_impl(true);
static auto f = detail::const_var_impl(false);
if (b) {
return t;
@@ -470,6 +471,7 @@ namespace chaiscript
return f;
}
}
#endif
}

View File

@@ -13,6 +13,53 @@ 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

View File

@@ -56,14 +56,14 @@ namespace chaiscript
class reserved_word_error : public std::runtime_error
{
public:
explicit reserved_word_error(const std::string &t_word) noexcept
reserved_word_error(const std::string &t_word) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
{
}
reserved_word_error(const reserved_word_error &) = default;
virtual ~reserved_word_error() noexcept = default;
virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {}
std::string word() const
{
@@ -78,14 +78,14 @@ namespace chaiscript
class illegal_name_error : public std::runtime_error
{
public:
explicit illegal_name_error(const std::string &t_name) noexcept
illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
{
}
illegal_name_error(const illegal_name_error &) = default;
virtual ~illegal_name_error() noexcept = default;
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
std::string name() const
{
@@ -101,14 +101,14 @@ namespace chaiscript
class name_conflict_error : public std::runtime_error
{
public:
explicit name_conflict_error(const std::string &t_name) noexcept
name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
{
}
name_conflict_error(const name_conflict_error &) = default;
virtual ~name_conflict_error() noexcept = default;
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
std::string name() const
{
@@ -125,13 +125,13 @@ namespace chaiscript
class global_non_const : public std::runtime_error
{
public:
global_non_const() noexcept
global_non_const() CHAISCRIPT_NOEXCEPT
: std::runtime_error("a global object must be const")
{
}
global_non_const(const global_non_const &) = default;
virtual ~global_non_const() noexcept = default;
virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {}
};
}
@@ -194,28 +194,30 @@ namespace chaiscript
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
}
~Module()
{
}
bool has_function(const Proxy_Function &new_f, const std::string &name)
{
return std::any_of(m_funcs.begin(), m_funcs.end(),
[&](const std::pair<Proxy_Function, std::string> &existing_f) {
return existing_f.second == name && *(existing_f.first) == *(new_f);
}
);
return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair<Proxy_Function, std::string> &existing_f) {
return existing_f.second == name && *(existing_f.first) == *(new_f);
});
}
private:
std::vector<std::pair<Type_Info, std::string>> m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string>> m_funcs;
std::vector<std::pair<Boxed_Value, std::string>> m_globals;
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
std::vector<std::string> m_evals;
std::vector<Type_Conversion> m_conversions;
template<typename T, typename InItr>
static void apply(InItr begin, const InItr end, T &t)
{
for_each(begin, end,
[&t](const auto &obj) {
for_each(begin, end, [&t](typename std::iterator_traits<InItr>::reference obj)
{
try {
t.add(obj.first, obj.second);
} catch (const chaiscript::exception::name_conflict_error &) {
@@ -265,7 +267,7 @@ namespace chaiscript
/// A Proxy_Function implementation that is able to take
/// a vector of Proxy_Functions and perform a dispatch on them. It is
/// used specifically in the case of dealing with Function object variables
class Dispatch_Function final : public dispatch::Proxy_Function_Base
class Dispatch_Function : public dispatch::Proxy_Function_Base
{
public:
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
@@ -274,7 +276,7 @@ namespace chaiscript
{
}
bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
{
try {
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
@@ -284,7 +286,9 @@ namespace chaiscript
}
}
std::vector<Const_Proxy_Function> get_contained_functions() const override
virtual ~Dispatch_Function() {}
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
}
@@ -310,19 +314,19 @@ namespace chaiscript
return arity;
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return std::any_of(std::begin(m_funcs), std::end(m_funcs),
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
}
std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "Multiple method dispatch function wrapper.";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dispatch::dispatch(m_funcs, params, t_conversions);
}
@@ -598,10 +602,12 @@ namespace chaiscript
{
t_holder.call_params.pop_back();
StackData &stack = get_stack_data(t_holder);
assert(!stack.empty());
stack.pop_back();
if (stack.size() > 1)
{
stack.pop_back();
} else {
throw std::range_error("Unable to pop global stack");
}
}
@@ -620,7 +626,7 @@ namespace chaiscript
/// Searches the current stack for an object of the given name
/// includes a special overload for the _ place holder object to
/// ensure that it is always in scope.
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const
{
enum class Loc : uint_fast32_t {
located = 0x80000000,
@@ -633,7 +639,7 @@ namespace chaiscript
if (loc == 0)
{
auto &stack = get_stack_data(t_holder);
auto &stack = get_stack_data();
// Is it in the stack?
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
@@ -652,7 +658,7 @@ namespace chaiscript
t_loc = static_cast<uint_fast32_t>(Loc::located);
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
auto &stack = get_stack_data(t_holder);
auto &stack = get_stack_data();
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
}
@@ -911,12 +917,15 @@ namespace chaiscript
return false;
}
return std::any_of(std::begin(t_funs), std::end(t_funs),
[&](const auto &fun) {
return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions);
for (const auto &fun : t_funs) {
if (fun->is_attribute_function()) {
if (fun->compare_first_type(t_params[0], t_conversions)) {
return true;
}
);
}
}
return false;
}
#ifdef CHAISCRIPT_MSVC
@@ -1100,7 +1109,7 @@ namespace chaiscript
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
return const_var(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
}
/// Dump all system info to stdout
@@ -1323,8 +1332,13 @@ namespace chaiscript
const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size();
static const auto boxed_type = user_type<Boxed_Value>();
static const auto boxed_pod_type = user_type<Boxed_Number>();
#ifdef CHAISCRIPT_HAS_MAGIC_STATICS
static auto boxed_type = user_type<Boxed_Value>();
static auto boxed_pod_type = user_type<Boxed_Number>();
#else
auto boxed_type = user_type<Boxed_Value>();
auto boxed_pod_type = user_type<Boxed_Number>();
#endif
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{
@@ -1528,10 +1542,6 @@ namespace chaiscript
m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
}
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
}
private:
std::reference_wrapper<Dispatch_Engine> m_engine;
std::reference_wrapper<Stack_Holder> m_stack_holder;

View File

@@ -33,7 +33,7 @@ namespace chaiscript
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() noexcept = default;
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
};
class Dynamic_Object
@@ -44,7 +44,9 @@ namespace chaiscript
{
}
Dynamic_Object() = default;
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{
}
bool is_explicit() const
{
@@ -82,10 +84,6 @@ namespace chaiscript
}
}
bool has_attr(const std::string &t_attr_name) const {
return m_attrs.find(t_attr_name) != m_attrs.end();
}
Boxed_Value &get_attr(const std::string &t_attr_name)
{
return m_attrs[t_attr_name];
@@ -109,14 +107,15 @@ namespace chaiscript
return get_attr(t_method_name);
}
std::map<std::string, Boxed_Value> get_attrs() const
{
return m_attrs;
}
private:
const std::string m_type_name = "";
bool m_option_explicit = false;
std::string m_type_name;
bool m_option_explicit;
std::map<std::string, Boxed_Value> m_attrs;
};

View File

@@ -39,7 +39,7 @@ namespace chaiscript
/// A Proxy_Function implementation designed for calling a function
/// that is automatically guarded based on the first param based on the
/// param's type name
class Dynamic_Object_Function final : public Proxy_Function_Base
class Dynamic_Object_Function : public Proxy_Function_Base
{
public:
Dynamic_Object_Function(
@@ -67,11 +67,12 @@ namespace chaiscript
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
}
virtual ~Dynamic_Object_Function() {}
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
bool operator==(const Proxy_Function_Base &f) const override
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
{
@@ -81,9 +82,9 @@ namespace chaiscript
}
}
bool is_attribute_function() const override { return m_is_attribute; }
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
@@ -93,19 +94,19 @@ namespace chaiscript
}
}
std::vector<Const_Proxy_Function> get_contained_functions() const override
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return {m_func};
}
std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
@@ -115,7 +116,7 @@ namespace chaiscript
}
}
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
}
@@ -169,7 +170,9 @@ namespace chaiscript
Proxy_Function m_func;
std::unique_ptr<Type_Info> m_ti;
const Type_Info m_doti;
const bool m_is_attribute;
bool m_is_attribute;
};
@@ -179,7 +182,7 @@ namespace chaiscript
* that is automatically guarded based on the first param based on the
* param's type name
*/
class Dynamic_Object_Constructor final : public Proxy_Function_Base
class Dynamic_Object_Constructor : public Proxy_Function_Base
{
public:
Dynamic_Object_Constructor(
@@ -205,27 +208,29 @@ namespace chaiscript
return std::vector<Type_Info>(begin, end);
}
bool operator==(const Proxy_Function_Base &f) const override
virtual ~Dynamic_Object_Constructor() {}
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
}
}
std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_func->annotation();
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
std::vector<Boxed_Value> new_params{bv};
@@ -237,8 +242,8 @@ namespace chaiscript
}
private:
const std::string m_type_name;
const Proxy_Function m_func;
std::string m_type_name;
Proxy_Function m_func;
};
}

View File

@@ -23,11 +23,12 @@ namespace chaiscript
{
namespace detail
{
/// \todo make this a variadic template
struct Exception_Handler_Base
{
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
virtual ~Exception_Handler_Base() = default;
virtual ~Exception_Handler_Base() {}
protected:
template<typename T>
@@ -37,12 +38,65 @@ namespace chaiscript
}
};
template<typename ... T>
struct Exception_Handler_Impl : Exception_Handler_Base
template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base
{
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
virtual ~Exception_Handler_Impl1() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
(void)std::initializer_list<int>{(throw_type<T>(bv, t_engine), 0)...};
throw_type<T1>(bv, t_engine);
}
};
template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl2() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl3() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl4() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
}
};
template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base
{
virtual ~Exception_Handler_Impl5() {}
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE
{
throw_type<T1>(bv, t_engine);
throw_type<T2>(bv, t_engine);
throw_type<T3>(bv, t_engine);
throw_type<T4>(bv, t_engine);
throw_type<T5>(bv, t_engine);
}
};
}
@@ -101,10 +155,42 @@ namespace chaiscript
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
/// \sa \ref exceptions
template<typename ... T>
template<typename T1>
Exception_Handler exception_specification()
{
return std::make_shared<detail::Exception_Handler_Impl<T...>>();
return Exception_Handler(new detail::Exception_Handler_Impl1<T1>());
}
/// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl2<T1, T2>());
}
/// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl3<T1, T2, T3>());
}
/// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl4<T1, T2, T3, T4>());
}
/// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing
/// \sa \ref exceptions
template<typename T1, typename T2, typename T3, typename T4, typename T5>
Exception_Handler exception_specification()
{
return Exception_Handler(new detail::Exception_Handler_Impl5<T1, T2, T3, T4, T5>());
}
}

View File

@@ -35,7 +35,8 @@ namespace chaiscript
/// \returns A std::function object for dispatching
/// \param[in] funcs the set of functions to dispatch on.
template<typename FunctionType>
std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
[](const Const_Proxy_Function &f) {
@@ -62,7 +63,8 @@ namespace chaiscript
/// \returns A std::function object for dispatching
/// \param[in] func A function to execute.
template<typename FunctionType>
std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
std::function<FunctionType>
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
}
@@ -70,7 +72,8 @@ namespace chaiscript
/// Helper for automatically unboxing a Boxed_Value that contains a function object
/// and creating a typesafe C++ function caller from it.
template<typename FunctionType>
std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
std::function<FunctionType>
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
{
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
}

View File

@@ -141,6 +141,22 @@ 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));
}
}

View File

@@ -20,19 +20,11 @@ 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
{
/**
@@ -61,14 +53,19 @@ namespace chaiscript
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::fun(f)
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
};
template<typename Ret>
struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &>
struct Handle_Return<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)
);
}
};
template<typename Ret>
@@ -76,19 +73,29 @@ namespace chaiscript
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
assignable_fun(std::ref(*f), f)
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
{
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)
);
}
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
{
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)
);
}
};
template<typename Ret>
@@ -96,17 +103,36 @@ namespace chaiscript
{
static Boxed_Value handle(std::function<Ret> &f) {
return Boxed_Value(
assignable_fun(std::ref(f), std::shared_ptr<std::function<Ret>>())
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(f),
std::shared_ptr<std::function<Ret>>())
);
}
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::fun(f)
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(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 *>
{
@@ -135,13 +161,21 @@ namespace chaiscript
};
template<typename Ret>
struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &>
struct Handle_Return<std::shared_ptr<Ret> >
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
};
template<typename Ret>
struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &>
struct Handle_Return<const std::shared_ptr<Ret> &>
{
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
};
template<typename Ret>
@@ -154,6 +188,9 @@ namespace chaiscript
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret>
struct Handle_Return<Ret &>
{
@@ -168,6 +205,9 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value>
{
@@ -177,19 +217,40 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
struct Handle_Return<const Boxed_Value>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
struct Handle_Return<Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value>
struct Handle_Return<const Boxed_Value &>
{
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
};
/**
@@ -204,9 +265,16 @@ namespace chaiscript
}
};
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<>
struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number>
struct Handle_Return<const Boxed_Number>
{
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
};
@@ -218,7 +286,7 @@ namespace chaiscript
{
static Boxed_Value handle()
{
return void_var();
return Boxed_Value(Boxed_Value::Void_Type());
}
};
}

View File

@@ -17,32 +17,13 @@ namespace chaiscript
namespace detail
{
template<typename Class, typename ... Params, size_t ... I >
Proxy_Function build_constructor_(Class (*)(Params...), std::index_sequence<I...>)
template<typename Class, typename ... Params >
Proxy_Function build_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>()...})
{
}
auto call = dispatch::detail::Constructor<Class, Params...>();
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, 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> &params, 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>();
}();
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
}
}
}
@@ -63,7 +44,7 @@ namespace chaiscript
Proxy_Function constructor()
{
T *f = nullptr;
return dispatch::detail::build_constructor_(f, std::make_index_sequence<dispatch::detail::Arity<T>::arity>());
return (dispatch::detail::build_constructor_(f));
}
}

View File

@@ -21,34 +21,15 @@
#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;
/**
* 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;
};
struct arity_error;
} // namespace exception
} // namespace chaiscript
@@ -164,7 +145,7 @@ namespace chaiscript
class Proxy_Function_Base
{
public:
virtual ~Proxy_Function_Base() = default;
virtual ~Proxy_Function_Base() {}
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Type_Conversions_State &t_conversions) const
{
@@ -267,8 +248,7 @@ namespace chaiscript
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs,
const Type_Conversions_State &t_conversions)
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions_State &t_conversions)
{
if (tis.size() - 1 != bvs.size())
{
@@ -302,13 +282,14 @@ namespace chaiscript
class guard_error : public std::runtime_error
{
public:
guard_error() noexcept
guard_error() CHAISCRIPT_NOEXCEPT
: std::runtime_error("Guard evaluation failed")
{ }
guard_error(const guard_error &) = default;
virtual ~guard_error() noexcept = default;
virtual ~guard_error() CHAISCRIPT_NOEXCEPT
{ }
};
}
@@ -333,8 +314,9 @@ namespace chaiscript
{
}
virtual ~Dynamic_Proxy_Function() {}
virtual bool operator==(const Proxy_Function_Base &rhs) const override
virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
{
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
@@ -345,7 +327,7 @@ namespace chaiscript
&& this->m_param_types == prhs->m_param_types);
}
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
&& test_guard(vals, t_conversions);
@@ -362,7 +344,7 @@ namespace chaiscript
return m_parsenode;
}
virtual std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return m_description;
}
@@ -412,7 +394,7 @@ namespace chaiscript
template<typename Callable>
class Dynamic_Proxy_Function_Impl final : public Dynamic_Proxy_Function
class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function
{
public:
Dynamic_Proxy_Function_Impl(
@@ -433,9 +415,11 @@ namespace chaiscript
{
}
virtual ~Dynamic_Proxy_Function_Impl() {}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
{
@@ -446,6 +430,7 @@ namespace chaiscript
}
private:
Callable m_f;
};
@@ -466,7 +451,7 @@ namespace chaiscript
/// and substitutes bound parameters into the parameter list
/// at runtime, when call() is executed.
/// it is used for bind(function, param1, _, param2) style calls
class Bound_Function final : public Proxy_Function_Base
class Bound_Function : public Proxy_Function_Base
{
public:
Bound_Function(const Const_Proxy_Function &t_f,
@@ -477,18 +462,19 @@ namespace chaiscript
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
}
bool operator==(const Proxy_Function_Base &t_f) const override
virtual bool operator==(const Proxy_Function_Base &t_f) const CHAISCRIPT_OVERRIDE
{
return &t_f == this;
}
virtual ~Bound_Function() {}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return m_f->call_match(build_param_list(vals), t_conversions);
}
std::vector<Const_Proxy_Function> get_contained_functions() const override
virtual std::vector<Const_Proxy_Function> get_contained_functions() const CHAISCRIPT_OVERRIDE
{
return std::vector<Const_Proxy_Function>{m_f};
}
@@ -525,7 +511,7 @@ namespace chaiscript
return args;
}
virtual std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "Bound: " + m_f->annotation();
}
@@ -538,11 +524,18 @@ namespace chaiscript
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
const auto types = t_f->get_param_types();
std::vector<Type_Info> types = t_f->get_param_types();
assert(types.size() == t_args.size() + 1);
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(push)
#pragma warning(disable : 6011)
#endif
// this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14
std::vector<Type_Info> retval{types[0]};
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
for (size_t i = 0; i < types.size() - 1; ++i)
{
@@ -555,7 +548,7 @@ namespace chaiscript
return retval;
}
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return (*m_f)(build_param_list(params), t_conversions);
}
@@ -573,63 +566,59 @@ namespace chaiscript
{
}
std::string annotation() const override
virtual ~Proxy_Function_Impl_Base() {}
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "";
}
bool operator==(const Proxy_Function_Base &t_func) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_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> &params, 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()
&& (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions));
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions));
}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
};
/// For any callable object
template<typename Func, typename Callable>
class Proxy_Function_Callable_Impl : 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))
{
}
virtual ~Proxy_Function_Callable_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
{
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
}
private:
Callable m_f;
};
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
{
public:
@@ -638,14 +627,60 @@ namespace chaiscript
{
}
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
virtual ~Assignable_Proxy_Function() {}
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
};
template<typename Func>
class Assignable_Proxy_Function_Impl : 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());
}
virtual ~Assignable_Proxy_Function_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
{
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
}
std::function<Func> internal_function() const
{
return m_f.get();
}
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) CHAISCRIPT_OVERRIDE {
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
return detail::Do_Call<typename std::function<Func>::result_type>::template go<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
template<typename T, typename Class>
class Attribute_Access final : public Proxy_Function_Base
class Attribute_Access : public Proxy_Function_Base
{
public:
Attribute_Access(T Class::* t_attr)
@@ -654,9 +689,11 @@ namespace chaiscript
{
}
bool is_attribute_function() const override { return true; }
virtual ~Attribute_Access() {}
bool operator==(const Proxy_Function_Base &t_func) const override
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; }
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
{
const Attribute_Access<T, Class> * aa
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
@@ -668,7 +705,7 @@ namespace chaiscript
}
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const override
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE
{
if (vals.size() != 1)
{
@@ -678,52 +715,26 @@ namespace chaiscript
return vals[0].get_type_info().bare_equal(user_type<Class>());
}
std::string annotation() const override
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
{
return "";
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
return do_call_impl<T>(o);
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
} else {
Class *o = boxed_cast<Class *>(bv, &t_conversions);
return do_call_impl<T>(o);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
}
}
private:
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<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<const Type>::handle(o->*m_attr);
}
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<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<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
}
static std::vector<Type_Info> param_types()
{
return {user_type<T>(), user_type<Class>()};
@@ -758,7 +769,7 @@ namespace chaiscript
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() noexcept = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}
std::vector<Boxed_Value> parameters;
std::vector<Const_Proxy_Function> functions;

View File

@@ -0,0 +1,275 @@
// 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 "../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() CHAISCRIPT_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>()... };
}
#ifdef CHAISCRIPT_GCC_4_6
/// \todo REMOVE THIS WHEN WE DROP G++4.6
// Forward declaration
template<typename ... Rest>
struct Try_Cast;
template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...>
{
static void do_try(const std::vector<Boxed_Value> &params, size_t generation, const Type_Conversions_State &t_conversions)
{
boxed_cast<Param>(params[generation], &t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
}
};
// 0th case
template<>
struct Try_Cast<>
{
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions_State &)
{
}
};
/**
* 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> &params, const Type_Conversions_State &t_conversions)
{
try {
Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) {
return false;
}
return true;
}
template<typename Ret, int count, typename ... Params>
struct Call_Func
{
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
}
};
template<typename Ret, typename ... Params>
struct Call_Func<Ret, 0, Params...>
{
#ifdef CHAISCRIPT_MSVC
#pragma warning(push)
#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this
#endif
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
};
/**
* 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>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
if (params.size() == sizeof...(Params))
{
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
}
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
}
#else
template<size_t ... I>
struct Indexes
{
};
template<size_t S, size_t ... I>
struct Make_Indexes
{
typedef typename Make_Indexes<S-1, I..., sizeof...(I)>::indexes indexes;
};
template<size_t ... I>
struct Make_Indexes<0, I...>
{
typedef Indexes<I...> indexes;
};
/**
* 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, size_t ... I>
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
(void)params; (void)t_conversions;
(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 Ret, typename ... Params>
bool compare_types_cast(Ret (*f)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return compare_types_cast(indexes(), f, params, t_conversions);
}
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, 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>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
return call_func(sig, indexes(), f, params, t_conversions);
}
#endif
}
}
}
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};
}
}
}
#endif

View File

@@ -11,8 +11,6 @@
#include "bind_first.hpp"
#include "proxy_functions.hpp"
#include "handle_return.hpp"
#include "function_call.hpp"
namespace chaiscript
{
@@ -37,396 +35,45 @@ 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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;
Signature *f = nullptr;
return fun(t, f, std::make_index_sequence<dispatch::detail::Arity<Signature>::arity>());
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
}
template<typename ... Param, size_t ... I>
Proxy_Function fun(void (*t_func)(Param...), std::index_sequence<I...>)
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
{
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)
{
}
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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> &params, 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);
}();
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
{
return fun(t_func, std::make_index_sequence<sizeof...(Param)>());
}
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
{
return fun(func, std::make_index_sequence<sizeof...(Param)>());
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...))
{
return fun(t_func, std::make_index_sequence<sizeof...(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));
}
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*/ )
{

View File

@@ -29,48 +29,48 @@ namespace chaiscript
{
public:
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) noexcept
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_dynamic_cast(const std::string &w) noexcept
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() noexcept = default;
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
};
class bad_boxed_type_cast : public bad_boxed_cast
{
public:
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
const std::string &t_what) noexcept
const std::string &t_what) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to, t_what)
{
}
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(t_from, t_to)
{
}
bad_boxed_type_cast(const std::string &w) noexcept
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
: bad_boxed_cast(w)
{
}
bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() noexcept = default;
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
};
}
@@ -97,7 +97,7 @@ namespace chaiscript
return true;
}
virtual ~Type_Conversion_Base() = default;
virtual ~Type_Conversion_Base() {}
protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
@@ -107,8 +107,8 @@ namespace chaiscript
private:
const Type_Info m_to;
const Type_Info m_from;
Type_Info m_to;
Type_Info m_from;
};
@@ -126,7 +126,7 @@ namespace chaiscript
if (t_from.is_const())
{
return Boxed_Value(
[&](){
[&]()->std::shared_ptr<const To>{
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
@@ -137,7 +137,7 @@ namespace chaiscript
);
} else {
return Boxed_Value(
[&](){
[&]()->std::shared_ptr<To>{
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
@@ -182,7 +182,7 @@ namespace chaiscript
if (t_from.is_const())
{
return Boxed_Value(
[&](){
[&]()->std::shared_ptr<const To>{
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{
return data;
@@ -193,7 +193,7 @@ namespace chaiscript
);
} else {
return Boxed_Value(
[&](){
[&]()->std::shared_ptr<To>{
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{
return data;
@@ -242,12 +242,12 @@ namespace chaiscript
{
}
Boxed_Value convert_down(const Boxed_Value &t_base) const override
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
{
return Dynamic_Caster<Base, Derived>::cast(t_base);
}
Boxed_Value convert(const Boxed_Value &t_derived) const override
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Static_Caster<Derived, Base>::cast(t_derived);
}
@@ -262,18 +262,17 @@ namespace chaiscript
{
}
Boxed_Value convert_down(const Boxed_Value &t_base) const override
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
{
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived),
"Unable to cast down inheritance hierarchy with non-polymorphic types");
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types");
}
bool bidir() const override
virtual bool bidir() const CHAISCRIPT_OVERRIDE
{
return false;
}
Boxed_Value convert(const Boxed_Value &t_derived) const override
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
{
return Static_Caster<Derived, Base>::cast(t_derived);
}
@@ -291,18 +290,18 @@ namespace chaiscript
{
}
Boxed_Value convert_down(const Boxed_Value &) const override
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
{
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
}
Boxed_Value convert(const Boxed_Value &t_from) const override
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
{
/// \todo better handling of errors from the conversion function
return m_func(t_from);
}
virtual bool bidir() const override
virtual bool bidir() const CHAISCRIPT_OVERRIDE
{
return false;
}
@@ -318,7 +317,11 @@ namespace chaiscript
public:
struct Conversion_Saves
{
bool enabled = false;
Conversion_Saves()
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves;
};
@@ -347,6 +350,7 @@ namespace chaiscript
m_num_types(m_conversions.size()),
m_thread_cache(this),
m_conversion_saves(this)
{
}
@@ -444,7 +448,7 @@ namespace chaiscript
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = find(to, from);
auto itr = find(to, from);
if (itr != m_conversions.end())
{

View File

@@ -29,7 +29,7 @@ namespace chaiscript
class Type_Info
{
public:
constexpr Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
CHAISCRIPT_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)
@@ -40,50 +40,59 @@ namespace chaiscript
{
}
constexpr Type_Info() = default;
CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_flags(1 << is_undef_flag)
{
}
constexpr bool operator<(const Type_Info &ti) const noexcept
#if !defined(_MSC_VER) || _MSC_VER != 1800
Type_Info(Type_Info&&) = default;
Type_Info& operator=(Type_Info&&) = default;
#endif
Type_Info(const Type_Info&) = default;
Type_Info& operator=(const Type_Info&) = default;
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return m_type_info < ti.m_type_info;
}
constexpr bool operator==(const Type_Info &ti) const noexcept
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_type_info == m_type_info
|| *ti.m_type_info == *m_type_info;
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
}
constexpr bool operator!=(const Type_Info &ti) const noexcept
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return !(*this == ti);
return m_type_info != nullptr && (*m_type_info) == ti;
}
constexpr bool operator==(const std::type_info &ti) const noexcept
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
{
return !is_undef() && (*m_type_info) == ti;
return ti.m_bare_type_info == m_bare_type_info
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
}
constexpr bool bare_equal(const Type_Info &ti) const noexcept
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
{
return ti.m_bare_type_info == m_bare_type_info
|| *ti.m_bare_type_info == *m_bare_type_info;
return m_bare_type_info != nullptr
&& (*m_bare_type_info) == ti;
}
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
{
return !is_undef() && (*m_bare_type_info) == ti;
}
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_const_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_reference_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_void_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_undef_flag)) != 0; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; }
std::string name() const
{
if (!is_undef())
if (m_type_info)
{
return m_type_info->name();
} else {
@@ -93,7 +102,7 @@ namespace chaiscript
std::string bare_name() const
{
if (!is_undef())
if (m_bare_type_info)
{
return m_bare_type_info->name();
} else {
@@ -101,23 +110,21 @@ namespace chaiscript
}
}
constexpr const std::type_info *bare_type_info() const
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
{
return m_bare_type_info;
}
private:
struct Unknown_Type {};
const std::type_info *m_type_info = &typeid(Unknown_Type);
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
unsigned int m_flags;
static const int is_const_flag = 0;
static const int is_reference_flag = 1;
static const int is_pointer_flag = 2;
static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
unsigned int m_flags = (1 << is_undef_flag);
};
namespace detail

View File

@@ -113,7 +113,7 @@ namespace chaiscript
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
@@ -121,18 +121,18 @@ namespace chaiscript
eval_error(const std::string &t_why,
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
bool t_dot_notation,
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
{}
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT :
std::runtime_error(format(t_why, t_where, t_fname)),
reason(t_why), start_position(t_where), filename(t_fname)
{}
eval_error(const std::string &t_why) noexcept
eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT
: std::runtime_error("Error: \"" + t_why + "\" "),
reason(t_why)
{}
@@ -161,7 +161,7 @@ namespace chaiscript
return ss.str();
}
virtual ~eval_error() noexcept {}
virtual ~eval_error() CHAISCRIPT_NOEXCEPT {}
private:
@@ -420,12 +420,12 @@ namespace chaiscript
/// Errors generated when loading a file
struct file_not_found_error : std::runtime_error {
file_not_found_error(const std::string &t_filename) noexcept
file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT
: std::runtime_error("File Not Found: " + t_filename)
{ }
file_not_found_error(const file_not_found_error &) = default;
virtual ~file_not_found_error() noexcept {}
virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {}
};
}

View File

@@ -54,13 +54,13 @@ namespace chaiscript
/// \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
load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT
: std::runtime_error(t_reason)
{
}
load_module_error(const load_module_error &) = default;
virtual ~load_module_error() noexcept {}
virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {}
};
}

View File

@@ -24,6 +24,7 @@
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/dynamic_object_detail.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/proxy_functions_detail.hpp"
#include "../dispatchkit/register_function.hpp"
#include "../dispatchkit/type_info.hpp"
#include "chaiscript_algebraic.hpp"
@@ -81,18 +82,20 @@ namespace chaiscript
}
struct Binary_Operator_AST_Node : AST_Node {
public:
Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(t_oper))
{ }
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
auto lhs = this->children[0]->eval(t_ss);
auto rhs = this->children[1]->eval(t_ss);
return do_oper(t_ss, m_oper, text, lhs, rhs);
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")";
}
@@ -128,25 +131,28 @@ namespace chaiscript
mutable std::atomic_uint_fast32_t m_loc;
};
struct Int_AST_Node final : AST_Node {
struct Int_AST_Node : public AST_Node {
public:
Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)),
m_value(std::move(t_bv)) { assert(text != ""); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
virtual ~Int_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
return m_value;
}
private:
Boxed_Value m_value;
};
struct Float_AST_Node final : AST_Node {
struct Float_AST_Node : public AST_Node {
public:
Float_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, std::move(t_loc)),
m_value(std::move(t_bv)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
virtual ~Float_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
return m_value;
}
@@ -155,19 +161,21 @@ namespace chaiscript
};
struct Id_AST_Node final : AST_Node {
struct Id_AST_Node : public AST_Node {
public:
Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) :
AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)),
m_value(get_value(t_ast_node_text)), m_loc(0)
{ }
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Id_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
if (!m_value.is_undef())
{
return m_value;
} else {
try {
return t_ss.get_object(this->text, m_loc);
return t_ss->get_object(this->text, m_loc);
}
catch (std::exception &) {
throw exception::eval_error("Can not find object: " + this->text);
@@ -198,33 +206,39 @@ namespace chaiscript
mutable std::atomic_uint_fast32_t m_loc;
};
struct Char_AST_Node final : AST_Node {
struct Char_AST_Node : public AST_Node {
public:
Char_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Char, std::move(t_loc)) { }
virtual ~Char_AST_Node() {}
};
struct Str_AST_Node final : AST_Node {
struct Str_AST_Node : public AST_Node {
public:
Str_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Str, std::move(t_loc)) { }
virtual ~Str_AST_Node() {}
};
struct Eol_AST_Node final : AST_Node {
struct Eol_AST_Node : public AST_Node {
public:
Eol_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Eol, std::move(t_loc)) { }
virtual ~Eol_AST_Node() {}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "\n";
}
};
struct Fun_Call_AST_Node final : AST_Node {
struct Fun_Call_AST_Node : public AST_Node {
public:
Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
virtual ~Fun_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
std::vector<Boxed_Value> params;
@@ -264,7 +278,7 @@ namespace chaiscript
}
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
@@ -288,11 +302,13 @@ namespace chaiscript
struct Arg_AST_Node final : AST_Node {
struct Arg_AST_Node : public AST_Node {
public:
Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
virtual ~Arg_AST_Node() {}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (size_t j = 0; j < this->children.size(); ++j) {
@@ -308,11 +324,13 @@ namespace chaiscript
}
};
struct Arg_List_AST_Node final : AST_Node {
struct Arg_List_AST_Node : public AST_Node {
public:
Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { }
virtual ~Arg_List_AST_Node() {}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
for (size_t j = 0; j < this->children.size(); ++j) {
@@ -353,9 +371,9 @@ namespace chaiscript
{
if (t_node->children.size() < 2)
{
return {};
return std::pair<std::string, Type_Info>();
} else {
return {t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)};
return std::pair<std::string, Type_Info>(t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false));
}
}
@@ -371,14 +389,19 @@ namespace chaiscript
}
};
struct Equation_AST_Node final : AST_Node {
struct Equation_AST_Node : public AST_Node {
public:
Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[1]->text))
{ assert(children.size() == 3); }
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value rhs = this->children[2]->eval(t_ss);
Boxed_Value lhs = this->children[0]->eval(t_ss);
@@ -446,20 +469,17 @@ namespace chaiscript
return rhs;
}
private:
Operators::Opers m_oper;
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_clone_loc;
};
struct Global_Decl_AST_Node final : AST_Node {
struct Global_Decl_AST_Node : public AST_Node {
public:
Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { }
virtual ~Global_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
const std::string &idname =
[&]()->const std::string & {
[&]()->const std::string &{
if (children[0]->identifier == AST_Node_Type::Reference) {
return children[0]->children[0]->text;
} else {
@@ -478,11 +498,12 @@ namespace chaiscript
};
struct Var_Decl_AST_Node final : AST_Node {
struct Var_Decl_AST_Node : public AST_Node {
public:
Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Var_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
if (this->children[0]->identifier == AST_Node_Type::Reference)
{
return this->children[0]->eval(t_ss);
@@ -503,7 +524,7 @@ namespace chaiscript
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "var " + this->children[0]->text;
}
@@ -511,14 +532,15 @@ namespace chaiscript
};
struct Array_Call_AST_Node final : AST_Node {
struct Array_Call_AST_Node : public AST_Node {
public:
Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
const std::vector<Boxed_Value> params{children[0]->eval(t_ss), children[1]->eval(t_ss)};
std::vector<Boxed_Value> params{children[0]->eval(t_ss), children[1]->eval(t_ss)};
try {
fpp.save_params(params);
@@ -527,9 +549,10 @@ namespace chaiscript
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
}
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
std::ostringstream oss;
oss << this->children[0]->pretty_print();
@@ -544,18 +567,19 @@ namespace chaiscript
return oss.str();
}
private:
mutable std::atomic_uint_fast32_t m_loc;
};
struct Dot_Access_AST_Node final : AST_Node {
struct Dot_Access_AST_Node : public AST_Node {
public:
Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)),
m_fun_name(
((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))?
children[2]->children[0]->text:children[2]->text) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Dot_Access_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
@@ -602,37 +626,42 @@ namespace chaiscript
private:
mutable std::atomic_uint_fast32_t m_loc;
mutable std::atomic_uint_fast32_t m_array_loc;
const std::string m_fun_name;
std::string m_fun_name;
};
struct Quoted_String_AST_Node final : AST_Node {
struct Quoted_String_AST_Node : public AST_Node {
public:
Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Quoted_String, std::move(t_loc)),
m_value(const_var(text)) { }
virtual ~Quoted_String_AST_Node() {}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override {
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE {
return m_value;
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "\"" + text + "\"";
}
private:
Boxed_Value m_value;
};
struct Single_Quoted_String_AST_Node final : AST_Node {
struct Single_Quoted_String_AST_Node : public AST_Node {
public:
Single_Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Single_Quoted_String, std::move(t_loc)),
m_value(const_var(char(text.at(0)))) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
virtual ~Single_Quoted_String_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
return m_value;
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "'" + text + "'";
}
@@ -641,12 +670,15 @@ namespace chaiscript
Boxed_Value m_value;
};
struct Lambda_AST_Node final : AST_Node {
struct Lambda_AST_Node : public AST_Node {
public:
Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)),
m_param_names(Arg_List_AST_Node::get_arg_names(children[1])) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Lambda_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
const auto captures = [&]()->std::map<std::string, Boxed_Value>{
std::map<std::string, Boxed_Value> named_captures;
@@ -657,6 +689,7 @@ namespace chaiscript
}();
const auto numparams = this->children[1]->children.size();
const auto param_names = m_param_names;
const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss);
const auto &lambda_node = this->children.back();
@@ -664,7 +697,7 @@ namespace chaiscript
return Boxed_Value(
dispatch::make_dynamic_proxy_function(
[engine, lambda_node, param_names = this->m_param_names, captures](const std::vector<Boxed_Value> &t_params)
[engine, lambda_node, param_names, captures](const std::vector<Boxed_Value> &t_params)
{
return detail::eval_function(engine, lambda_node, param_names, t_params, &captures);
},
@@ -674,15 +707,17 @@ namespace chaiscript
}
private:
const std::vector<std::string> m_param_names;
std::vector<std::string> m_param_names;
};
struct Block_AST_Node final : AST_Node {
struct Block_AST_Node : public AST_Node {
public:
Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { }
virtual ~Block_AST_Node() {}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
const auto num_children = children.size();
@@ -690,14 +725,17 @@ namespace chaiscript
children[i]->eval(t_ss);
}
return children.back()->eval(t_ss);
}
};
struct Def_AST_Node final : AST_Node {
struct Def_AST_Node : public AST_Node {
public:
Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Def_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
std::vector<std::string> t_param_names;
size_t numparams = 0;
AST_NodePtr guardnode;
@@ -751,16 +789,17 @@ namespace chaiscript
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Function redefined '" + e.name() + "'");
}
return void_var();
return Boxed_Value();
}
};
struct While_AST_Node final : AST_Node {
struct While_AST_Node : public AST_Node {
public:
While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~While_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try {
@@ -777,15 +816,16 @@ namespace chaiscript
// loop was broken intentionally
}
return void_var();
return Boxed_Value();
}
};
struct Class_AST_Node final : AST_Node {
struct Class_AST_Node : public AST_Node {
public:
Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Class_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
/// \todo do this better
@@ -794,30 +834,33 @@ namespace chaiscript
children[1]->eval(t_ss);
return void_var();
return Boxed_Value();
}
};
struct Ternary_Cond_AST_Node final : AST_Node {
struct Ternary_Cond_AST_Node : public AST_Node {
public:
Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 3); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Ternary_Cond_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
if (get_bool_condition(children[0]->eval(t_ss))) {
return children[1]->eval(t_ss);
} else {
}
else {
return children[2]->eval(t_ss);
}
}
};
struct If_AST_Node final : AST_Node {
struct If_AST_Node : public AST_Node {
public:
If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~If_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
if (get_bool_condition(children[0]->eval(t_ss))) {
return children[1]->eval(t_ss);
@@ -838,17 +881,19 @@ namespace chaiscript
}
}
return void_var();
return Boxed_Value();
}
};
struct For_AST_Node final : AST_Node {
struct For_AST_Node : public AST_Node {
public:
For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 4); }
virtual ~For_AST_Node() {}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
try {
@@ -870,16 +915,17 @@ namespace chaiscript
// loop broken
}
return void_var();
return Boxed_Value();
}
};
struct Switch_AST_Node final : AST_Node {
struct Switch_AST_Node : public AST_Node {
public:
Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Switch_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
bool breaking = false;
size_t currentCase = 1;
bool hasMatched = false;
@@ -912,46 +958,50 @@ namespace chaiscript
}
++currentCase;
}
return void_var();
return Boxed_Value();
}
mutable std::atomic_uint_fast32_t m_loc;
};
struct Case_AST_Node final : AST_Node {
struct Case_AST_Node : public AST_Node {
public:
Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 2); /* how many children does it have? */ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Case_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
children[1]->eval(t_ss);
return void_var();
return Boxed_Value();
}
};
struct Default_AST_Node final : AST_Node {
struct Default_AST_Node : public AST_Node {
public:
Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 1); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Default_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
children[0]->eval(t_ss);
return void_var();
return Boxed_Value();
}
};
struct Inline_Array_AST_Node final : AST_Node {
struct Inline_Array_AST_Node : public AST_Node {
public:
Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
try {
std::vector<Boxed_Value> vec;
if (!children.empty()) {
@@ -972,20 +1022,20 @@ namespace chaiscript
}
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "[" + AST_Node::pretty_print() + "]";
}
private:
mutable std::atomic_uint_fast32_t m_loc;
};
struct Inline_Map_AST_Node final : AST_Node {
struct Inline_Map_AST_Node : public AST_Node {
public:
Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Inline_Map_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
std::map<std::string, Boxed_Value> retval;
@@ -1005,29 +1055,31 @@ namespace chaiscript
}
}
private:
mutable std::atomic_uint_fast32_t m_loc;
};
struct Return_AST_Node final : AST_Node {
struct Return_AST_Node : public AST_Node {
public:
Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Return_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
if (!this->children.empty()) {
throw detail::Return_Value(children[0]->eval(t_ss));
}
else {
throw detail::Return_Value(void_var());
throw detail::Return_Value(Boxed_Value());
}
}
};
struct File_AST_Node final : AST_Node {
struct File_AST_Node : public AST_Node {
public:
File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual ~File_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE {
try {
const auto num_children = children.size();
@@ -1037,7 +1089,7 @@ namespace chaiscript
}
return children.back()->eval(t_ss);
} else {
return void_var();
return Boxed_Value();
}
} catch (const detail::Continue_Loop &) {
throw exception::eval_error("Unexpected `continue` statement outside of a loop");
@@ -1047,12 +1099,13 @@ namespace chaiscript
}
};
struct Reference_AST_Node final : AST_Node {
struct Reference_AST_Node : public AST_Node {
public:
Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 1); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
Boxed_Value bv;
t_ss.add_object(this->children[0]->text, bv);
@@ -1062,15 +1115,19 @@ namespace chaiscript
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
}
}
virtual ~Reference_AST_Node() {}
};
struct Prefix_AST_Node final : AST_Node {
struct Prefix_AST_Node : public AST_Node {
public:
Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)),
m_oper(Operators::to_operator(children[0]->text, true))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Prefix_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
Boxed_Value bv(children[1]->eval(t_ss));
try {
@@ -1093,51 +1150,63 @@ namespace chaiscript
mutable std::atomic_uint_fast32_t m_loc;
};
struct Break_AST_Node final : AST_Node {
struct Break_AST_Node : public AST_Node {
public:
Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
virtual ~Break_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
throw detail::Break_Loop();
}
};
struct Continue_AST_Node final : AST_Node {
struct Continue_AST_Node : public AST_Node {
public:
Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
virtual ~Continue_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
throw detail::Continue_Loop();
}
};
struct Noop_AST_Node final : public AST_Node {
struct Noop_AST_Node : public AST_Node {
public:
Noop_AST_Node() :
AST_Node("", AST_Node_Type::Noop, Parse_Location())
AST_Node("", AST_Node_Type::Noop, Parse_Location()),
m_value(const_var(true))
{ }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{
virtual ~Noop_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{
// It's a no-op, that evaluates to "true"
// the magic-static version of const_var(true) helps us here
return const_var(true);
return m_value;
}
private:
Boxed_Value m_value;
};
struct Map_Pair_AST_Node final : AST_Node {
struct Map_Pair_AST_Node : public AST_Node {
public:
Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { }
virtual ~Map_Pair_AST_Node() {}
};
struct Value_Range_AST_Node final : AST_Node {
struct Value_Range_AST_Node : public AST_Node {
public:
Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { }
virtual ~Value_Range_AST_Node() {}
};
struct Inline_Range_AST_Node final : AST_Node {
struct Inline_Range_AST_Node : public AST_Node {
public:
Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
try {
auto oper1 = children[0]->children[0]->children[0]->eval(t_ss);
auto oper2 = children[0]->children[0]->children[1]->eval(t_ss);
@@ -1148,18 +1217,21 @@ namespace chaiscript
}
}
private:
mutable std::atomic_uint_fast32_t m_loc;
};
struct Annotation_AST_Node final : AST_Node {
struct Annotation_AST_Node : public AST_Node {
public:
Annotation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Annotation, std::move(t_loc)) { }
virtual ~Annotation_AST_Node() {}
};
struct Try_AST_Node final : AST_Node {
struct Try_AST_Node : public AST_Node {
public:
Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { }
virtual ~Try_AST_Node() {}
Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const
{
@@ -1222,7 +1294,7 @@ namespace chaiscript
return retval;
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
Boxed_Value retval;
chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
@@ -1266,21 +1338,26 @@ namespace chaiscript
};
struct Catch_AST_Node final : AST_Node {
struct Catch_AST_Node : public AST_Node {
public:
Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { }
virtual ~Catch_AST_Node() {}
};
struct Finally_AST_Node final : AST_Node {
struct Finally_AST_Node : public AST_Node {
public:
Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { }
virtual ~Finally_AST_Node() {}
};
struct Method_AST_Node final : AST_Node {
struct Method_AST_Node : public AST_Node {
public:
Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
virtual ~Method_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
AST_NodePtr guardnode;
@@ -1361,16 +1438,17 @@ namespace chaiscript
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Method redefined '" + e.name() + "'");
}
return void_var();
return Boxed_Value();
}
};
struct Attr_Decl_AST_Node final : AST_Node {
struct Attr_Decl_AST_Node : public AST_Node {
public:
Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
virtual ~Attr_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE
{
const auto &d = t_ss->get_parent_locals();
const auto itr = d.find("_current_class_name");
@@ -1396,41 +1474,42 @@ namespace chaiscript
} catch (const exception::name_conflict_error &e) {
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
}
return void_var();
return Boxed_Value();
}
};
struct Logical_And_AST_Node final : AST_Node {
struct Logical_And_AST_Node : public AST_Node {
public:
Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 3); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
virtual ~Logical_And_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
return const_var(get_bool_condition(children[0]->eval(t_ss))
&& get_bool_condition(children[2]->eval(t_ss)));
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "(" + AST_Node::pretty_print() + ")";
}
};
struct Logical_Or_AST_Node final : AST_Node {
struct Logical_Or_AST_Node : public AST_Node {
public:
Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children))
{ assert(children.size() == 3); }
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override
{
virtual ~Logical_Or_AST_Node() {}
virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{
return const_var(get_bool_condition(children[0]->eval(t_ss))
|| get_bool_condition(children[2]->eval(t_ss)));
}
std::string pretty_print() const override
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
{
return "(" + AST_Node::pretty_print() + ")";
}
@@ -1441,4 +1520,3 @@ namespace chaiscript
}
#endif /* CHAISCRIPT_EVAL_HPP_ */

View File

@@ -58,122 +58,15 @@ namespace chaiscript
class ChaiScript_Parser {
static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet()
{
std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> alphabet;
for (auto &alpha : alphabet) {
alpha.fill(false);
}
alphabet[detail::symbol_alphabet][static_cast<size_t>('?')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('+')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('-')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('*')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('/')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('|')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('&')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('^')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('=')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('.')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('<')]=true;
alphabet[detail::symbol_alphabet][static_cast<size_t>('>')]=true;
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
alphabet[detail::keyword_alphabet][static_cast<size_t>('_')]=true;
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::int_alphabet][c]=true; }
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::float_alphabet][c]=true; }
alphabet[detail::float_alphabet][static_cast<size_t>('.')]=true;
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
for ( size_t c = 'a' ; c <= 'f' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
for ( size_t c = 'A' ; c <= 'F' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
alphabet[detail::x_alphabet][static_cast<size_t>('x')]=true;
alphabet[detail::x_alphabet][static_cast<size_t>('X')]=true;
for ( size_t c = '0' ; c <= '1' ; ++c ) { alphabet[detail::bin_alphabet][c]=true; }
alphabet[detail::b_alphabet][static_cast<size_t>('b')]=true;
alphabet[detail::b_alphabet][static_cast<size_t>('B')]=true;
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; }
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; }
alphabet[detail::id_alphabet][static_cast<size_t>('_')] = true;
alphabet[detail::white_alphabet][static_cast<size_t>(' ')]=true;
alphabet[detail::white_alphabet][static_cast<size_t>('\t')]=true;
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('l')] = true;
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('L')] = true;
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('u')] = true;
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('U')] = true;
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('l')] = true;
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('L')] = true;
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('f')] = true;
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('F')] = true;
return alphabet;
}
static const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &create_alphabet()
{
static const auto alpha = build_alphabet();
return alpha;
}
static const std::vector<std::vector<std::string>> &create_operator_matches() {
static const std::vector<std::vector<std::string>> operator_matches {
{"?"},
{"||"},
{"&&"},
{"|"},
{"^"},
{"&"},
{"==", "!="},
{"<", "<=", ">", ">="},
{"<<", ">>"},
//We share precedence here but then separate them later
{"+", "-"},
{"*", "/", "%"}
};
return operator_matches;
}
static const std::array<AST_Node_Type::Type, 11> &create_operators() {
static const std::array<AST_Node_Type::Type, 11> operators = {{
AST_Node_Type::Ternary_Cond,
AST_Node_Type::Logical_Or,
AST_Node_Type::Logical_And,
AST_Node_Type::Bitwise_Or,
AST_Node_Type::Bitwise_Xor,
AST_Node_Type::Bitwise_And,
AST_Node_Type::Equality,
AST_Node_Type::Comparison,
AST_Node_Type::Shift,
AST_Node_Type::Addition,
AST_Node_Type::Multiplication
}};
return operators;
}
static constexpr const char * const m_multiline_comment_begin = "/*";
static constexpr const char * const m_multiline_comment_end = "*/";
static constexpr const char * const m_singleline_comment = "//";
const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &m_alphabet = create_alphabet();
const std::vector<std::vector<std::string>> &m_operator_matches = create_operator_matches();
const std::array<AST_Node_Type::Type, 11> &m_operators = create_operators();
std::string m_multiline_comment_begin;
std::string m_multiline_comment_end;
std::string m_singleline_comment;
std::shared_ptr<std::string> m_filename;
std::vector<AST_NodePtr> m_match_stack;
bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet];
std::vector<std::vector<std::string>> m_operator_matches;
std::vector<AST_Node_Type::Type> m_operators;
struct Position
{
@@ -278,13 +171,108 @@ namespace chaiscript
public:
ChaiScript_Parser()
: m_multiline_comment_begin("/*"),
m_multiline_comment_end("*/"),
m_singleline_comment("//")
{
m_match_stack.reserve(2);
setup_operators();
}
ChaiScript_Parser(const ChaiScript_Parser &) = delete;
ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete;
void setup_operators()
{
m_operators.emplace_back(AST_Node_Type::Ternary_Cond);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"?"}));
m_operators.emplace_back(AST_Node_Type::Logical_Or);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"||"}));
m_operators.emplace_back(AST_Node_Type::Logical_And);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"&&"}));
m_operators.emplace_back(AST_Node_Type::Bitwise_Or);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"|"}));
m_operators.emplace_back(AST_Node_Type::Bitwise_Xor);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"^"}));
m_operators.emplace_back(AST_Node_Type::Bitwise_And);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"&"}));
m_operators.emplace_back(AST_Node_Type::Equality);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"==", "!="}));
m_operators.emplace_back(AST_Node_Type::Comparison);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"<", "<=", ">", ">="}));
m_operators.emplace_back(AST_Node_Type::Shift);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"<<", ">>"}));
//We share precedence here but then separate them later
m_operators.emplace_back(AST_Node_Type::Addition);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"+", "-"}));
//We share precedence here but then separate them later
m_operators.emplace_back(AST_Node_Type::Multiplication);
m_operator_matches.emplace_back(std::initializer_list<std::string>({"*", "/", "%"}));
for (auto & elem : m_alphabet) {
std::fill(std::begin(elem), std::end(elem), false);
}
m_alphabet[detail::symbol_alphabet][static_cast<int>('?')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('+')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('-')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('*')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('/')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('|')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('&')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('^')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('=')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('.')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('<')]=true;
m_alphabet[detail::symbol_alphabet][static_cast<int>('>')]=true;
for ( int c = 'a' ; c <= 'z' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; }
for ( int c = 'A' ; c <= 'Z' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; }
for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; }
m_alphabet[detail::keyword_alphabet][static_cast<int>('_')]=true;
for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::int_alphabet][c]=true; }
for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::float_alphabet][c]=true; }
m_alphabet[detail::float_alphabet][static_cast<int>('.')]=true;
for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; }
for ( int c = 'a' ; c <= 'f' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; }
for ( int c = 'A' ; c <= 'F' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; }
m_alphabet[detail::x_alphabet][static_cast<int>('x')]=true;
m_alphabet[detail::x_alphabet][static_cast<int>('X')]=true;
for ( int c = '0' ; c <= '1' ; ++c ) { m_alphabet[detail::bin_alphabet][c]=true; }
m_alphabet[detail::b_alphabet][static_cast<int>('b')]=true;
m_alphabet[detail::b_alphabet][static_cast<int>('B')]=true;
for ( int c = 'a' ; c <= 'z' ; ++c ) { m_alphabet[detail::id_alphabet][c]=true; }
for ( int c = 'A' ; c <= 'Z' ; ++c ) { m_alphabet[detail::id_alphabet][c]=true; }
m_alphabet[detail::id_alphabet][static_cast<int>('_')] = true;
m_alphabet[detail::white_alphabet][static_cast<int>(' ')]=true;
m_alphabet[detail::white_alphabet][static_cast<int>('\t')]=true;
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('l')] = true;
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('L')] = true;
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('u')] = true;
m_alphabet[detail::int_suffix_alphabet][static_cast<int>('U')] = true;
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('l')] = true;
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('L')] = true;
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('f')] = true;
m_alphabet[detail::float_suffix_alphabet][static_cast<int>('F')] = true;
}
/// test a char in an m_alphabet
bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast<uint8_t>(c)]; }
@@ -435,16 +423,16 @@ namespace chaiscript
/// Skips any multi-line or single-line comment
bool SkipComment() {
if (Symbol_(m_multiline_comment_begin)) {
if (Symbol_(m_multiline_comment_begin.c_str())) {
while (m_position.has_more()) {
if (Symbol_(m_multiline_comment_end)) {
if (Symbol_(m_multiline_comment_end.c_str())) {
break;
} else if (!Eol_()) {
++m_position;
}
}
return true;
} else if (Symbol_(m_singleline_comment)) {
} else if (Symbol_(m_singleline_comment.c_str())) {
while (m_position.has_more()) {
if (Symbol_("\r\n")) {
m_position -= 2;
@@ -905,8 +893,8 @@ namespace chaiscript
in_quote = !in_quote;
} else if (*m_position == '}' && !in_quote) {
--in_interpolation;
}
}
if (prev_char == '\\') {
prev_char = 0;
} else {
@@ -1196,7 +1184,7 @@ namespace chaiscript
std::string match;
{
// scope for cparser destructor
// scope for cparser destrutor
Char_Parser<std::string> cparser(match, false);
for (auto s = start + 1, end = m_position - 1; s != end; ++s) {
@@ -1204,10 +1192,6 @@ namespace chaiscript
}
}
if (match.size() != 1) {
throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename);
}
m_match_stack.push_back(make_node<eval::Single_Quoted_String_AST_Node>(match, start.line, start.col));
return true;
}

View File

@@ -1,7 +1,7 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and 2009-2016, Jason Turner (jason@emptycrate.com)
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_
@@ -9,7 +9,7 @@
namespace chaiscript {
struct ChaiScript_Prelude {
static std::string chaiscript_prelude() { return R"chaiscript(
static std::string chaiscript_prelude() { return R""(
def lt(l, r) {
if (call_exists(`<`, l, r)) {
@@ -215,29 +215,6 @@ def for_each(container, func) : call_exists(range, container) {
}
}
def any_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (func(t_range.front())) {
return true;
}
t_range.pop_front();
}
false;
}
def all_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (!func(t_range.front())) {
return false;
}
t_range.pop_front();
}
true;
}
def back_inserter(container) {
bind(push_back, container, _);
}
@@ -553,7 +530,7 @@ def find(container, value) {
}
)chaiscript";
)"";
}
};

View File

@@ -505,7 +505,7 @@ class Function
/// \endcode
Vector get_contained_functions() const;
/// \brief Returns a function guard as function
/// \brief Returns a vector of the contained functions
///
/// Example:
/// \code

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ namespace chaiscript
{
std::map<std::string, Boxed_Value> m;
for (const auto &p : t_json.object_range())
for (const auto &p : t_json.ObjectRange())
{
m.insert(std::make_pair(p.first, from_json(p.second)));
}
@@ -41,7 +41,7 @@ namespace chaiscript
{
std::vector<Boxed_Value> vec;
for (const auto &p : t_json.array_range())
for (const auto &p : t_json.ArrayRange())
{
vec.emplace_back(from_json(p));
}
@@ -49,13 +49,13 @@ namespace chaiscript
return Boxed_Value(vec);
}
case json::JSON::Class::String:
return Boxed_Value(t_json.to_string());
return Boxed_Value(t_json.ToString());
case json::JSON::Class::Floating:
return Boxed_Value(t_json.to_float());
return Boxed_Value(t_json.ToFloat());
case json::JSON::Class::Integral:
return Boxed_Value(t_json.to_int());
return Boxed_Value(t_json.ToInt());
case json::JSON::Class::Boolean:
return Boxed_Value(t_json.to_bool());
return Boxed_Value(t_json.ToBool());
}
throw std::runtime_error("Unknown JSON type");
@@ -102,24 +102,32 @@ namespace chaiscript
try {
Boxed_Number bn(t_bv);
json::JSON obj;
if (Boxed_Number::is_floating_point(t_bv))
{
return json::JSON(bn.get_as<double>());
obj = bn.get_as<double>();
} else {
return json::JSON(bn.get_as<long>());
obj = bn.get_as<long>();
}
return obj;
} catch (const chaiscript::detail::exception::bad_any_cast &) {
// not a number
}
try {
return json::JSON(boxed_cast<bool>(t_bv));
bool b = boxed_cast<bool>(t_bv);
json::JSON obj;
obj = b;
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a bool
}
try {
return json::JSON(boxed_cast<std::string>(t_bv));
std::string s = boxed_cast<std::string>(t_bv);
json::JSON obj;
obj = s;
return obj;
} catch (const chaiscript::exception::bad_boxed_cast &) {
// not a string
}

View File

@@ -69,7 +69,11 @@ namespace chaiscript
typename std::enable_if<std::is_enum<Enum>::value, void>::type
add_class(ModuleType &t_module,
const std::string &t_class_name,
#ifdef CHAISCRIPT_GCC_4_6
const std::vector<std::pair<int, std::string>> &t_constants
#else
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants
#endif
)
{
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
@@ -83,8 +87,13 @@ namespace chaiscript
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
}());
#ifdef CHAISCRIPT_GCC_4_6
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; }), "==");
#else
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
#endif
for (const auto &constant : t_constants)
{

View File

@@ -1,8 +1,3 @@
<a href="https://www.patreon.com/bePatron?u=2977989&redirect_uri=https%3A%2F%2Fwww.patreon.com%2Flefticus">
<img height="40" width="204" src="https://s3-us-west-1.amazonaws.com/widget-images/become-patron-widget-medium%402x.png">
</a>
Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=master)](http://codecov.io/github/ChaiScript/ChaiScript?branch=master)
Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=develop)](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop)

View File

@@ -44,14 +44,14 @@ class ChaiScriptDerived : public BaseClass
tie(t_funcs.at(1), m_validateValueImpl);
}
std::string doSomething(float f, double d) const override
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
{
assert(m_doSomethingImpl);
return m_doSomethingImpl(*this, f, d);
}
protected:
bool validateValue(const std::string &t_val) override
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
{
assert(m_validateValueImpl);
return m_validateValueImpl(*this, t_val);

View File

@@ -371,9 +371,6 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
}
catch (const chaiscript::exception::load_module_error &e) {
std::cout << "Unhandled module load error\n" << e.what() << '\n';
}
// catch (std::exception &e) {
// std::cout << e.what() << '\n';

View File

@@ -8,10 +8,18 @@
class TestBaseType
{
public:
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(push)
#pragma warning(disable : 4351)
#endif
// MSVC 12 warns that we are using new (correct) behavior
TestBaseType() : val(10), const_val(15), mdarray{} { }
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
#ifdef CHAISCRIPT_MSVC_12
#pragma warning(pop)
#endif
TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {}
virtual int func() { return 0; }
@@ -22,11 +30,6 @@ class TestBaseType
int val;
const int const_val;
const int *const_val_ptr = &const_val;
const int *get_const_val_ptr() {
return const_val_ptr;
}
int mdarray[2][3][5];
std::function<int (int)> func_member;
@@ -81,7 +84,7 @@ class TestDerivedType : public TestBaseType
virtual ~TestDerivedType() {}
TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default;
virtual int func() override { return 1; }
virtual int func() CHAISCRIPT_OVERRIDE { return 1; }
int derived_only_func() { return 19; }
private:
@@ -183,15 +186,19 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&TestBaseType::func), "func");
m->add(chaiscript::fun(&TestBaseType::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
m->add(chaiscript::fun(&TestBaseType::const_val_ptr), "const_val_ptr");
m->add(chaiscript::fun(&TestBaseType::get_const_val_ptr), "get_const_val_ptr");
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
#ifndef CHAISCRIPT_MSVC_12
// we cannot support these in MSVC_12 because of a bug in the implementation of
// std::reference_wrapper
// Array types
m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray");
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"));
// end array types
#endif
// member that is a function
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");

View File

@@ -1 +0,0 @@

View File

@@ -206,7 +206,7 @@ bool built_in_type_test(const T &initial, bool ispod)
/** shared_ptr tests **/
auto ip = std::make_shared<T>(initial);
std::shared_ptr<T> ip(new T(initial));
passed &= do_test<T>(var(ip), true, true, true, true, true,
true, true, true, true, true,
@@ -221,7 +221,7 @@ bool built_in_type_test(const T &initial, bool ispod)
ispod, ispod, ispod, false, true);
/** const shared_ptr tests **/
auto ipc = std::make_shared<const T>(T(initial));
std::shared_ptr<const T> ipc(new T(initial));
passed &= do_test<T>(var(ipc), true, true, false, true, false,
true, false, true, false, true,

View File

@@ -1,26 +0,0 @@
class MyClass
{
def MyClass()
{
this.x = 2;
}
var x;
}
var o = MyClass();
var o2 = MyClass();
o2.x = 5;
o = o2;
assert_true(o.x == 5)
assert_true(o == o2)
o2.x = 3;
print(o2.x);
print(o.x);
assert_true(o != o2)

View File

@@ -8,6 +8,4 @@ assert_equal(13, t0.val)
assert_equal(15, t0.constMe().const_val)
assert_equal(13, t0.constMe().val)
assert_equal(15, t0.get_const_val_ptr())
assert_equal(15, t0.const_val_ptr)