Compare commits
38 Commits
Release-5.
...
v4.1.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f24d376fa5 | ||
![]() |
7917ea02dc | ||
![]() |
deef33640c | ||
![]() |
58f3256389 | ||
![]() |
f1a4c4c427 | ||
![]() |
afd27a4b01 | ||
![]() |
4c65e45598 | ||
![]() |
923369a4f4 | ||
![]() |
964342bff3 | ||
![]() |
623c64299a | ||
![]() |
9832d1ce39 | ||
![]() |
ed7bdfb172 | ||
![]() |
204ab53afc | ||
![]() |
8f7226051e | ||
![]() |
46d1c50923 | ||
![]() |
9e3c2960aa | ||
![]() |
9fd4a1b9f5 | ||
![]() |
441cdf0935 | ||
![]() |
f0016d978a | ||
![]() |
1155720b14 | ||
![]() |
f5b7be3743 | ||
![]() |
d8f881239f | ||
![]() |
0a436398dd | ||
![]() |
9f309fcbe9 | ||
![]() |
4e33e969dc | ||
![]() |
08d9d9e28e | ||
![]() |
935276fccd | ||
![]() |
f8feaf6ea8 | ||
![]() |
dfcc415c31 | ||
![]() |
927235d871 | ||
![]() |
bf4f90a4ff | ||
![]() |
45f07f9924 | ||
![]() |
39d817469c | ||
![]() |
7a25625fdd | ||
![]() |
5e6a51ba63 | ||
![]() |
a8ea5f151d | ||
![]() |
5a76d98692 | ||
![]() |
3bccf4d977 |
128
CMakeLists.txt
128
CMakeLists.txt
@@ -13,22 +13,24 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES ".swp")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*~")
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.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 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 4)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 1)
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||
set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An embedded scripting language for C++")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libboost-dev (>=1.36.0)")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "BSD")
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Programming")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "boost-devel >= 1.36.0, boost-thread >= 1.36.0")
|
||||
|
||||
set(CHAI_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
|
||||
|
||||
@@ -59,75 +61,79 @@ if(MSVC)
|
||||
add_definitions(/bigobj)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic)
|
||||
|
||||
if (APPLE)
|
||||
add_definitions(-Wno-sign-compare)
|
||||
# -Wno-missing-field-initializers is for boost on macos
|
||||
add_definitions(-Wno-missing-field-initializers -Wno-sign-compare)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER MATCHES ".*clang")
|
||||
|
||||
option(USE_LIBCXX "Use clang's libcxx" TRUE)
|
||||
|
||||
if (USE_LIBCXX)
|
||||
add_definitions(-stdlib=libc++)
|
||||
set (EXTRA_LINKER_FLAGS -std=c++0x -stdlib=libc++)
|
||||
else ()
|
||||
set (EXTRA_LINKER_FLAGS -std=c++0x )
|
||||
endif()
|
||||
else()
|
||||
set (EXTRA_LINKER_FLAGS )
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
|
||||
set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.43" "1.43.0" "1.42" "1.42.0" "1.41")
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
|
||||
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/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
find_package(Boost 1.36.0 COMPONENTS thread system)
|
||||
|
||||
if (Boost_FOUND)
|
||||
link_directories( ${Boost_LIBRARY_DIRS} )
|
||||
else()
|
||||
message(FATAL_ERROR "Can not find Boost")
|
||||
endif(Boost_FOUND)
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
add_definitions(-pthread)
|
||||
list(APPEND LIBS "pthread")
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
set(DYNAMIC_LOADER "dl")
|
||||
list(APPEND LIBS "dl")
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
|
||||
list(APPEND LIBS ${READLINE_LIB})
|
||||
|
||||
set(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
|
||||
if (NOT MSVC)
|
||||
# Boost on MSVC does automatic linking
|
||||
list(APPEND LIBS ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_2005)
|
||||
# vs2005 is a bit too loud about possible loss of data warnings
|
||||
# ADD_DEFINITIONS(/wd4244)
|
||||
endif()
|
||||
|
||||
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
|
||||
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${Boost_INCLUDE_DIR})
|
||||
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
||||
target_link_libraries(chai ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_dependencies(chai chaiscript_stdlib)
|
||||
target_link_libraries(chai ${LIBS})
|
||||
|
||||
if (BUILD_SAMPLES)
|
||||
add_executable(example samples/example.cpp)
|
||||
target_link_libraries(example ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(example ${LIBS})
|
||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||
target_link_libraries(memory_leak_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
if (BUILD_MODULES)
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(stl_extra ${LIBS})
|
||||
|
||||
add_library(reflection MODULE src/reflection.cpp)
|
||||
target_link_libraries(reflection ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(reflection ${LIBS})
|
||||
set(MODULES stl_extra reflection)
|
||||
endif()
|
||||
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai)
|
||||
|
||||
list(SORT UNIT_TESTS)
|
||||
|
||||
@@ -147,57 +153,85 @@ if(BUILD_TESTING)
|
||||
|
||||
if (NOT UNIT_TEST_LIGHT)
|
||||
add_executable(utility_test unittests/utility_test.cpp)
|
||||
target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(utility_test ${LIBS})
|
||||
add_test(NAME Utility_Test COMMAND utility_test)
|
||||
|
||||
add_executable(dynamic_object_test unittests/dynamic_object_test.cpp)
|
||||
target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(dynamic_object_test ${LIBS})
|
||||
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
|
||||
|
||||
add_executable(functor_creation_test unittests/functor_creation_test.cpp)
|
||||
target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(functor_creation_test ${LIBS})
|
||||
add_test(NAME Functor_Creation_Test COMMAND functor_creation_test)
|
||||
|
||||
add_executable(functor_cast_test unittests/functor_cast_test.cpp)
|
||||
target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(functor_cast_test ${LIBS})
|
||||
add_test(NAME Functor_Cast_Test COMMAND functor_cast_test)
|
||||
|
||||
add_executable(boxed_cast_test unittests/boxed_cast_test.cpp)
|
||||
target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(boxed_cast_test ${LIBS})
|
||||
add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test)
|
||||
|
||||
add_executable(object_lifetime_test unittests/object_lifetime_test.cpp)
|
||||
target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(object_lifetime_test ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
|
||||
|
||||
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
|
||||
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(function_ordering_test ${LIBS})
|
||||
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
|
||||
|
||||
add_executable(type_info_test unittests/type_info_test.cpp)
|
||||
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(type_info_test ${LIBS})
|
||||
add_test(NAME Type_Info_Test COMMAND type_info_test)
|
||||
|
||||
add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp)
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS})
|
||||
add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test)
|
||||
|
||||
add_executable(short_comparison_test unittests/short_comparison_test.cpp)
|
||||
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(short_comparison_test ${LIBS})
|
||||
add_test(NAME Short_Comparison_Test COMMAND short_comparison_test)
|
||||
|
||||
add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp)
|
||||
target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_test(NAME cpp_lambda_test COMMAND cpp_lambda_test)
|
||||
add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp)
|
||||
target_link_libraries(expected_eval_errors_test ${LIBS})
|
||||
add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test)
|
||||
|
||||
add_executable(set_state_test unittests/set_state_test.cpp)
|
||||
target_link_libraries(set_state_test ${LIBS})
|
||||
add_test(NAME Set_State_Test COMMAND set_state_test)
|
||||
|
||||
add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp)
|
||||
target_link_libraries(simultaneous_chaiscript_test ${LIBS})
|
||||
add_test(NAME Simultaneous_Chaiscript_Test COMMAND simultaneous_chaiscript_test)
|
||||
|
||||
add_executable(c_linkage_test unittests/c_linkage_test.cpp)
|
||||
target_link_libraries(c_linkage_test ${LIBS})
|
||||
add_test(NAME C_Linkage_Test COMMAND c_linkage_test)
|
||||
|
||||
add_executable(integer_literal_test unittests/integer_literal_test.cpp)
|
||||
target_link_libraries(integer_literal_test ${LIBS})
|
||||
add_test(NAME Integer_Literal_Test COMMAND integer_literal_test)
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
add_executable(multithreaded_test unittests/multithreaded_test.cpp)
|
||||
target_link_libraries(multithreaded_test ${LIBS})
|
||||
add_test(NAME Multithreaded_Test COMMAND multithreaded_test)
|
||||
set_property(TEST Multithreaded_Test
|
||||
PROPERTY ENVIRONMENT
|
||||
"CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/"
|
||||
"CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/"
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp
|
||||
unittests/multifile_test_module.cpp)
|
||||
target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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} ${EXTRA_LINKER_FLAGS})
|
||||
target_link_libraries(test_module ${LIBS})
|
||||
|
||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
endif()
|
||||
|
@@ -50,7 +50,7 @@ function run_test
|
||||
# Run multithreaded tests
|
||||
echo "****Building multithreaded test"
|
||||
pushd src
|
||||
g++ multithreaded.cpp -ldl -omultithreaded -I../include -O3
|
||||
g++ multithreaded.cpp -lboost_thread-mt -ldl -omultithreaded -I../include -O3
|
||||
echo "****Testing 1 thread runtime"
|
||||
/usr/bin/time -p ./multithreaded 1 2> ../../r$1-1threadruntime.out
|
||||
echo "****Testing 2 thread runtime"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
def isprime(n)
|
||||
{
|
||||
for (auto i = 2; i < n; ++i)
|
||||
for (var i = 2; i < n; ++i)
|
||||
{
|
||||
if (n % i == 0) {return false}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ def isprime(n)
|
||||
|
||||
def primes(n)
|
||||
{
|
||||
auto count = 0
|
||||
for (auto i = 2; i <= n; ++i)
|
||||
var count = 0
|
||||
for (var i = 2; i <= n; ++i)
|
||||
{
|
||||
if (isprime(i)) {++count}
|
||||
}
|
||||
@@ -21,6 +21,5 @@ def primes(n)
|
||||
}
|
||||
|
||||
|
||||
auto N = 5000
|
||||
|
||||
var N = 5000
|
||||
print("primes: " + primes(N).to_string())
|
||||
|
@@ -51,7 +51,7 @@ $language_data = array (
|
||||
'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally', 'case', 'switch', 'default',
|
||||
),
|
||||
2 => array(
|
||||
'def', 'false', 'fun', 'true', 'var', 'auto', 'attr',
|
||||
'def', 'false', 'fun', 'true', 'var', 'attr',
|
||||
),
|
||||
3 => array(
|
||||
// built in functions
|
||||
|
@@ -52,7 +52,7 @@ syn keyword chaiscriptExceptions try catch throw
|
||||
syn keyword chaiscriptKeyword def true false attr
|
||||
|
||||
"Built in types
|
||||
syn keyword chaiscriptType fun var auto
|
||||
syn keyword chaiscriptType fun var
|
||||
|
||||
"Built in funcs, keep it simple
|
||||
syn keyword chaiscriptFunc eval throw
|
||||
|
@@ -74,16 +74,16 @@
|
||||
/// <hr>
|
||||
/// \subsection compiling Compiling ChaiScript Applications
|
||||
///
|
||||
/// ChaiScript is a header only library with only one dependecy: The
|
||||
/// ChaiScript is a header only library with only two dependecies. boost::threads (optional) and the
|
||||
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
||||
///
|
||||
/// \subsubsection compilinggcc Compiling with GCC
|
||||
///
|
||||
/// To compile the above application on a Unix like operating system (MacOS, Linux) with GCC you need to link
|
||||
/// the dynamic loader. For example:
|
||||
/// both boost::threads and the dynamic loader. For example:
|
||||
///
|
||||
/// \code
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -lboost_threads
|
||||
/// \endcode
|
||||
///
|
||||
/// Alternatively, you may compile without threading support.
|
||||
@@ -140,7 +140,10 @@
|
||||
///
|
||||
/// \subsubsection addingobjects Adding Objects
|
||||
///
|
||||
/// Named objects can be created with the chaiscript::var function.
|
||||
/// Named objects can be created with the chaiscript::var function. Note: adding a object
|
||||
/// adds it to the current thread scope, not to a global scope. If you have multiple
|
||||
/// threads that need to access the same variables you will need to add them
|
||||
/// separately for each thread, from the thread itself.
|
||||
///
|
||||
/// \code
|
||||
/// using namespace chaiscript;
|
||||
@@ -245,9 +248,7 @@
|
||||
///
|
||||
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
|
||||
/// {
|
||||
/// std::stringstream ss;
|
||||
/// ss << t_lhs << t_rhs;
|
||||
/// return ss.str();
|
||||
/// return t_lhs + boost::lexical_cast<std::string>(t_rhs);
|
||||
/// }
|
||||
///
|
||||
/// chai.add(fun(append_string_int), "+");
|
||||
@@ -299,8 +300,8 @@
|
||||
/// <hr>
|
||||
/// \subsection pointerconversions Pointer / Object Conversions
|
||||
///
|
||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
||||
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
|
||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, boost::shared_ptr<T>,
|
||||
/// boost::shared_ptr<const T>, boost::reference_wrapper<T>, boost::reference_wrapper<const T> and value types automatically.
|
||||
///
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
|
||||
/// Const may be added, but never removed.
|
||||
@@ -313,12 +314,12 @@
|
||||
/// void fun3(int);
|
||||
/// void fun4(int &);
|
||||
/// void fun5(const int &);
|
||||
/// void fun5(std::shared_ptr<int>);
|
||||
/// void fun6(std::shared_ptr<const int>);
|
||||
/// void fun7(const std::shared_ptr<int> &);
|
||||
/// void fun8(const std::shared_ptr<const int> &);
|
||||
/// void fun9(std::reference_wrapper<int>);
|
||||
/// void fun10(std::reference_wrapper<const int>);
|
||||
/// void fun5(boost::shared_ptr<int>);
|
||||
/// void fun6(boost::shared_ptr<const int>);
|
||||
/// void fun7(const boost::shared_ptr<int> &);
|
||||
/// void fun8(const boost::shared_ptr<const int> &);
|
||||
/// void fun9(boost::reference_wrapper<int>);
|
||||
/// void fun10(boost::reference_wrapper<const int>);
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
@@ -379,10 +380,10 @@
|
||||
/// \subsection functionobjects Function Objects
|
||||
///
|
||||
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
|
||||
/// between ChaiScript functions and std::function objects.
|
||||
/// between ChaiScript functions and boost::function objects.
|
||||
///
|
||||
/// \code
|
||||
/// void callafunc(const std::function<void (const std::string &)> &t_func)
|
||||
/// void callafunc(const boost::function<void (const std::string &)> &t_func)
|
||||
/// {
|
||||
/// t_func("bob");
|
||||
/// }
|
||||
@@ -392,9 +393,9 @@
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::fun(&callafunc), "callafunc");
|
||||
/// chai("callafunc(fun(x) { print(x); })"); // pass a lambda function to the registered function
|
||||
/// // which expects a typed std::function
|
||||
/// // which expects a typed boost::function
|
||||
///
|
||||
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
|
||||
/// boost::function<void ()> f = chai.eval<boost::function<void ()> >("dump_system");
|
||||
/// f(); // call the ChaiScript function dump_system, from C++
|
||||
/// }
|
||||
/// \endcode
|
||||
@@ -409,7 +410,7 @@
|
||||
///
|
||||
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
|
||||
///
|
||||
/// Disabling thread safety increases performance in many cases.
|
||||
/// Disabling thread safety increases performance and removes the requirement for boost_threads.
|
||||
///
|
||||
/// <hr>
|
||||
///
|
||||
@@ -745,16 +746,20 @@
|
||||
/// \namespace chaiscript::detail
|
||||
/// \brief Classes and functions reserved for internal use. Items in this namespace are not supported.
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
|
||||
#include "dispatchkit/dispatchkit.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
#include "dispatchkit/function_call.hpp"
|
||||
#include "dispatchkit/dynamic_object.hpp"
|
||||
#include "dispatchkit/boxed_number.hpp"
|
||||
|
||||
#ifdef BOOST_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
#include "language/chaiscript_eval.hpp"
|
||||
#include "language/chaiscript_engine.hpp"
|
||||
|
||||
|
||||
|
||||
#endif /* CHAISCRIPT_HPP_ */
|
||||
|
@@ -1,28 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DEFINES_HPP_
|
||||
#define CHAISCRIPT_DEFINES_HPP_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CHAISCRIPT_MSVC _MSC_VER
|
||||
#define CHAISCRIPT_HAS_DECLSPEc
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CHAISCRIPT_WINDOWS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_HAS_DECLSPEC
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define CHAISCRIPT_MODULE_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,44 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_STDLIB_HPP_
|
||||
#define CHAISCRIPT_STDLIB_HPP_
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
#include "dispatchkit/bootstrap.hpp"
|
||||
#include "dispatchkit/bootstrap_stl.hpp"
|
||||
|
||||
/// \file
|
||||
///
|
||||
/// This file generates the standard library that normal ChaiScript usage requires.
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Std_Lib
|
||||
{
|
||||
public:
|
||||
|
||||
static ModulePtr library()
|
||||
{
|
||||
using namespace bootstrap;
|
||||
|
||||
ModulePtr lib = Bootstrap::bootstrap();
|
||||
|
||||
lib->add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
lib->add(standard_library::string_type<std::string>("string"));
|
||||
lib->add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
lib->add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -8,8 +8,7 @@
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <boost/thread.hpp>
|
||||
#else
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
@@ -26,81 +25,48 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// If threading is enabled, then this namespace contains std thread classes.
|
||||
/// If threading is enabled, then this namespace contains boost::thread classes.
|
||||
/// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
|
||||
/// This allows us to avoid \#ifdef code in the sections that need thread safety.
|
||||
namespace threading
|
||||
{
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
|
||||
template<typename T>
|
||||
class unique_lock : public std::unique_lock<T>
|
||||
{
|
||||
public:
|
||||
unique_lock(T &t) : std::unique_lock<T>(t) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class shared_lock : public std::unique_lock<T>
|
||||
{
|
||||
public:
|
||||
shared_lock(T &t) : std::unique_lock<T>(t) {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class lock_guard : public std::lock_guard<T>
|
||||
{
|
||||
public:
|
||||
lock_guard(T &t) : std::lock_guard<T>(t) {}
|
||||
};
|
||||
|
||||
class shared_mutex : public std::mutex { };
|
||||
|
||||
using std::mutex;
|
||||
|
||||
using std::recursive_mutex;
|
||||
using boost::unique_lock;
|
||||
using boost::shared_lock;
|
||||
using boost::lock_guard;
|
||||
using boost::shared_mutex;
|
||||
using boost::recursive_mutex;
|
||||
|
||||
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
///
|
||||
/// \todo move to thread_local when it exists
|
||||
template<typename T>
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
~Thread_Storage()
|
||||
{
|
||||
m_thread_storage.reset();
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
{
|
||||
return get_tls().get();
|
||||
if (!m_thread_storage.get())
|
||||
{
|
||||
m_thread_storage.reset(new T());
|
||||
}
|
||||
|
||||
return m_thread_storage.get();
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
{
|
||||
return *get_tls();
|
||||
return *(this->operator->());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<T> get_tls() const
|
||||
{
|
||||
unique_lock<mutex> lock(m_mutex);
|
||||
|
||||
auto itr = m_instances.find(std::this_thread::get_id());
|
||||
|
||||
if (itr != m_instances.end()) { return itr->second; }
|
||||
|
||||
std::shared_ptr<T> new_instance(new T());
|
||||
|
||||
m_instances.insert(std::make_pair(std::this_thread::get_id(), new_instance));
|
||||
|
||||
return new_instance;
|
||||
}
|
||||
|
||||
mutable mutex m_mutex;
|
||||
mutable std::map<std::thread::id, std::shared_ptr<T> > m_instances;
|
||||
mutable boost::thread_specific_ptr<T> m_thread_storage;
|
||||
};
|
||||
|
||||
#else
|
||||
|
@@ -1,162 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_ANY_HPP_
|
||||
#define CHAISCRIPT_ANY_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
namespace detail {
|
||||
namespace exception
|
||||
{
|
||||
/// \brief Thrown in the event that an Any cannot be cast to the desired type
|
||||
///
|
||||
/// It is used internally during function dispatch.
|
||||
///
|
||||
/// \sa chaiscript::detail::Any
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_any_cast() noexcept
|
||||
: m_what("bad any cast")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_any_cast() noexcept {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
virtual const char * what() const noexcept
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_what;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class Any {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
virtual void *data() = 0;
|
||||
virtual const std::type_info &type() const = 0;
|
||||
virtual std::shared_ptr<Data> clone() const = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
Data_Impl(const T &t_type)
|
||||
: m_type(typeid(T)),
|
||||
m_data(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void *data()
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::shared_ptr<Data> clone() const
|
||||
{
|
||||
return std::shared_ptr<Data>(new Data_Impl<T>(m_data));
|
||||
}
|
||||
|
||||
const std::type_info &m_type;
|
||||
T m_data;
|
||||
};
|
||||
|
||||
std::shared_ptr<Data> m_data;
|
||||
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
Any() = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
{
|
||||
if (!t_any.empty())
|
||||
{
|
||||
m_data = t_any.m_data->clone();
|
||||
} else {
|
||||
m_data.reset();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any(const ValueType &t_value)
|
||||
{
|
||||
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
|
||||
}
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
{
|
||||
Any copy(t_any);
|
||||
swap(copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any & operator=(const ValueType &t_value)
|
||||
{
|
||||
m_data = std::shared_ptr<Data>(new Data_Impl<ValueType>(t_value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ToType>
|
||||
ToType &cast() const
|
||||
{
|
||||
if (m_data && typeid(ToType) == m_data->type())
|
||||
{
|
||||
return *static_cast<ToType *>(m_data->data());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
~Any()
|
||||
{
|
||||
}
|
||||
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
std::shared_ptr<Data> data = t_other.m_data;
|
||||
t_other.m_data = m_data;
|
||||
m_data = data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// queries
|
||||
bool empty() const
|
||||
{
|
||||
return !bool(m_data);
|
||||
}
|
||||
|
||||
const std::type_info & type() const
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
return m_data->type();
|
||||
} else {
|
||||
return typeid(void);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -22,25 +22,25 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) noexcept
|
||||
const std::string &t_what) throw()
|
||||
: from(t_from), to(&t_to), m_what(t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const std::string &t_what) noexcept
|
||||
bad_boxed_cast(const std::string &t_what) throw()
|
||||
: to(0), m_what(t_what)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_cast() noexcept {}
|
||||
virtual ~bad_boxed_cast() throw() {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
virtual const char * what() const noexcept
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
@@ -4,130 +4,91 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <boost/preprocessor/arithmetic/inc.hpp>
|
||||
|
||||
#define param(z,n,text) BOOST_PP_CAT(text, BOOST_PP_INC(n))
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef CHAISCRIPT_BIND_FIRST_HPP_
|
||||
#define CHAISCRIPT_BIND_FIRST_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 8 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/bind_first.hpp>
|
||||
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
# define m BOOST_PP_INC(n)
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<int>
|
||||
struct Placeholder
|
||||
{
|
||||
/// \brief Helper function for binding the first parameter of a class method pointer. Used in chaiscript::fun overloads
|
||||
/// that take 1 or 2 parameters to pre-bind to the function.
|
||||
///
|
||||
/// \param[in] f method pointer to bind
|
||||
/// \param[in] o object to bind as first parameter
|
||||
/// \returns a new boost::function object with one fewer parameters than the function passed in.
|
||||
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
|
||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const O &o)
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<1>
|
||||
{
|
||||
static decltype(std::placeholders::_1) value() { return std::placeholders::_1; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<2>
|
||||
{
|
||||
static decltype(std::placeholders::_2) value() { return std::placeholders::_2; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<3>
|
||||
{
|
||||
static decltype(std::placeholders::_3) value() { return std::placeholders::_3; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<4>
|
||||
{
|
||||
static decltype(std::placeholders::_4) value() { return std::placeholders::_4; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<5>
|
||||
{
|
||||
static decltype(std::placeholders::_5) value() { return std::placeholders::_5; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<6>
|
||||
{
|
||||
static decltype(std::placeholders::_6) value() { return std::placeholders::_6; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<7>
|
||||
{
|
||||
static decltype(std::placeholders::_7) value() { return std::placeholders::_7; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<8>
|
||||
{
|
||||
static decltype(std::placeholders::_8) value() { return std::placeholders::_8; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<9>
|
||||
{
|
||||
static decltype(std::placeholders::_9) value() { return std::placeholders::_9; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<10>
|
||||
{
|
||||
static decltype(std::placeholders::_10) value() { return std::placeholders::_10; }
|
||||
};
|
||||
|
||||
|
||||
template<int count, int maxcount, typename Sig>
|
||||
struct Bind_First
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., Placeholder<maxcount - count + 1>::value());
|
||||
}
|
||||
};
|
||||
|
||||
template<int maxcount, typename Sig>
|
||||
struct Bind_First<0, maxcount, Sig>
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return std::bind(f, innerparams...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
|
||||
/// \brief Helper function for binding the first parameter of a const class method pointer. Used in chaiscript::fun overloads
|
||||
/// that take 1 or 2 parameters to pre-bind to the function.
|
||||
///
|
||||
/// \param[in] f method pointer to bind
|
||||
/// \param[in] o object to bind as first parameter
|
||||
/// \returns a new boost::function object with one fewer parameters than the function passed in.
|
||||
template<typename Ret, typename O, typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))>
|
||||
bind_first(Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)) const, const O &o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
|
||||
/// \brief Helper function for binding the first parameter of a function pointer. Used in chaiscript::fun overloads
|
||||
/// that take 1 or 2 parameters to pre-bind to the function.
|
||||
///
|
||||
/// \param[in] f method pointer to bind
|
||||
/// \param[in] o object to bind as first parameter
|
||||
/// \returns a new boost::function object with one fewer parameters than the function passed in.
|
||||
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
|
||||
bind_first(Ret (*f)(BOOST_PP_ENUM_PARAMS(m, Param)), const O &o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
|
||||
/// \brief Helper function for binding the first parameter of a boost::function object. Used in chaiscript::fun overloads
|
||||
/// that take 1 or 2 parameters to pre-bind to the function.
|
||||
///
|
||||
/// \param[in] f method pointer to bind
|
||||
/// \param[in] o object to bind as first parameter
|
||||
/// \returns a new boost::function object with one fewer parameters than the function passed in.
|
||||
template<typename Ret,typename O BOOST_PP_COMMA_IF(m) BOOST_PP_ENUM_PARAMS(m, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM(n, param, Param))>
|
||||
bind_first(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(m, Param))> &f, const O &o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef n
|
||||
#undef m
|
||||
#undef param
|
||||
|
||||
#endif
|
||||
|
@@ -12,8 +12,8 @@
|
||||
#include "register_function.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -26,9 +26,9 @@ namespace chaiscript
|
||||
/// \param[in] v Boxed_Number to copy into the new object
|
||||
/// \returns The newly created object.
|
||||
template<typename P1>
|
||||
std::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
boost::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
{
|
||||
std::shared_ptr<P1> p(new P1());
|
||||
boost::shared_ptr<P1> p(new P1());
|
||||
Boxed_Value bv(p);
|
||||
Boxed_Number nb(bv);
|
||||
nb = v;
|
||||
@@ -97,25 +97,29 @@ namespace chaiscript
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
template<typename Input>
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
return ss.str();
|
||||
}
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << i;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function for converting from a string to a value
|
||||
* uses ostream operator >> to perform the conversion
|
||||
*/
|
||||
template<typename Input>
|
||||
Input parse_string(const std::string &i)
|
||||
{
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
return t;
|
||||
}
|
||||
Input parse_string(const std::string &i)
|
||||
{
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -143,7 +147,7 @@ namespace chaiscript
|
||||
* function variables.
|
||||
*/
|
||||
template<typename Type>
|
||||
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||
boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
@@ -152,10 +156,10 @@ namespace chaiscript
|
||||
* Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
*/
|
||||
template<typename Type>
|
||||
std::shared_ptr<typename std::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
||||
boost::shared_ptr<typename boost::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const boost::shared_ptr<typename boost::add_const<Type>::type> &p)
|
||||
{
|
||||
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
||||
return boost::const_pointer_cast<typename boost::remove_const<Type>::type>(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +170,7 @@ namespace chaiscript
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<Type> &rhs)
|
||||
{
|
||||
if (lhs.is_undef()
|
||||
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
|
||||
@@ -287,10 +291,10 @@ namespace chaiscript
|
||||
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return bool(pf->get_guard());
|
||||
return pf->get_guard();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -298,7 +302,7 @@ namespace chaiscript
|
||||
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_guard())
|
||||
@@ -316,9 +320,7 @@ namespace chaiscript
|
||||
throw bv;
|
||||
}
|
||||
|
||||
static std::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(
|
||||
std::shared_ptr<chaiscript::detail::Dispatch_Engine> e
|
||||
= std::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
|
||||
static boost::shared_ptr<chaiscript::detail::Dispatch_Engine> bootstrap2(boost::shared_ptr<chaiscript::detail::Dispatch_Engine> e = boost::shared_ptr<chaiscript::detail::Dispatch_Engine> (new chaiscript::detail::Dispatch_Engine()))
|
||||
{
|
||||
e->add(user_type<void>(), "void");
|
||||
return e;
|
||||
@@ -346,22 +348,24 @@ namespace chaiscript
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||
const dispatch::Proxy_Function_Base *b)
|
||||
{
|
||||
auto v = (b->*f)();
|
||||
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
|
||||
Vector v = (b->*f)();
|
||||
|
||||
std::vector<Boxed_Value> vbv;
|
||||
|
||||
for (const auto &o: v)
|
||||
for (typename Vector::const_iterator itr = v.begin();
|
||||
itr != v.end();
|
||||
++itr)
|
||||
{
|
||||
vbv.push_back(const_var(o));
|
||||
vbv.push_back(const_var(*itr));
|
||||
}
|
||||
|
||||
return vbv;
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
|
||||
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -392,7 +396,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
|
||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
@@ -400,7 +404,7 @@ namespace chaiscript
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
|
||||
m->add(fun(&dispatch::Dynamic_Object::get_attr), "get_attr");
|
||||
|
||||
m->eval("def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
|
||||
m->eval("def Dynamic_Object::clone() { var new_o := Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), bind(fun(new_o, x) { new_o.get_attr(x.first) = x.second; }, new_o, _) ); return new_o; }");
|
||||
|
||||
m->add(fun(&has_guard), "has_guard");
|
||||
m->add(fun(&get_guard), "get_guard");
|
||||
@@ -423,6 +427,7 @@ namespace chaiscript
|
||||
m->add(fun(&Type_Info::is_void), "is_type_void");
|
||||
m->add(fun(&Type_Info::is_undef), "is_type_undef");
|
||||
m->add(fun(&Type_Info::is_pointer), "is_type_pointer");
|
||||
m->add(fun(&Type_Info::is_arithmetic), "is_type_arithmetic");
|
||||
m->add(fun(&Type_Info::name), "cpp_name");
|
||||
m->add(fun(&Type_Info::bare_name), "cpp_bare_name");
|
||||
m->add(fun(&Type_Info::bare_equal), "bare_equal");
|
||||
@@ -442,18 +447,19 @@ namespace chaiscript
|
||||
bootstrap_pod_type<long double>("long_double", m);
|
||||
bootstrap_pod_type<float>("float", m);
|
||||
bootstrap_pod_type<int>("int", m);
|
||||
bootstrap_pod_type<long>("long", m);
|
||||
bootstrap_pod_type<unsigned int>("unsigned_int", m);
|
||||
bootstrap_pod_type<unsigned long>("unsigned_long", m);
|
||||
bootstrap_pod_type<size_t>("size_t", m);
|
||||
bootstrap_pod_type<char>("char", m);
|
||||
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
||||
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
||||
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
||||
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
||||
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
||||
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||
bootstrap_pod_type<boost::int8_t>("int8_t", m);
|
||||
bootstrap_pod_type<boost::int16_t>("int16_t", m);
|
||||
bootstrap_pod_type<boost::int32_t>("int32_t", m);
|
||||
bootstrap_pod_type<boost::int64_t>("int64_t", m);
|
||||
bootstrap_pod_type<boost::uint8_t>("uint8_t", m);
|
||||
bootstrap_pod_type<boost::uint16_t>("uint16_t", m);
|
||||
bootstrap_pod_type<boost::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<boost::uint64_t>("uint64_t", m);
|
||||
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
@@ -463,17 +469,17 @@ namespace chaiscript
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
|
||||
"bind");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<boost::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
m->add(fun(&ptr_assign<boost::add_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&call_exists, std::placeholders::_1))),
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
||||
"call_exists");
|
||||
|
||||
m->add(fun(&Boxed_Value::type_match), "type_match");
|
||||
m->add(fun(&type_match), "type_match");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -17,7 +17,6 @@
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bootstrap.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -148,6 +147,103 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
int return_int_impl(const boost::function<typename T::size_type (const T *)> &t_func, const T *t_obj)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
return t_func(t_obj);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const)
|
||||
{
|
||||
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1);
|
||||
}
|
||||
|
||||
template<typename T, typename P1>
|
||||
int return_int_impl(const boost::function<typename T::size_type (const T *, P1)> &t_func, const T *t_obj, P1 p1)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
return t_func(t_obj, p1);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, typename P1>
|
||||
int return_int_impl_non_const(const boost::function<typename T::size_type (T *, P1)> &t_func, T *t_obj, P1 p1)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
return t_func(t_obj, p1);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T, typename P1>
|
||||
boost::function<int (const T *, P1)> return_int(size_t (T::*t_func)(P1) const)
|
||||
{
|
||||
return boost::bind(&return_int_impl<T, P1>, boost::function<size_t (const T *, P1)>(boost::mem_fn(t_func)), _1, _2);
|
||||
}
|
||||
|
||||
template<typename T, typename P1>
|
||||
boost::function<int (T *, P1)> return_int(size_t (T::*t_func)(P1) )
|
||||
{
|
||||
return boost::bind(&return_int_impl_non_const<T, P1>, boost::function<size_t (T*, P1)>(boost::mem_fn(t_func)), _1, _2);
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename P1, typename P2>
|
||||
int return_int_impl(const boost::function<typename T::size_type (const T *, P1, P2)> &t_func, const T *t_obj, P1 p1, P2 p2)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
return t_func(t_obj, p1, p2);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename StringType, StringType (StringType::*Func)(typename StringType::size_type, typename StringType::size_type) const >
|
||||
StringType substr_helper(const StringType &str, int begin, int end)
|
||||
{
|
||||
return (str.*Func)(begin, end);
|
||||
}
|
||||
|
||||
template<typename T, typename P1, typename P2>
|
||||
boost::function<int (const T *, P1, P2)> return_int(size_t (T::*t_func)(P1, P2) const)
|
||||
{
|
||||
return boost::bind(&return_int_impl<T, P1, P2>, boost::function<size_t (const T *, P1, P2)>(boost::mem_fn(t_func)), _1, _2, _3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert(T &t_target, const T &t_other)
|
||||
{
|
||||
t_target.insert(t_other.begin(), t_other.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||
{
|
||||
t_target.insert(t_val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add Bidir_Range support for the given ContainerType
|
||||
@@ -229,11 +325,11 @@ namespace chaiscript
|
||||
//In the interest of runtime safety for the m, we prefer the at() method for [] access,
|
||||
//to throw an exception in an out of bounds condition.
|
||||
m->add(
|
||||
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
fun(boost::function<typename ContainerType::reference (ContainerType *, int)>
|
||||
(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
m->add(
|
||||
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
||||
fun(boost::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
||||
(boost::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -257,9 +353,12 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun( std::function<int (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
|
||||
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
|
||||
boost::function<int (const ContainerType *)> f = detail::return_int(&ContainerType::size);
|
||||
m->add(fun(f), "size");
|
||||
// m->add(fun(boost::function<int (const ContainerType *)>(boost::mem_fn(&ContainerType::size))), "size");
|
||||
m->add(fun<bool (ContainerType::*)() const>(&ContainerType::empty), "empty");
|
||||
m->add(fun<void (ContainerType::*)()>(&ContainerType::clear), "clear");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -391,8 +490,25 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count), "count");
|
||||
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count");
|
||||
|
||||
|
||||
typedef size_t (ContainerType::*erase)(const typename ContainerType::key_type &);
|
||||
erase eraseptr(&ContainerType::erase);
|
||||
|
||||
m->add(fun(boost::function<int (ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(eraseptr))), "erase");
|
||||
|
||||
m->add(fun(&detail::insert<ContainerType>), "insert");
|
||||
|
||||
std::string insert_name;
|
||||
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value))
|
||||
{
|
||||
insert_name = "insert_ref";
|
||||
} else {
|
||||
insert_name = "insert";
|
||||
}
|
||||
|
||||
m->add(fun(&detail::insert_ref<ContainerType>), insert_name);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -465,8 +581,8 @@ namespace chaiscript
|
||||
if ( rhs.size() != this.size() ) { \
|
||||
return false; \
|
||||
} else { \
|
||||
auto r1 = range(this); \
|
||||
auto r2 = range(rhs); \
|
||||
var r1 = range(this); \
|
||||
var r2 = range(rhs); \
|
||||
while (!r1.empty()) \
|
||||
{ \
|
||||
if (!eq(r1.front(), r2.front())) \
|
||||
@@ -512,17 +628,20 @@ namespace chaiscript
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
typedef std::function<int (const String *, const String &, int)> find_func;
|
||||
typedef typename String::size_type (String::*find_func_ptr)(const String &, typename String::size_type) const;
|
||||
typedef boost::function<int (const String *, const String &, int)> find_func;
|
||||
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find(f, pos); } )), "find");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->rfind(f, pos); } ) ), "rfind");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_of(f, pos); } ) ), "find_first_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_of(f, pos); } ) ), "find_last_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of");
|
||||
m->add(fun(find_func( [](const String *s, const String &f, int pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find)))), "find");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::rfind)))), "rfind");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_of)))), "find_first_of");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_of)))), "find_last_of");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_first_not_of)))), "find_first_not_of");
|
||||
m->add(fun(find_func(detail::return_int(static_cast<find_func_ptr>(&String::find_last_not_of)))), "find_last_not_of");
|
||||
|
||||
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->c_str(); } ) ), "c_str");
|
||||
m->add(fun( std::function<const char *(const String *)>( [](const String *s) { return s->data(); } ) ), "data");
|
||||
m->add(fun(&detail::substr_helper<String, &String::substr>), "substr");
|
||||
|
||||
m->add(fun(&String::c_str), "c_str");
|
||||
m->add(fun(&String::data), "data");
|
||||
|
||||
|
||||
return m;
|
||||
|
@@ -7,14 +7,20 @@
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/type_traits/is_polymorphic.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -25,39 +31,39 @@ namespace chaiscript
|
||||
/// \returns Type equivalent to the requested type
|
||||
/// \throws exception::bad_boxed_cast If the requested conversion is not possible
|
||||
///
|
||||
/// boxed_cast will attempt to make conversions between value, &, *, std::shared_ptr, std::reference_wrapper,
|
||||
/// and std::function (const and non-const) where possible. boxed_cast is used internally during function
|
||||
/// boxed_cast will attempt to make conversions between value, &, *, boost::shared_ptr, boost::reference_wrapper,
|
||||
/// and boost::function (const and non-const) where possible. boxed_cast is used internally during function
|
||||
/// dispatch. This means that all of these conversions will be attempted automatically for you during
|
||||
/// ChaiScript function calls.
|
||||
///
|
||||
/// \li non-const values can be extracted as const or non-const
|
||||
/// \li const values can be extracted only as const
|
||||
/// \li Boxed_Value constructed from pointer or std::reference_wrapper can be extracted as reference,
|
||||
/// \li Boxed_Value constructed from pointer or boost::reference_wrapper can be extracted as reference,
|
||||
/// pointer or value types
|
||||
/// \li Boxed_Value constructed from std::shared_ptr or value types can be extracted as reference,
|
||||
/// pointer, value, or std::shared_ptr types
|
||||
/// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference,
|
||||
/// pointer, value, or boost::shared_ptr types
|
||||
///
|
||||
/// Conversions to std::function objects are attempted as well
|
||||
/// Conversions to boost::function objects are attempted as well
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// // All of the following should succeed
|
||||
/// chaiscript::Boxed_Value bv(1);
|
||||
/// std::shared_ptr<int> spi = chaiscript::boxed_cast<std::shared_ptr<int> >(bv);
|
||||
/// boost::shared_ptr<int> spi = chaiscript::boxed_cast<boost::shared_ptr<int> >(bv);
|
||||
/// int i = chaiscript::boxed_cast<int>(bv);
|
||||
/// int *ip = chaiscript::boxed_cast<int *>(bv);
|
||||
/// int &ir = chaiscript::boxed_cast<int &>(bv);
|
||||
/// std::shared_ptr<const int> cspi = chaiscript::boxed_cast<std::shared_ptr<const int> >(bv);
|
||||
/// boost::shared_ptr<const int> cspi = chaiscript::boxed_cast<boost::shared_ptr<const int> >(bv);
|
||||
/// const int ci = chaiscript::boxed_cast<const int>(bv);
|
||||
/// const int *cip = chaiscript::boxed_cast<const int *>(bv);
|
||||
/// const int &cir = chaiscript::boxed_cast<const int &>(bv);
|
||||
/// \endcode
|
||||
///
|
||||
/// std::function conversion example
|
||||
/// boost::function conversion example
|
||||
/// \code
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
|
||||
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
|
||||
/// boost::function<int (int, int)> f = chaiscript::boxed_cast<boost::function<int (int, int)> >(bv);
|
||||
/// int i = f(2,3);
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
@@ -66,23 +72,22 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
} catch (const boost::bad_any_cast &) {
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||
// statment in THIS VERSION of the template instantiation
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
||||
if (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
||||
{
|
||||
try {
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv));
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
} catch (const boost::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
} else {
|
||||
@@ -91,7 +96,7 @@ namespace chaiscript
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
@@ -10,6 +10,10 @@
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -23,7 +27,7 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -31,16 +35,16 @@ namespace chaiscript
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
|
||||
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
||||
} else {
|
||||
return ob.get().cast<std::reference_wrapper<const Result> >();
|
||||
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
|
||||
}
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
} else {
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<const Result> >(ob.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,16 +77,16 @@ namespace chaiscript
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
||||
} else {
|
||||
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
|
||||
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
|
||||
}
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||
} else {
|
||||
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
|
||||
return (boost::any_cast<boost::shared_ptr<const Result> >(ob.get())).get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,9 +104,9 @@ namespace chaiscript
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
||||
} else {
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -113,77 +117,76 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
typedef typename boost::reference_wrapper<Result> Result_Type;
|
||||
|
||||
static Result &cast(const Boxed_Value &ob)
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
return ob.get().cast<std::reference_wrapper<Result> >();
|
||||
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get());
|
||||
} else {
|
||||
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
|
||||
return r;
|
||||
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
* Cast_Helper_Inner for casting to a boost::shared_ptr<> type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<typename boost::shared_ptr<Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
typedef typename boost::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
* Cast_Helper_Inner for casting to a boost::shared_ptr<const> type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<typename boost::shared_ptr<const Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
typedef typename boost::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
|
||||
return boost::const_pointer_cast<const Result>(boost::any_cast<boost::shared_ptr<Result> >(ob.get()));
|
||||
} else {
|
||||
return ob.get().cast<std::shared_ptr<const Result> >();
|
||||
return boost::any_cast<boost::shared_ptr<const Result> >(ob.get());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
* Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<Result> > : Cast_Helper_Inner<boost::shared_ptr<Result> >
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<Result> &> : Cast_Helper_Inner<boost::shared_ptr<Result> >
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
* Cast_Helper_Inner for casting to a const boost::shared_ptr<const> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> > : Cast_Helper_Inner<boost::shared_ptr<const Result> >
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> &> : Cast_Helper_Inner<boost::shared_ptr<const Result> >
|
||||
{
|
||||
};
|
||||
|
||||
@@ -218,35 +221,35 @@ namespace chaiscript
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
* Cast_Helper_Inner for casting to a boost::reference_wrapper type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "../language/chaiscript_algebraic.hpp"
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -46,9 +47,8 @@ namespace chaiscript
|
||||
case Operators::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace chaiscript
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
@@ -114,7 +114,7 @@ namespace chaiscript
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
return t_lhs;
|
||||
}
|
||||
@@ -142,9 +142,8 @@ namespace chaiscript
|
||||
case Operators::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,9 +167,8 @@ namespace chaiscript
|
||||
case Operators::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -191,7 +189,7 @@ namespace chaiscript
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -207,13 +205,13 @@ namespace chaiscript
|
||||
} else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const()) {
|
||||
return binary::go<LHS, RHS>(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
} else if (t_oper > Operators::const_flag) {
|
||||
return const_binary::go<LHS, RHS>(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()), *static_cast<const RHS *>(t_rhs.get_const_ptr()), t_lhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -239,24 +237,24 @@ namespace chaiscript
|
||||
return Go<LHS, long, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return Go<LHS, unsigned long, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return Go<LHS, std::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return Go<LHS, std::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return Go<LHS, std::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return Go<LHS, std::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return Go<LHS, std::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return Go<LHS, std::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return Go<LHS, std::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return Go<LHS, std::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int8_t)) {
|
||||
return Go<LHS, boost::int8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int16_t)) {
|
||||
return Go<LHS, boost::int16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int32_t)) {
|
||||
return Go<LHS, boost::int32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int64_t)) {
|
||||
return Go<LHS, boost::int64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||
return Go<LHS, boost::uint8_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||
return Go<LHS, boost::uint16_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||
return Go<LHS, boost::uint32_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||
return Go<LHS, boost::uint64_t, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,27 +278,40 @@ namespace chaiscript
|
||||
return oper_rhs<long, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return oper_rhs<unsigned long, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
return oper_rhs<std::int8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return oper_rhs<std::int16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return oper_rhs<std::int32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return oper_rhs<std::int64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return oper_rhs<std::uint8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return oper_rhs<std::uint16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return oper_rhs<std::uint32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return oper_rhs<std::uint64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int8_t)) {
|
||||
return oper_rhs<boost::int8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int16_t)) {
|
||||
return oper_rhs<boost::int16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int32_t)) {
|
||||
return oper_rhs<boost::int32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::int64_t)) {
|
||||
return oper_rhs<boost::int64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||
return oper_rhs<boost::uint8_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||
return oper_rhs<boost::uint16_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||
return oper_rhs<boost::uint32_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||
return oper_rhs<boost::uint64_t, false>(t_oper, t_lhs, t_rhs);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Target, typename Source>
|
||||
Target get_as_aux() const
|
||||
{
|
||||
return static_cast<Target>(*static_cast<const Source *>(bv.get_const_ptr()));
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
std::string to_string_aux(const Boxed_Value &v) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << *static_cast<const Source *>(v.get_const_ptr());
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
@@ -315,6 +326,93 @@ namespace chaiscript
|
||||
validate_boxed_number(v);
|
||||
}
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
: bv(Boxed_Value(t))
|
||||
{
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
template<typename Target> Target get_as() const
|
||||
{
|
||||
const Type_Info &inp_ = bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return get_as_aux<Target, int>();
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return get_as_aux<Target, double>();
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return get_as_aux<Target, float>();
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return get_as_aux<Target, long double>();
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return get_as_aux<Target, char>();
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return get_as_aux<Target, unsigned int>();
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return get_as_aux<Target, long>();
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return get_as_aux<Target, unsigned long>();
|
||||
} else if (inp_ == typeid(boost::int8_t)) {
|
||||
return get_as_aux<Target, boost::int8_t>();
|
||||
} else if (inp_ == typeid(boost::int16_t)) {
|
||||
return get_as_aux<Target, boost::int16_t>();
|
||||
} else if (inp_ == typeid(boost::int32_t)) {
|
||||
return get_as_aux<Target, boost::int32_t>();
|
||||
} else if (inp_ == typeid(boost::int64_t)) {
|
||||
return get_as_aux<Target, boost::int64_t>();
|
||||
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||
return get_as_aux<Target, boost::uint8_t>();
|
||||
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||
return get_as_aux<Target, boost::uint16_t>();
|
||||
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||
return get_as_aux<Target, boost::uint32_t>();
|
||||
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||
return get_as_aux<Target, boost::uint64_t>();
|
||||
} else {
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
const Type_Info &inp_ = bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return to_string_aux<int>(bv);
|
||||
} else if (inp_ == typeid(double)) {
|
||||
return to_string_aux<double>(bv);
|
||||
} else if (inp_ == typeid(float)) {
|
||||
return to_string_aux<float>(bv);
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
return to_string_aux<long double>(bv);
|
||||
} else if (inp_ == typeid(char)) {
|
||||
return to_string_aux<int>(Boxed_Value(get_as_aux<int, char>()));
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
return to_string_aux<unsigned int>(bv);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
return to_string_aux<long>(bv);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
return to_string_aux<unsigned long>(bv);
|
||||
} else if (inp_ == typeid(boost::int8_t)) {
|
||||
return to_string_aux<int>(Boxed_Value(get_as_aux<int, boost::int8_t>()));
|
||||
} else if (inp_ == typeid(boost::int16_t)) {
|
||||
return to_string_aux<boost::int16_t>(bv);
|
||||
} else if (inp_ == typeid(boost::int32_t)) {
|
||||
return to_string_aux<boost::int32_t>(bv);
|
||||
} else if (inp_ == typeid(boost::int64_t)) {
|
||||
return to_string_aux<boost::int64_t>(bv);
|
||||
} else if (inp_ == typeid(boost::uint8_t)) {
|
||||
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, boost::uint8_t>()));
|
||||
} else if (inp_ == typeid(boost::uint16_t)) {
|
||||
return to_string_aux<boost::uint16_t>(bv);
|
||||
} else if (inp_ == typeid(boost::uint32_t)) {
|
||||
return to_string_aux<boost::uint32_t>(bv);
|
||||
} else if (inp_ == typeid(boost::uint64_t)) {
|
||||
return to_string_aux<boost::uint64_t>(bv);
|
||||
} else {
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
@@ -386,12 +484,12 @@ namespace chaiscript
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == typeid(bool))
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
|
||||
if (!inp_.is_arithmetic())
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
throw boost::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,15 @@
|
||||
#include "../chaiscript_threading.hpp"
|
||||
|
||||
#include <map>
|
||||
#include "any.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -36,7 +44,7 @@ namespace chaiscript
|
||||
struct Data
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
const chaiscript::detail::Any &to,
|
||||
const boost::any &to,
|
||||
bool tr,
|
||||
const void *t_void_ptr)
|
||||
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?0:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
@@ -60,7 +68,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
boost::any m_obj;
|
||||
void *m_data_ptr;
|
||||
const void *m_const_data_ptr;
|
||||
bool m_is_ref;
|
||||
@@ -68,70 +76,65 @@ namespace chaiscript
|
||||
|
||||
struct Object_Data
|
||||
{
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
return boost::make_shared<Data>(
|
||||
detail::Get_Type_Info<void>::get(),
|
||||
chaiscript::detail::Any(),
|
||||
boost::any(),
|
||||
false,
|
||||
nullptr)
|
||||
;
|
||||
static_cast<void *>(0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
|
||||
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
|
||||
{
|
||||
return get(*obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
|
||||
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
return boost::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
boost::any(obj),
|
||||
false,
|
||||
obj.get()
|
||||
);
|
||||
obj.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T *t)
|
||||
static boost::shared_ptr<Data> get(T *t)
|
||||
{
|
||||
return get(std::ref(*t));
|
||||
return get(boost::ref(*t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
|
||||
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
return boost::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
boost::any(obj),
|
||||
true,
|
||||
&obj.get()
|
||||
);
|
||||
obj.get_pointer());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T& t)
|
||||
static boost::shared_ptr<Data> get(const T& t)
|
||||
{
|
||||
auto p = std::make_shared<T>(t);
|
||||
return std::make_shared<Data>(
|
||||
boost::shared_ptr<T> p(new T(t));
|
||||
return boost::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(p),
|
||||
boost::any(p),
|
||||
false,
|
||||
p.get()
|
||||
);
|
||||
p.get());
|
||||
}
|
||||
|
||||
static std::shared_ptr<Data> get()
|
||||
static boost::shared_ptr<Data> get()
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
return boost::make_shared<Data>(
|
||||
Type_Info(),
|
||||
chaiscript::detail::Any(),
|
||||
boost::any(),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
static_cast<void *>(0));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -219,7 +222,7 @@ namespace chaiscript
|
||||
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0);
|
||||
}
|
||||
|
||||
const chaiscript::detail::Any & get() const
|
||||
const boost::any & get() const
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
@@ -244,17 +247,11 @@ namespace chaiscript
|
||||
return m_data->m_const_data_ptr;
|
||||
}
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(Boxed_Value l, Boxed_Value r)
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Data> m_data;
|
||||
boost::shared_ptr<Data> m_data;
|
||||
};
|
||||
|
||||
/// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, std::shared_ptr, or std::reference_type
|
||||
/// \brief Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer, boost::shared_ptr, or boost::reference_type
|
||||
/// a copy is not made.
|
||||
/// \param t The value to box
|
||||
///
|
||||
@@ -281,7 +278,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::shared_ptr<typename std::add_const<T>::type >(new T(t)));
|
||||
return Boxed_Value(boost::shared_ptr<typename boost::add_const<T>::type >(new T(t)));
|
||||
}
|
||||
|
||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
@@ -292,33 +289,33 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(T *t)
|
||||
{
|
||||
return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
|
||||
return Boxed_Value( const_cast<typename boost::add_const<T>::type *>(t) );
|
||||
}
|
||||
|
||||
/// \brief Takes a std::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
/// \brief Takes a boost::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
/// Does not copy the pointed to value.
|
||||
/// \param[in] t Pointer to make immutable
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
|
||||
Boxed_Value const_var_impl(const boost::shared_ptr<T> &t)
|
||||
{
|
||||
return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
|
||||
return Boxed_Value( boost::const_pointer_cast<typename boost::add_const<T>::type>(t) );
|
||||
}
|
||||
|
||||
/// \brief Takes a std::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
|
||||
/// \brief Takes a boost::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
|
||||
/// Does not copy the referenced value.
|
||||
/// \param[in] t Reference object to make immutable
|
||||
/// \returns Immutable Boxed_Value
|
||||
/// \sa Boxed_Value::is_const
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
|
||||
Boxed_Value const_var_impl(const boost::reference_wrapper<T> &t)
|
||||
{
|
||||
return Boxed_Value( std::cref(t.get()) );
|
||||
return Boxed_Value( boost::cref(t.get()) );
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer type
|
||||
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a boost::reference or pointer type
|
||||
/// the value is not copied. If it is an object type, it is copied.
|
||||
/// \param[in] t Object to make immutable
|
||||
/// \returns Immutable Boxed_Value
|
||||
@@ -348,6 +345,11 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(Boxed_Value l, Boxed_Value r)
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -11,12 +11,12 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
@@ -39,12 +39,12 @@ namespace chaiscript
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
reserved_word_error(const std::string &t_word) noexcept
|
||||
reserved_word_error(const std::string &t_word) throw()
|
||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~reserved_word_error() noexcept {}
|
||||
virtual ~reserved_word_error() throw() {}
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
@@ -86,12 +86,12 @@ namespace chaiscript
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
global_non_const() noexcept
|
||||
global_non_const() throw()
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() noexcept {}
|
||||
virtual ~global_non_const() throw() {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
throw exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.push_back(std::make_pair(t_bv, t_name));
|
||||
@@ -138,7 +138,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const std::shared_ptr<Module> &m)
|
||||
Module &add(const boost::shared_ptr<Module> &m)
|
||||
{
|
||||
m->apply(*this, *this);
|
||||
return *m;
|
||||
@@ -154,11 +154,6 @@ namespace chaiscript
|
||||
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
|
||||
}
|
||||
|
||||
~Module()
|
||||
{
|
||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
@@ -173,7 +168,7 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
t.add(begin->first, begin->second);
|
||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||
} catch (const exception::name_conflict_error &) {
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
@@ -213,7 +208,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/// Convenience typedef for Module objects to be added to the ChaiScript runtime
|
||||
typedef std::shared_ptr<Module> ModulePtr;
|
||||
typedef boost::shared_ptr<Module> ModulePtr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -376,7 +371,7 @@ namespace chaiscript
|
||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||
typedef std::map<std::string, Boxed_Value> Scope;
|
||||
typedef std::deque<Scope> StackData;
|
||||
typedef std::shared_ptr<StackData> Stack;
|
||||
typedef boost::shared_ptr<StackData> Stack;
|
||||
|
||||
struct State
|
||||
{
|
||||
@@ -385,12 +380,10 @@ namespace chaiscript
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
std::set<std::string> m_reserved_words;
|
||||
|
||||
State &operator=(const State &) = default;
|
||||
};
|
||||
|
||||
Dispatch_Engine()
|
||||
: m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
: m_place_holder(boost::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -452,7 +445,7 @@ namespace chaiscript
|
||||
Scope::iterator itr = scope.find(name);
|
||||
if (itr != stack.back().end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
throw exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, obj));
|
||||
}
|
||||
@@ -466,14 +459,14 @@ namespace chaiscript
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
throw exception::global_non_const();
|
||||
}
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
throw exception::name_conflict_error(name);
|
||||
} else {
|
||||
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||
}
|
||||
@@ -673,6 +666,27 @@ namespace chaiscript
|
||||
return functions.find(name) != functions.end();
|
||||
}
|
||||
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
return scope;
|
||||
}
|
||||
|
||||
/// \brief Sets all of the locals for the current thread state.
|
||||
///
|
||||
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||
///
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
scope = t_locals;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Get a map of all objects that can be seen from the current scope in a scripting context
|
||||
@@ -967,8 +981,8 @@ namespace chaiscript
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
|
||||
if (dynamic_lhs && dynamic_rhs)
|
||||
{
|
||||
@@ -1060,7 +1074,7 @@ namespace chaiscript
|
||||
|
||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||
{
|
||||
throw chaiscript::exception::reserved_word_error(name);
|
||||
throw exception::reserved_word_error(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1088,7 +1102,7 @@ namespace chaiscript
|
||||
{
|
||||
if ((*t_f) == *(*itr2))
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(t_name);
|
||||
throw exception::name_conflict_error(t_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,9 @@
|
||||
#include "boxed_value.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_polymorphic.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -20,22 +23,22 @@ 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) throw()
|
||||
: 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) throw()
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
bad_boxed_dynamic_cast(const std::string &w) throw()
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept {}
|
||||
virtual ~bad_boxed_dynamic_cast() throw() {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,8 +90,8 @@ namespace chaiscript
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
{
|
||||
std::shared_ptr<const Base> data
|
||||
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived));
|
||||
boost::shared_ptr<const Base> data
|
||||
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
@@ -96,8 +99,8 @@ namespace chaiscript
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<Base> data
|
||||
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived));
|
||||
boost::shared_ptr<Base> data
|
||||
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
@@ -112,15 +115,15 @@ namespace chaiscript
|
||||
{
|
||||
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived);
|
||||
const Base &data = dynamic_cast<const Base &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
return Boxed_Value(boost::cref(data));
|
||||
} else {
|
||||
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
|
||||
Base &data = dynamic_cast<Base &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
return Boxed_Value(boost::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -136,9 +139,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
static std::shared_ptr<Dynamic_Conversion> create()
|
||||
static boost::shared_ptr<Dynamic_Conversion> create()
|
||||
{
|
||||
std::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
|
||||
boost::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
|
||||
|
||||
/// \todo this is a hack and a kludge. The idea is to make sure that
|
||||
/// the conversion is registered both in the module's notion of the static conversion object
|
||||
@@ -165,7 +168,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@@ -219,7 +222,7 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
|
||||
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
@@ -249,9 +252,9 @@ namespace chaiscript
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
BOOST_STATIC_ASSERT((boost::is_base_of<Base,Derived>::value));
|
||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
|
||||
|
||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
||||
}
|
||||
@@ -275,9 +278,9 @@ namespace chaiscript
|
||||
try {
|
||||
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -51,26 +52,16 @@ namespace chaiscript
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
const std::string &t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(t_func->get_param_types()),
|
||||
m_type_name(t_type_name), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
Dynamic_Object_Function(
|
||||
const std::string &t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
const Type_Info &t_ti)
|
||||
const boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
|
||||
m_type_name(t_type_name), m_func(t_func), m_ti(new Type_Info(t_ti))
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
m_type_name(t_type_name), m_func(t_func), m_ti(t_ti)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
@@ -97,7 +88,9 @@ namespace chaiscript
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||
{
|
||||
return {m_func};
|
||||
std::vector<Const_Proxy_Function> fs;
|
||||
fs.push_back(m_func);
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
@@ -130,18 +123,23 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> build_param_types(
|
||||
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
|
||||
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
|
||||
{
|
||||
std::vector<Type_Info> types(t_inner_types);
|
||||
if (t_objectti)
|
||||
{
|
||||
std::vector<Type_Info> types(t_inner_types);
|
||||
|
||||
assert(types.size() > 1);
|
||||
assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||
types[1] = t_objectti;
|
||||
return types;
|
||||
assert(types.size() > 1);
|
||||
assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||
types[1] = *t_objectti;
|
||||
return types;
|
||||
} else {
|
||||
return t_inner_types;
|
||||
}
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
const boost::optional<Type_Info> &ti)
|
||||
{
|
||||
static Type_Info doti = user_type<Dynamic_Object>();
|
||||
if (bv.get_type_info().bare_equal(doti))
|
||||
@@ -164,7 +162,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
const boost::optional<Type_Info> &ti)
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@@ -176,7 +174,7 @@ namespace chaiscript
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
boost::optional<Type_Info> m_ti;
|
||||
|
||||
};
|
||||
|
||||
@@ -195,10 +193,10 @@ namespace chaiscript
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
||||
m_type_name(t_type_name), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
}
|
||||
|
||||
static std::vector<Type_Info> build_type_list(const std::vector<Type_Info> &tl)
|
||||
{
|
||||
|
@@ -21,7 +21,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
void throw_type(const Boxed_Value &bv)
|
||||
{
|
||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
|
||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const exception::bad_boxed_cast &) {}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
|
||||
/// \sa \ref exceptions
|
||||
typedef std::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
|
||||
typedef boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
|
@@ -7,6 +7,9 @@
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_HPP_
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "proxy_functions.hpp"
|
||||
@@ -22,13 +25,13 @@ namespace chaiscript
|
||||
/**
|
||||
* Build a function caller that knows how to dispatch on a set of functions
|
||||
* example:
|
||||
* std::function<void (int)> f =
|
||||
* boost::function<void (int)> f =
|
||||
* build_function_caller(dispatchkit.get_function("print"));
|
||||
* \returns A std::function object for dispatching
|
||||
* \returns A boost::function object for dispatching
|
||||
* \param[in] funcs the set of functions to dispatch on.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
boost::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||
{
|
||||
FunctionType *p=0;
|
||||
@@ -42,14 +45,14 @@ namespace chaiscript
|
||||
* example:
|
||||
* void my_function(Proxy_Function f)
|
||||
* {
|
||||
* std::function<void (int)> local_f =
|
||||
* boost::function<void (int)> local_f =
|
||||
* build_function_caller(f);
|
||||
* }
|
||||
* \returns A std::function object for dispatching
|
||||
* \returns A boost::function object for dispatching
|
||||
* \param[in] func A function to execute.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
boost::function<FunctionType>
|
||||
functor(Const_Proxy_Function func)
|
||||
{
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
@@ -62,7 +65,7 @@ namespace chaiscript
|
||||
* and creating a typesafe C++ function caller from it.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
boost::function<FunctionType>
|
||||
functor(const Boxed_Value &bv)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
||||
@@ -71,12 +74,12 @@ namespace chaiscript
|
||||
|
||||
namespace detail{
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function &
|
||||
* Cast helper to handle automatic casting to const boost::function &
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
struct Cast_Helper<const boost::function<Signature> &>
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -84,18 +87,18 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob);
|
||||
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to std::function
|
||||
* Cast helper to handle automatic casting to boost::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
struct Cast_Helper<boost::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -103,18 +106,18 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function
|
||||
* Cast helper to handle automatic casting to const boost::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
struct Cast_Helper<const boost::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -122,7 +125,7 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -4,9 +4,19 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#define addparam(z,n,text) params.push_back((boost::is_reference<Param ## n>::value&&!(boost::is_same<chaiscript::Boxed_Value, typename boost::remove_const<typename boost::remove_reference<Param ## n>::type>::type>::value))?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) ));
|
||||
#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n))
|
||||
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "proxy_functions.hpp"
|
||||
@@ -44,41 +54,50 @@ namespace chaiscript
|
||||
dispatch::dispatch(t_funcs, params);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 9 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/function_call_detail.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* used internally for unwrapping a function call's types
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
|
||||
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
|
||||
BOOST_PP_REPEAT(n, addparam, ~)
|
||||
|
||||
return Function_Caller_Ret<Ret>::call(funcs, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* used internally for unwrapping a function call's types
|
||||
*/
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs)
|
||||
: m_funcs(t_funcs)
|
||||
{
|
||||
}
|
||||
|
||||
Ret operator()(Param...param)
|
||||
{
|
||||
return Function_Caller_Ret<Ret>::call(m_funcs, {
|
||||
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs)
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
||||
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
|
||||
{
|
||||
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]);
|
||||
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
|
||||
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
|
||||
(funcs[0]);
|
||||
|
||||
if (pfi)
|
||||
{
|
||||
@@ -88,11 +107,15 @@ namespace chaiscript
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs));
|
||||
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
|
||||
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef n
|
||||
#undef addparam
|
||||
#undef curry
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "boxed_number.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -43,27 +44,27 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> >
|
||||
struct Handle_Return<boost::shared_ptr<Ret> >
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &>
|
||||
struct Handle_Return<const boost::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
@@ -74,7 +75,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
return Boxed_Value(boost::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -87,12 +88,12 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::ref(r));
|
||||
return Boxed_Value(boost::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(std::cref(r));
|
||||
return Boxed_Value(boost::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -7,8 +7,6 @@
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace bootstrap
|
||||
@@ -156,7 +154,7 @@ namespace chaiscript
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_minus(L l)
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
|
@@ -4,36 +4,24 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_constructors.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
# endif
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* A constructor function, used for creating a new object
|
||||
* of a given type with a given set of params
|
||||
*/
|
||||
template<typename Class, typename ... Params>
|
||||
std::shared_ptr<Class> constructor_(Params ... params)
|
||||
{
|
||||
return std::shared_ptr<Class>(new Class(params...));
|
||||
}
|
||||
|
||||
template<typename Class, typename ... Params >
|
||||
Proxy_Function build_constructor_(Class (*)(Params...))
|
||||
{
|
||||
typedef std::shared_ptr<Class> (sig)(Params...);
|
||||
return Proxy_Function(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// \brief Generates a constructor function for use with ChaiScript
|
||||
///
|
||||
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
|
||||
@@ -51,8 +39,43 @@ namespace chaiscript
|
||||
T *f = 0;
|
||||
return (dispatch::detail::build_constructor_(f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* A constructor function, used for creating a new object
|
||||
* of a given type with a given set of params
|
||||
*/
|
||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
boost::shared_ptr<Class> constructor_( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||
{
|
||||
return boost::shared_ptr<Class>(new Class( BOOST_PP_ENUM_PARAMS(n, p) ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for build a constructor function
|
||||
* example:
|
||||
* dispatchengine.register_function(build_constructor<MyClass, int, const std::string&>, "MyClass");
|
||||
* \todo See if it is possible to make this not be a variadic function
|
||||
*/
|
||||
template<typename Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
Proxy_Function build_constructor_(Class (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
typedef boost::shared_ptr<Class> (sig)(BOOST_PP_ENUM_PARAMS(n, Param));
|
||||
return Proxy_Function(new Proxy_Function_Impl<sig>(boost::function<sig>(&(constructor_<Class BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -12,10 +12,10 @@
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include "proxy_functions_detail.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -23,11 +23,41 @@ namespace chaiscript
|
||||
class Boxed_Number;
|
||||
struct AST_Node;
|
||||
|
||||
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
|
||||
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
/**
|
||||
* Helper for building a list of parameters for calling a Proxy_Function
|
||||
* it does automatic conversion to Boxed_Value types via operator<<
|
||||
*
|
||||
* example usage:
|
||||
* Boxed_Value retval = dispatch(dispatchengine.get_function("+"),
|
||||
* chaiscript::Param_List_Builder() << 5 << 6);
|
||||
*/
|
||||
struct Param_List_Builder
|
||||
{
|
||||
Param_List_Builder &operator<<(const Boxed_Value &so)
|
||||
{
|
||||
objects.push_back(so);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Param_List_Builder &operator<<(T t)
|
||||
{
|
||||
objects.push_back(Boxed_Value(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const std::vector<Boxed_Value> &() const
|
||||
{
|
||||
return objects;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> objects;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pure virtual base class for all Proxy_Function implementations
|
||||
* Proxy_Functions are a type erasure of type safe C++
|
||||
@@ -50,14 +80,14 @@ namespace chaiscript
|
||||
/// if the function is variadic or takes no arguments (arity of 0 or -1), the returned
|
||||
/// value containes exactly 1 Type_Info object: the return type
|
||||
/// \returns the types of all parameters.
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
std::vector<Type_Info> get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0;
|
||||
|
||||
virtual std::vector<std::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||
virtual std::vector<boost::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||
{
|
||||
return std::vector<std::shared_ptr<const Proxy_Function_Base> >();
|
||||
return std::vector<boost::shared_ptr<const Proxy_Function_Base> >();
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +140,7 @@ namespace chaiscript
|
||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| bv.get_type_info().bare_equal(user_type<boost::shared_ptr<const Proxy_Function_Base> >())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -144,11 +174,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Common typedef used for passing of any registered function in ChaiScript
|
||||
typedef std::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
|
||||
typedef boost::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
|
||||
|
||||
/// \brief Const version of Proxy_Function chaiscript. Points to a const Proxy_Function. This is how most registered functions
|
||||
/// are handled internally.
|
||||
typedef std::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
typedef boost::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
|
||||
namespace exception
|
||||
{
|
||||
@@ -156,11 +186,11 @@ namespace chaiscript
|
||||
class guard_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
guard_error() noexcept
|
||||
guard_error() throw()
|
||||
: std::runtime_error("Guard evaluation failed")
|
||||
{ }
|
||||
|
||||
virtual ~guard_error() noexcept
|
||||
virtual ~guard_error() throw()
|
||||
{ }
|
||||
};
|
||||
}
|
||||
@@ -175,7 +205,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dynamic_Proxy_Function(
|
||||
const std::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
||||
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
||||
int t_arity=-1,
|
||||
const AST_NodePtr &t_parsenode = AST_NodePtr(),
|
||||
const std::string &t_description = "",
|
||||
@@ -266,7 +296,7 @@ namespace chaiscript
|
||||
// For the return type
|
||||
types.push_back(chaiscript::detail::Get_Type_Info<Boxed_Value>::get());
|
||||
|
||||
if (arity > 0)
|
||||
if (arity >= 0)
|
||||
{
|
||||
for (int i = 0; i < arity; ++i)
|
||||
{
|
||||
@@ -277,7 +307,7 @@ namespace chaiscript
|
||||
return types;
|
||||
}
|
||||
|
||||
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
int m_arity;
|
||||
std::string m_description;
|
||||
Proxy_Function m_guard;
|
||||
@@ -382,7 +412,6 @@ namespace chaiscript
|
||||
const std::vector<Boxed_Value> &t_args)
|
||||
{
|
||||
assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast<int>(t_args.size()));
|
||||
|
||||
if (t_f->get_arity() < 0) { return std::vector<Type_Info>(); }
|
||||
|
||||
std::vector<Type_Info> types = t_f->get_param_types();
|
||||
@@ -414,18 +443,18 @@ namespace chaiscript
|
||||
|
||||
/**
|
||||
* The standard typesafe function call implementation of Proxy_Function
|
||||
* It takes a std::function<> object and performs runtime
|
||||
* It takes a boost::function<> object and performs runtime
|
||||
* type checking of Boxed_Value parameters, in a type safe manner
|
||||
*/
|
||||
template<typename Func>
|
||||
class Proxy_Function_Impl : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl(const std::function<Func> &f)
|
||||
Proxy_Function_Impl(const boost::function<Func> &f)
|
||||
: Proxy_Function_Base(detail::build_param_type_list(static_cast<Func *>(0))),
|
||||
m_f(f), m_dummy_func(0)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl() {}
|
||||
|
||||
@@ -435,11 +464,13 @@ namespace chaiscript
|
||||
return pimpl != 0;
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const
|
||||
{
|
||||
return static_cast<int>(m_types.size()) - 1;
|
||||
}
|
||||
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals) const
|
||||
{
|
||||
if (int(vals.size()) != get_arity())
|
||||
@@ -455,7 +486,7 @@ namespace chaiscript
|
||||
return "";
|
||||
}
|
||||
|
||||
std::function<Func> internal_function() const
|
||||
boost::function<Func> internal_function() const
|
||||
{
|
||||
return m_f;
|
||||
}
|
||||
@@ -463,11 +494,11 @@ namespace chaiscript
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params);
|
||||
return detail::Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<Func> m_f;
|
||||
boost::function<Func> m_f;
|
||||
Func *m_dummy_func;
|
||||
};
|
||||
|
||||
@@ -481,8 +512,8 @@ namespace chaiscript
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
@@ -490,7 +521,6 @@ namespace chaiscript
|
||||
{
|
||||
const Attribute_Access<T, Class> * aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
||||
|
||||
if (aa) {
|
||||
return m_attr == aa->m_attr;
|
||||
} else {
|
||||
@@ -528,10 +558,10 @@ namespace chaiscript
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
@@ -541,9 +571,11 @@ namespace chaiscript
|
||||
private:
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
return {user_type<T>(), user_type<Class>()};
|
||||
std::vector<Type_Info> v;
|
||||
v.push_back(user_type<T>());
|
||||
v.push_back(user_type<Class>());
|
||||
return v;
|
||||
}
|
||||
|
||||
T Class::* m_attr;
|
||||
};
|
||||
}
|
||||
@@ -558,14 +590,16 @@ namespace chaiscript
|
||||
class dispatch_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
dispatch_error(const std::vector<Boxed_Value> &t_bvs)
|
||||
: std::runtime_error("Error with function dispatch"), parameters(t_bvs)
|
||||
dispatch_error(const std::vector<Boxed_Value> &t_parameters,
|
||||
const std::vector<Const_Proxy_Function> &t_functions)
|
||||
: std::runtime_error("Error with function dispatch"), parameters(t_parameters), functions(t_functions)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dispatch_error() noexcept {}
|
||||
virtual ~dispatch_error() throw() {}
|
||||
|
||||
std::vector<Boxed_Value> parameters;
|
||||
std::vector<Const_Proxy_Function> functions;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -581,6 +615,7 @@ namespace chaiscript
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
{
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
@@ -599,7 +634,7 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
|
||||
throw exception::dispatch_error(plist);
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -4,6 +4,13 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#define gettypeinfo(z,n,text) ti.push_back(chaiscript::detail::Get_Type_Info<Param ## n>::get());
|
||||
#define casthelper(z,n,text) BOOST_PP_COMMA_IF(n) chaiscript::boxed_cast< Param ## n >(params[n])
|
||||
#define trycast(z,n,text) chaiscript::boxed_cast<Param ## n>(params[n]);
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
|
||||
|
||||
@@ -12,6 +19,8 @@
|
||||
#include "type_info.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -32,13 +41,26 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~arity_error() noexcept {}
|
||||
virtual ~arity_error() throw() {}
|
||||
|
||||
int got;
|
||||
int expected;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
|
||||
#define BOOST_PP_FILENAME_1 <chaiscript/dispatchkit/proxy_functions_detail.hpp>
|
||||
#include BOOST_PP_ITERATE()
|
||||
|
||||
|
||||
# endif
|
||||
#else
|
||||
# define n BOOST_PP_ITERATION()
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
@@ -47,105 +69,66 @@ namespace chaiscript
|
||||
* 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...))
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)))
|
||||
{
|
||||
return std::vector<Type_Info> { chaiscript::detail::Get_Type_Info<Ret>::get(),
|
||||
chaiscript::detail::Get_Type_Info<Params>::get()... };
|
||||
std::vector<Type_Info> ti;
|
||||
ti.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
|
||||
|
||||
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
||||
|
||||
return ti;
|
||||
}
|
||||
|
||||
|
||||
// Forward declaration
|
||||
template<typename ... Rest>
|
||||
struct Try_Cast;
|
||||
|
||||
// implementation
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Try_Cast<Param, Rest...>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation)
|
||||
{
|
||||
boxed_cast<Param>(params[generation]);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1);
|
||||
}
|
||||
};
|
||||
|
||||
// 0th case
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, int)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Ret, int count, typename ... Params>
|
||||
struct Call_Func
|
||||
{
|
||||
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
struct Call_Func<Ret, 0, Params...>
|
||||
{
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> &, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams))...);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
* The function attempts to unbox each paramter 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 Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
Ret call_func(const boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> &f,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
if (params.size() != n)
|
||||
{
|
||||
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params);
|
||||
throw exception::arity_error(static_cast<int>(params.size()), n);
|
||||
} else {
|
||||
return f(BOOST_PP_REPEAT(n, casthelper, ~));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
|
||||
bool compare_types_cast(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)),
|
||||
const std::vector<Boxed_Value> & BOOST_PP_IF(n, params, ))
|
||||
{
|
||||
try {
|
||||
BOOST_PP_REPEAT(n, trycast, ~);
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#undef n
|
||||
#undef gettypeinfo
|
||||
#undef casthelper
|
||||
#undef trycast
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -157,7 +140,7 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params));
|
||||
}
|
||||
@@ -167,7 +150,7 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
call_func(fun, params);
|
||||
return Handle_Return<void>::handle();
|
||||
|
@@ -9,6 +9,12 @@
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bind_first.hpp"
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function_types/components.hpp>
|
||||
#include <boost/function_types/function_type.hpp>
|
||||
#include <boost/function_types/is_member_object_pointer.hpp>
|
||||
#include <boost/function_types/is_member_function_pointer.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -16,48 +22,39 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
struct FunctionSignature
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Sig>
|
||||
struct FunctionSignature<std::function<Sig> >
|
||||
{
|
||||
typedef Sig Signature;
|
||||
};
|
||||
|
||||
template<typename Ret, typename ... Args>
|
||||
std::function<Ret (Args...) > to_function(Ret (*func)(Args...))
|
||||
{
|
||||
return std::function<Ret (Args...)>(func);
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Args>
|
||||
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
|
||||
{
|
||||
return std::function<Ret (Class &, Args...)>(func);
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Args>
|
||||
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
|
||||
{
|
||||
return std::function<Ret (const Class &, Args...)>(func);
|
||||
}
|
||||
|
||||
template<bool Object>
|
||||
template<bool Object, bool MemFn>
|
||||
struct Fun_Helper
|
||||
{
|
||||
template<typename T>
|
||||
static Proxy_Function go(T t)
|
||||
{
|
||||
return Proxy_Function(
|
||||
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
|
||||
new Proxy_Function_Impl<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
|
||||
boost::function<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type
|
||||
>(t)));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Fun_Helper<true>
|
||||
struct Fun_Helper<false, true>
|
||||
{
|
||||
template<typename T>
|
||||
static Proxy_Function go(T t)
|
||||
{
|
||||
return Proxy_Function(
|
||||
new Proxy_Function_Impl<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type> (
|
||||
boost::function<
|
||||
typename boost::function_types::function_type<boost::function_types::components<T> >::type
|
||||
>(boost::mem_fn(t))));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct Fun_Helper<true, false>
|
||||
{
|
||||
template<typename T, typename Class>
|
||||
static Proxy_Function go(T Class::* m)
|
||||
@@ -68,19 +65,19 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a std::function object
|
||||
/// \param[in] f std::function to expose to ChaiScript
|
||||
/// \brief Creates a new Proxy_Function object from a boost::function object
|
||||
/// \param[in] f boost::function to expose to ChaiScript
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// std::function<int (char, float, std::string)> f = get_some_function();
|
||||
/// boost::function<int (char, float, std::string)> f = get_some_function();
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(fun(f), "some_function");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
template<typename T>
|
||||
Proxy_Function fun(const std::function<T> &f)
|
||||
Proxy_Function fun(const boost::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
@@ -108,7 +105,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Proxy_Function fun(T t)
|
||||
{
|
||||
return dispatch::detail::Fun_Helper<std::is_member_object_pointer<T>::value>::go(t);
|
||||
return dispatch::detail::Fun_Helper<boost::function_types::is_member_object_pointer<T>::value, boost::function_types::is_member_function_pointer<T>::value>::go(t);
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
|
||||
@@ -125,7 +122,7 @@ namespace chaiscript
|
||||
/// MyClass obj;
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// // Add function taking only one argument, an int, and permanently bound to "obj"
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
|
||||
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj)), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
@@ -151,7 +148,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// // Add function taking only no arguments, and permanently bound to "obj" and "1"
|
||||
/// // memberfunction() will be equivalent to obj.memberfunction(1)
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
|
||||
/// chai.add(fun(&MyClass::memberfunction, boost::ref(obj), 1), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
|
@@ -9,8 +9,17 @@
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -20,7 +29,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Bare_Type
|
||||
{
|
||||
typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
|
||||
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -140,70 +149,70 @@ namespace chaiscript
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
return Type_Info(boost::is_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||
boost::is_void<T>::value,
|
||||
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
|
||||
&typeid(T),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::shared_ptr<T> >
|
||||
struct Get_Type_Info<boost::shared_ptr<T> >
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
&typeid(std::shared_ptr<T> ),
|
||||
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||
boost::is_void<T>::value,
|
||||
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
|
||||
&typeid(boost::shared_ptr<T> ),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
struct Get_Type_Info<const boost::shared_ptr<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
&typeid(const std::shared_ptr<T> &),
|
||||
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||
boost::is_void<T>::value,
|
||||
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
|
||||
&typeid(const boost::shared_ptr<T> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
struct Get_Type_Info<boost::reference_wrapper<T> >
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
&typeid(std::reference_wrapper<T> ),
|
||||
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||
boost::is_void<T>::value,
|
||||
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
|
||||
&typeid(boost::reference_wrapper<T> ),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
struct Get_Type_Info<const boost::reference_wrapper<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
&typeid(const std::reference_wrapper<T> &),
|
||||
return Type_Info(boost::is_const<T>::value, boost::is_reference<T>::value, boost::is_pointer<T>::value,
|
||||
boost::is_void<T>::value,
|
||||
boost::is_arithmetic<T>::value && !boost::is_same<typename boost::remove_const<T>::type, bool>::value,
|
||||
&typeid(const boost::reference_wrapper<T> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
@@ -7,7 +7,8 @@
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
@@ -7,8 +7,8 @@
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
|
||||
#include <sstream>
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -23,7 +23,7 @@ namespace chaiscript
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond
|
||||
Logical_And, Logical_Or, Switch, Case, Default, Ternary_Cond
|
||||
};
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace chaiscript
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition"};
|
||||
"Logical_And", "Logical_Or", "Switch", "Case", "Default", "Ternary Condition"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
@@ -69,54 +69,233 @@ namespace chaiscript
|
||||
File_Position start_position;
|
||||
File_Position end_position;
|
||||
std::string filename;
|
||||
std::string detail;
|
||||
std::vector<AST_NodePtr> call_stack;
|
||||
|
||||
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 chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_ss)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(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) :
|
||||
std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss))
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
std::runtime_error(format(t_why, t_parameters, t_ss)),
|
||||
reason(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) :
|
||||
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) :
|
||||
std::runtime_error(format(t_why, t_where, t_fname)),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
||||
{}
|
||||
|
||||
eval_error(const std::string &t_why) noexcept
|
||||
eval_error(const std::string &t_why) throw()
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
|
||||
virtual ~eval_error() noexcept {}
|
||||
std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << what();
|
||||
if (call_stack.size() > 0) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")" << std::endl;
|
||||
ss << std::endl << detail << std::endl;
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
ss << std::endl;
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
virtual ~eval_error() throw() {}
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static int id(const T& t)
|
||||
{
|
||||
return t->identifier;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string pretty(const T& t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string fname(const T& t)
|
||||
{
|
||||
return *t->filename;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string startpos(const T& t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << t->start.line << ", " << t->start.column;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static std::string format_why(const std::string &t_why)
|
||||
{
|
||||
return "Error: \"" + t_why + "\"";
|
||||
}
|
||||
|
||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||
static std::string format_types(const Const_Proxy_Function &t_func,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
int arity = t_func->get_arity();
|
||||
std::vector<Type_Info> types = t_func->get_param_types();
|
||||
|
||||
std::string retval;
|
||||
if (arity == -1)
|
||||
{
|
||||
retval = "(...)";
|
||||
if (t_dot_notation)
|
||||
{
|
||||
retval = "(Object)." + retval;
|
||||
}
|
||||
} else if (types.size() <= 1) {
|
||||
retval = "()";
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
|
||||
std::string paramstr;
|
||||
|
||||
for (size_t index = 1;
|
||||
index != types.size();
|
||||
++index)
|
||||
{
|
||||
paramstr += (types[index].is_const()?"const ":"");
|
||||
paramstr += t_ss.get_type_name(types[index]);
|
||||
|
||||
if (index == 1 && t_dot_notation)
|
||||
{
|
||||
paramstr += ").(";
|
||||
if (types.size() == 2)
|
||||
{
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
paramstr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||
|
||||
ss << ")";
|
||||
retval = ss.str();
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||
|
||||
if (dynfun)
|
||||
{
|
||||
Proxy_Function f = dynfun->get_guard();
|
||||
|
||||
if (f)
|
||||
{
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
|
||||
= boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
|
||||
if (dynfunguard)
|
||||
{
|
||||
retval += " : " + format_guard(dynfunguard->get_parse_tree());
|
||||
}
|
||||
}
|
||||
|
||||
retval += "\n Defined at " + format_location(dynfun->get_parse_tree());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_guard(const T &t)
|
||||
{
|
||||
return t->pretty_print();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::string format_location(const T &t)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "(" << *t->filename << " " << t->start.line << ", " << t->start.column << ")";
|
||||
|
||||
return oss.str();
|
||||
|
||||
}
|
||||
|
||||
static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "With parameters: (";
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||
|
||||
for (std::vector<chaiscript::Const_Proxy_Function>::const_iterator itr = t_functions.begin();
|
||||
itr != t_functions.end();
|
||||
++itr)
|
||||
{
|
||||
ss << " " << format_types((*itr), t_dot_notation, t_ss) << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
|
||||
}
|
||||
|
||||
static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(";
|
||||
|
||||
if (!t_parameters.empty())
|
||||
{
|
||||
std::string paramstr;
|
||||
|
||||
for (const Boxed_Value &bv: t_parameters)
|
||||
for (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin();
|
||||
itr != t_parameters.end();
|
||||
++itr)
|
||||
{
|
||||
paramstr += (bv.is_const()?"const ":"");
|
||||
paramstr += t_ss.type_name(bv);
|
||||
paramstr += ", ";
|
||||
paramstr += (itr->is_const()?"const ":"");
|
||||
paramstr += t_ss.type_name(*itr);
|
||||
|
||||
if (itr == t_parameters.begin() && t_dot_notation)
|
||||
{
|
||||
paramstr += ").(";
|
||||
if (t_parameters.size() == 1)
|
||||
{
|
||||
paramstr += ", ";
|
||||
}
|
||||
} else {
|
||||
paramstr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
ss << paramstr.substr(0, paramstr.size() - 2);
|
||||
@@ -148,14 +327,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << format_parameters(t_parameters, t_ss);
|
||||
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
ss << format_filename(t_fname);
|
||||
@@ -167,14 +346,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
const std::vector<Boxed_Value> &t_parameters,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << format_parameters(t_parameters, t_ss);
|
||||
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
return ss.str();
|
||||
@@ -200,26 +381,39 @@ namespace chaiscript
|
||||
* Errors generated when loading a file
|
||||
*/
|
||||
struct file_not_found_error : public std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) noexcept
|
||||
file_not_found_error(const std::string &t_filename) throw()
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
virtual ~file_not_found_error() noexcept {}
|
||||
virtual ~file_not_found_error() throw() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
|
||||
public:
|
||||
const std::string text;
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
std::shared_ptr<const std::string> filename;
|
||||
const int identifier;
|
||||
boost::shared_ptr<const std::string> filename;
|
||||
File_Position start, end;
|
||||
std::vector<AST_NodePtr> children;
|
||||
AST_NodePtr annotation;
|
||||
|
||||
virtual std::string pretty_print() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << text;
|
||||
|
||||
for (unsigned int j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->pretty_print();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the contents of an AST node, including its children, recursively
|
||||
*/
|
||||
@@ -256,14 +450,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname,
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
|
||||
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
|
||||
text(t_ast_node_text), identifier(t_id), filename(t_fname),
|
||||
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
|
||||
{
|
||||
}
|
||||
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
|
||||
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
@@ -10,17 +10,12 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#ifdef BOOST_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
@@ -39,12 +34,12 @@ 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) throw()
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~load_module_error() noexcept
|
||||
virtual ~load_module_error() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -62,7 +57,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
throw exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +80,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
throw exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +180,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +200,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +223,7 @@ namespace chaiscript
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
throw exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
@@ -236,7 +231,7 @@ namespace chaiscript
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +293,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current evaluation m_engine
|
||||
*/
|
||||
@@ -308,7 +304,9 @@ namespace chaiscript
|
||||
/**
|
||||
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
*/
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
void build_eval_system() {
|
||||
using namespace bootstrap;
|
||||
m_engine.add_reserved_word("auto");
|
||||
m_engine.add_reserved_word("def");
|
||||
m_engine.add_reserved_word("fun");
|
||||
m_engine.add_reserved_word("while");
|
||||
@@ -318,27 +316,25 @@ namespace chaiscript
|
||||
m_engine.add_reserved_word("&&");
|
||||
m_engine.add_reserved_word("||");
|
||||
m_engine.add_reserved_word(",");
|
||||
m_engine.add_reserved_word("auto");
|
||||
m_engine.add_reserved_word(":=");
|
||||
m_engine.add_reserved_word("var");
|
||||
m_engine.add_reserved_word("return");
|
||||
m_engine.add_reserved_word("break");
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
if (t_lib)
|
||||
{
|
||||
add(t_lib);
|
||||
}
|
||||
add(Bootstrap::bootstrap());
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, std::ref(m_engine)), "dump_system");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, std::ref(m_engine)), "dump_object");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, boost::ref(m_engine)), "dump_system");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, boost::ref(m_engine)), "dump_object");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, boost::ref(m_engine)), "is_type");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, boost::ref(m_engine)), "type_name");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, boost::ref(m_engine)), "function_exists");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, boost::ref(m_engine)), "get_functions");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, boost::ref(m_engine)), "get_objects");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, boost::ref(m_engine)), "name");
|
||||
|
||||
|
||||
typedef void (ChaiScript::*load_mod_1)(const std::string&);
|
||||
@@ -347,6 +343,11 @@ namespace chaiscript
|
||||
m_engine.add(fun(static_cast<load_mod_1>(&ChaiScript::load_module), this), "load_module");
|
||||
m_engine.add(fun(static_cast<load_mod_2>(&ChaiScript::load_module), this), "load_module");
|
||||
|
||||
add(standard_library::vector_type<std::vector<Boxed_Value> >("Vector"));
|
||||
add(standard_library::string_type<std::string>("string"));
|
||||
add(standard_library::map_type<std::map<std::string, Boxed_Value> >("Map"));
|
||||
add(standard_library::pair_type<std::pair<Boxed_Value, Boxed_Value > >("Pair"));
|
||||
|
||||
m_engine.add(fun(&ChaiScript::use, this), "use");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval, this), "eval");
|
||||
m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval");
|
||||
@@ -361,7 +362,7 @@ namespace chaiscript
|
||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||
|
||||
if (!infile.is_open()) {
|
||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
@@ -381,11 +382,9 @@ namespace chaiscript
|
||||
|
||||
public:
|
||||
/// \brief Constructor for ChaiScript
|
||||
/// \param[in] t_lib Standard library to apply to this ChaiScript instance
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
ChaiScript(const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
|
||||
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
|
||||
{
|
||||
@@ -399,74 +398,9 @@ namespace chaiscript
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
build_eval_system(t_lib);
|
||||
build_eval_system();
|
||||
}
|
||||
|
||||
/// \brief Constructor for ChaiScript.
|
||||
///
|
||||
/// This version of the ChaiScript constructor attempts to find the stdlib module to load
|
||||
/// at runtime generates an error if it cannot be found.
|
||||
///
|
||||
/// \param[in] t_modulepaths Vector of paths to search when attempting to load a binary module
|
||||
/// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file
|
||||
ChaiScript( const std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
const std::vector<std::string> &t_usepaths = std::vector<std::string>())
|
||||
: m_modulepaths(t_modulepaths), m_usepaths(t_usepaths)
|
||||
{
|
||||
if (m_modulepaths.empty())
|
||||
{
|
||||
m_modulepaths.push_back("");
|
||||
}
|
||||
|
||||
if (m_usepaths.empty())
|
||||
{
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
|
||||
#ifdef _POSIX_VERSION
|
||||
// If on Unix, add the path of the current executable to the module search path
|
||||
// as windows would do
|
||||
|
||||
union cast_union
|
||||
{
|
||||
void (ChaiScript::*in_ptr)(const std::string&);
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
Dl_info rInfo;
|
||||
memset( &rInfo, 0, sizeof(rInfo) );
|
||||
cast_union u;
|
||||
u.in_ptr = &ChaiScript::use;
|
||||
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
|
||||
std::string dllpath(rInfo.dli_fname);
|
||||
size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
dllpath.erase(lastslash);
|
||||
}
|
||||
|
||||
// Let's see if this is a link that we should expand
|
||||
std::vector<char> buf(2048);
|
||||
size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
if (pathlen > 0 && pathlen < buf.size())
|
||||
{
|
||||
dllpath = std::string(&buf.front(), pathlen);
|
||||
}
|
||||
|
||||
m_modulepaths.push_back(dllpath+"/");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// attempt to load the stdlib
|
||||
load_module("chaiscript_stdlib");
|
||||
|
||||
build_eval_system(ModulePtr());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \brief Loads and parses a file. If the file is already, it is not reloaded
|
||||
/// The use paths specified at ChaiScript construction time are searched for the
|
||||
/// requested file.
|
||||
@@ -504,7 +438,7 @@ namespace chaiscript
|
||||
/// \brief Adds a constant object that is available in all contexts and to all threads
|
||||
/// \param[in] t_bv Boxed_Value to add as a global
|
||||
/// \param[in] t_name Name of the value to add
|
||||
/// \throw chaiscript::exception::global_non_const If t_bv is not a constant object
|
||||
/// \throw exception::global_non_const If t_bv is not a constant object
|
||||
/// \sa Boxed_Value::is_const
|
||||
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
{
|
||||
@@ -522,8 +456,12 @@ namespace chaiscript
|
||||
std::set<std::string> active_loaded_modules;
|
||||
};
|
||||
|
||||
/// \brief Returns a state object that represents the current state of the system
|
||||
/// \return Current state of the system
|
||||
/// \brief Returns a state object that represents the current state of the global system
|
||||
///
|
||||
/// The global system includes the reserved words, global const objects, functions and types.
|
||||
/// local variables are thread specific and not included.
|
||||
///
|
||||
/// \return Current state of the global system
|
||||
///
|
||||
/// \b Example:
|
||||
///
|
||||
@@ -544,6 +482,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Sets the state of the system
|
||||
///
|
||||
/// The global system includes the reserved words, global objects, functions and types.
|
||||
/// local variables are thread specific and not included.
|
||||
///
|
||||
/// \param[in] t_state New state to set
|
||||
///
|
||||
/// \b Example:
|
||||
@@ -563,7 +505,23 @@ namespace chaiscript
|
||||
m_engine.set_state(t_state.engine_state);
|
||||
}
|
||||
|
||||
/// \brief Adds a type, function or object to ChaiScript
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
return m_engine.get_locals();
|
||||
}
|
||||
|
||||
/// \brief Sets all of the locals for the current thread state.
|
||||
///
|
||||
/// \param[in] t_locals The map<name, value> set of variables to replace the current state with
|
||||
///
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
m_engine.set_locals(t_locals);
|
||||
}
|
||||
|
||||
/// \brief Adds a type, function or object to ChaiScript. Objects are added to the local thread state.
|
||||
/// \param[in] t_t Item to add
|
||||
/// \param[in] t_name Name of item to add
|
||||
/// \returns Reference to current ChaiScript object
|
||||
@@ -620,7 +578,7 @@ namespace chaiscript
|
||||
/// If no file can be found matching the search criteria and containing the appropriate entry point
|
||||
/// (the symbol mentioned above), an exception is thrown.
|
||||
///
|
||||
/// \throw chaiscript::exception::load_module_error In the event that no matching module can be found.
|
||||
/// \throw exception::load_module_error In the event that no matching module can be found.
|
||||
void load_module(const std::string &t_module_name)
|
||||
{
|
||||
std::vector<exception::load_module_error> errors;
|
||||
@@ -644,7 +602,7 @@ namespace chaiscript
|
||||
std::string name = m_modulepaths[i] + prefixes[j] + t_module_name + postfixes[k];
|
||||
load_module(t_module_name, name);
|
||||
return;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
} catch (const exception::load_module_error &e) {
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
@@ -666,7 +624,7 @@ namespace chaiscript
|
||||
errstring += itr->what();
|
||||
}
|
||||
|
||||
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
}
|
||||
|
||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||
@@ -700,7 +658,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
try {
|
||||
@@ -718,17 +676,19 @@ namespace chaiscript
|
||||
/// \tparam T Type to extract from the result value of the script execution
|
||||
/// \param[in] t_input Script to execute
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
||||
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return boxed_cast<T>(do_eval(t_input));
|
||||
return boxed_cast<T>(do_eval(t_input, t_filename));
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
@@ -741,14 +701,16 @@ namespace chaiscript
|
||||
///
|
||||
/// \param[in] t_input Script to execute
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
|
||||
{
|
||||
try {
|
||||
return do_eval(t_input);
|
||||
return do_eval(t_input, t_filename);
|
||||
} catch (Boxed_Value &bv) {
|
||||
if (t_handler) {
|
||||
t_handler->handle(bv);
|
||||
@@ -761,7 +723,7 @@ namespace chaiscript
|
||||
/// \param[in] t_filename File to load and parse.
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \return result of the script execution
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
try {
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
@@ -778,8 +740,8 @@ namespace chaiscript
|
||||
/// \param[in] t_filename File to load and parse.
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \return result of the script execution
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
/// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
/// \throw exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted
|
||||
/// to the requested type.
|
||||
template<typename T>
|
||||
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,6 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
@@ -34,6 +33,8 @@ namespace chaiscript
|
||||
, bin_alphabet
|
||||
, id_alphabet
|
||||
, white_alphabet
|
||||
, int_suffix_alphabet
|
||||
, float_suffix_alphabet
|
||||
, max_alphabet
|
||||
, lengthof_alphabet = 256
|
||||
};
|
||||
@@ -46,7 +47,7 @@ namespace chaiscript
|
||||
std::string m_multiline_comment_begin;
|
||||
std::string m_multiline_comment_end;
|
||||
std::string m_singleline_comment;
|
||||
std::shared_ptr<std::string> m_filename;
|
||||
boost::shared_ptr<std::string> m_filename;
|
||||
std::vector<AST_NodePtr> m_match_stack;
|
||||
bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet];
|
||||
|
||||
@@ -176,6 +177,17 @@ namespace chaiscript
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,6 +356,12 @@ namespace chaiscript
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--m_input_pos;
|
||||
@@ -372,6 +390,11 @@ namespace chaiscript
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
else {
|
||||
--m_input_pos;
|
||||
@@ -387,6 +410,14 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
void IntSuffix_() {
|
||||
while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet))
|
||||
{
|
||||
++m_input_pos;
|
||||
++m_col;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a binary value from input, without skipping initial whitespace
|
||||
*/
|
||||
@@ -420,6 +451,173 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
Boxed_Value buildFloat(const std::string &t_val)
|
||||
{
|
||||
bool float_ = false;
|
||||
bool long_ = false;
|
||||
|
||||
size_t i = t_val.size();
|
||||
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
char val = t_val[i-1];
|
||||
|
||||
if (val == 'f' || val == 'F')
|
||||
{
|
||||
float_ = true;
|
||||
} else if (val == 'l' || val == 'L') {
|
||||
long_ = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss(t_val.substr(0, i));
|
||||
|
||||
if (float_)
|
||||
{
|
||||
float f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
} else if (long_) {
|
||||
long double f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
} else {
|
||||
double f;
|
||||
ss >> f;
|
||||
return Boxed_Value(const_var(f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename IntType>
|
||||
Boxed_Value buildInt(const IntType &t_type, const std::string &t_val)
|
||||
{
|
||||
bool unsigned_ = false;
|
||||
bool long_ = false;
|
||||
bool longlong_ = false;
|
||||
|
||||
size_t i = t_val.size();
|
||||
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
char val = t_val[i-1];
|
||||
|
||||
if (val == 'u' || val == 'U')
|
||||
{
|
||||
unsigned_ = true;
|
||||
} else if (val == 'l' || val == 'L') {
|
||||
if (long_)
|
||||
{
|
||||
longlong_ = true;
|
||||
}
|
||||
|
||||
long_ = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream ss(t_val.substr(0, i));
|
||||
ss >> t_type;
|
||||
|
||||
std::stringstream testu(t_val.substr(0, i));
|
||||
boost::uint64_t u;
|
||||
testu >> t_type >> u;
|
||||
|
||||
bool unsignedrequired = false;
|
||||
size_t size = sizeof(int) * 8;
|
||||
|
||||
if ((u >> (sizeof(int) * 8)) > 0)
|
||||
{
|
||||
//requires something bigger than int
|
||||
long_ = true;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(sizeof(long) == sizeof(boost::uint64_t) || sizeof(long) * 2 == sizeof(boost::uint64_t));
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||
// statment in this compiler / architecture
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if ( sizeof(long) < sizeof(boost::uint64_t) && (u >> ((sizeof(boost::uint64_t) - sizeof(long)) * 8)) > 0)
|
||||
{
|
||||
//requires something bigger than long
|
||||
longlong_ = true;
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
if (longlong_)
|
||||
{
|
||||
size = sizeof(boost::int64_t) * 8;
|
||||
} else if (long_) {
|
||||
size = sizeof(long) * 8;
|
||||
}
|
||||
|
||||
if ( (u >> (size - 1)) > 0)
|
||||
{
|
||||
unsignedrequired = true;
|
||||
}
|
||||
|
||||
if (unsignedrequired && !unsigned_)
|
||||
{
|
||||
if (t_type == &std::hex || t_type == &std::oct)
|
||||
{
|
||||
// with hex and octal we are happy to just make it unsigned
|
||||
unsigned_ = true;
|
||||
} else {
|
||||
// with decimal we must bump it up to the next size
|
||||
if (long_)
|
||||
{
|
||||
longlong_ = true;
|
||||
} else if (!long_ && !longlong_) {
|
||||
long_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unsigned_)
|
||||
{
|
||||
if (longlong_)
|
||||
{
|
||||
boost::uint64_t val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else if (long_) {
|
||||
unsigned long val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else {
|
||||
unsigned int val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
}
|
||||
} else {
|
||||
if (longlong_)
|
||||
{
|
||||
boost::int64_t val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else if (long_) {
|
||||
long val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
} else {
|
||||
int val;
|
||||
ss >> val;
|
||||
return Boxed_Value(const_var(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a number from the input, detecting if it's an integer or floating point
|
||||
*/
|
||||
@@ -436,19 +634,14 @@ namespace chaiscript
|
||||
if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) {
|
||||
if (Hex_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
std::stringstream ss(match);
|
||||
unsigned int temp_int;
|
||||
ss >> std::hex >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << static_cast<int>(temp_int);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::hex, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
if (Binary_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
int temp_int = 0;
|
||||
boost::int64_t temp_int = 0;
|
||||
size_t pos = 0, end = match.length();
|
||||
|
||||
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
|
||||
@@ -459,32 +652,36 @@ namespace chaiscript
|
||||
++pos;
|
||||
}
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << temp_int;
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i;
|
||||
if (match.length() <= sizeof(int) * 8)
|
||||
{
|
||||
i = Boxed_Value(const_var(int(temp_int)));
|
||||
} else {
|
||||
i = Boxed_Value(const_var(temp_int));
|
||||
}
|
||||
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
if (Float_()) {
|
||||
std::string match(start, m_input_pos);
|
||||
AST_NodePtr t(new eval::Float_AST_Node(match, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value f = buildFloat(match);
|
||||
AST_NodePtr t(new eval::Float_AST_Node(match, f, AST_Node_Type::Float, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
IntSuffix_();
|
||||
std::string match(start, m_input_pos);
|
||||
if ((match.size() > 0) && (match[0] == '0')) {
|
||||
std::stringstream ss(match);
|
||||
unsigned int temp_int;
|
||||
ss >> std::oct >> temp_int;
|
||||
|
||||
std::ostringstream out_int;
|
||||
out_int << int(temp_int);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(out_int.str(), AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::oct, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
else {
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
Boxed_Value i = buildInt(std::dec, match);
|
||||
AST_NodePtr t(new eval::Int_AST_Node(match, i, AST_Node_Type::Int, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
m_match_stack.push_back(t);
|
||||
}
|
||||
return true;
|
||||
@@ -1505,7 +1702,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a curly-brace C-style block from input
|
||||
*/
|
||||
@@ -1632,10 +1829,10 @@ namespace chaiscript
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("auto") || Keyword("var")) {
|
||||
if (Keyword("var")) {
|
||||
retval = true;
|
||||
|
||||
if (!(Reference() || Id(true))) {
|
||||
if (!Id(true)) {
|
||||
throw exception::eval_error("Incomplete variable declaration", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
@@ -1691,7 +1888,7 @@ namespace chaiscript
|
||||
retval = true;
|
||||
Container_Arg_List();
|
||||
if (!Char(']')) {
|
||||
throw exception::eval_error("Missing closing brace '}' in container initializer", File_Position(m_line, m_col), *m_filename);
|
||||
throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) {
|
||||
if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) {
|
||||
@@ -1712,25 +1909,6 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool Reference() {
|
||||
bool retval = false;
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Symbol("&", false)) {
|
||||
retval = true;
|
||||
|
||||
if (!Id(true)) {
|
||||
throw exception::eval_error("Incomplete '&' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(
|
||||
new eval::Reference_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a unary prefixed expression from input
|
||||
*/
|
||||
@@ -1793,15 +1971,6 @@ namespace chaiscript
|
||||
|
||||
build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top);
|
||||
}
|
||||
else if (Char('&', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -2088,11 +2257,6 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Equation()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
@@ -2106,6 +2270,11 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else {
|
||||
has_more = false;
|
||||
}
|
||||
@@ -2122,7 +2291,7 @@ namespace chaiscript
|
||||
m_input_end = t_input.end();
|
||||
m_line = 1;
|
||||
m_col = 1;
|
||||
m_filename = std::shared_ptr<std::string>(new std::string(t_fname));
|
||||
m_filename = boost::shared_ptr<std::string>(new std::string(t_fname));
|
||||
|
||||
if ((t_input.size() > 1) && (t_input[0] == '#') && (t_input[1] == '!')) {
|
||||
while ((m_input_pos != m_input_end) && (!Eol())) {
|
||||
|
@@ -54,8 +54,8 @@ def push_front(container, x) : call_exists(push_front_ref, container, x) { conta
|
||||
def insert_at(container, pos, x) { container.insert_ref_at(pos, clone(x)); } \n\
|
||||
# Returns the reverse of the given container\n\
|
||||
def reverse(container) {\n\
|
||||
auto retval = new(container); \n\
|
||||
auto r = range(container); \n\
|
||||
var retval = new(container); \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval.push_back(r.back()); \n\
|
||||
r.pop_back(); \n\
|
||||
@@ -82,7 +82,7 @@ def retro::pop_front() { pop_back(this.m_range) } \n\
|
||||
def retro::empty() { empty(this.m_range); } \n\
|
||||
# Performs the second value function over the container first value\n\
|
||||
def for_each(container, func) : call_exists(range, container) { \n\
|
||||
auto t_range = range(container); \n\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
func(t_range.front()); \n\
|
||||
t_range.pop_front(); \n\
|
||||
@@ -93,7 +93,7 @@ def back_inserter(container) { \n\
|
||||
}\n\
|
||||
\n\
|
||||
def contains(container, item, compare_func) : call_exists(range, container) { \n\
|
||||
auto t_range = range(container); \n\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
if ( compare_func(t_range.front(), item) ) { return true; } \n\
|
||||
t_range.pop_front(); \n\
|
||||
@@ -102,7 +102,7 @@ def contains(container, item, compare_func) : call_exists(range, container) { \n
|
||||
} \n\
|
||||
def contains(container, item) { return contains(container, item, eq) } \n\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
auto range = range(container); \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(func(range.front())); \n\
|
||||
range.pop_front(); \n\
|
||||
@@ -110,14 +110,14 @@ def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Performs the second value function over the container first value. Creates a new container with the results\n\
|
||||
def map(container, func) { \n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
map(container, func, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.\n\
|
||||
def foldl(container, func, initial) : call_exists(range, container){ \n\
|
||||
auto retval = initial; \n\
|
||||
auto range = range(container); \n\
|
||||
var retval = initial; \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval = (func(range.front(), retval)); \n\
|
||||
range.pop_front(); \n\
|
||||
@@ -130,9 +130,9 @@ def sum(container) { foldl(container, `+`, 0.0) } \n\
|
||||
def product(container) { foldl(container, `*`, 1.0) } \n\
|
||||
# Returns a new container with the elements of the first value concatenated with the elements of the second value\n\
|
||||
def concat(x, y) : call_exists(clone, x) { \n\
|
||||
auto retval = x; \n\
|
||||
auto inserter = back_inserter(retval); \n\
|
||||
auto range = range(y); \n\
|
||||
var retval = x; \n\
|
||||
var inserter = back_inserter(retval); \n\
|
||||
var range = range(y); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
@@ -140,8 +140,8 @@ def concat(x, y) : call_exists(clone, x) { \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def take(container, num, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto i = num; \n\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
@@ -150,12 +150,12 @@ def take(container, num, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements taken from the container\n\
|
||||
def take(container, num) {\n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
take(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def take_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty()) && f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
@@ -163,13 +163,13 @@ def take_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements match the second value function\n\
|
||||
def take_while(container, f) {\n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
take_while(container, f, back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def drop(container, num, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto i = num; \n\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
@@ -181,12 +181,12 @@ def drop(container, num, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements dropped from the given container \n\
|
||||
def drop(container, num) {\n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
drop(container, num, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty())&& f(r.front())) { \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
@@ -197,14 +197,14 @@ def drop_while(container, f, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements dropped that match the second value function\n\
|
||||
def drop_while(container, f) {\n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
drop_while(container, f, back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.\n\
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
auto retval = r.front(); \n\
|
||||
var r = range(container); \n\
|
||||
var retval = r.front(); \n\
|
||||
r.pop_front(); \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
@@ -216,8 +216,8 @@ def reduce(container, func) : container.size() >= 2 && call_exists(range, contai
|
||||
} \n\
|
||||
# Returns a string of the elements in container delimited by the second value string\n\
|
||||
def join(container, delim) { \n\
|
||||
auto retval = ""; \n\
|
||||
auto range = range(container); \n\
|
||||
var retval = ""; \n\
|
||||
var range = range(container); \n\
|
||||
if (!range.empty()) { \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
@@ -230,7 +230,7 @@ def join(container, delim) { \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def filter(container, f, inserter) : call_exists(range, container) { \n\
|
||||
auto r = range(container); \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
if (f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
@@ -240,12 +240,12 @@ def filter(container, f, inserter) : call_exists(range, container) { \n\
|
||||
} \n\
|
||||
# Returns a new Vector which match the second value function\n\
|
||||
def filter(container, f) { \n\
|
||||
auto retval = new(container); \n\
|
||||
var retval = new(container); \n\
|
||||
filter(container, f, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def generate_range(x, y, inserter) { \n\
|
||||
auto i = x; \n\
|
||||
var i = x; \n\
|
||||
while (i <= y) { \n\
|
||||
inserter(i); \n\
|
||||
++i; \n\
|
||||
@@ -253,17 +253,17 @@ def generate_range(x, y, inserter) { \n\
|
||||
} \n\
|
||||
# Returns a new Vector which represents the range from the first value to the second value\n\
|
||||
def generate_range(x, y) { \n\
|
||||
auto retval = Vector(); \n\
|
||||
var retval = Vector(); \n\
|
||||
generate_range(x,y,back_inserter(retval)); \n\
|
||||
retval; \n\
|
||||
}\n\
|
||||
# Returns a new Vector with the first value to the second value as its elements\n\
|
||||
def collate(x, y) { \n\
|
||||
return [x, y]; \n\
|
||||
[x, y]; \n\
|
||||
} \n\
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) { \n\
|
||||
auto r_x = range(x); \n\
|
||||
auto r_y = range(y); \n\
|
||||
var r_x = range(x); \n\
|
||||
var r_y = range(y); \n\
|
||||
while (!r_x.empty() && !r_y.empty()) { \n\
|
||||
inserter(f(r_x.front(), r_y.front())); \n\
|
||||
r_x.pop_front(); \n\
|
||||
@@ -272,7 +272,7 @@ def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y)
|
||||
} \n\
|
||||
# Returns a new Vector which joins matching elements of the second and third value with the first value function\n\
|
||||
def zip_with(f, x, y) { \n\
|
||||
auto retval = Vector(); \n\
|
||||
var retval = Vector(); \n\
|
||||
zip_with(f,x,y,back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
@@ -314,7 +314,7 @@ def string::trim() { \n\
|
||||
ltrim(rtrim(this)); \n\
|
||||
} \n\
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") { \n\
|
||||
auto range = range(container); \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
if (compare_func(range.front(), value)) { \n\
|
||||
return range; \n\
|
||||
|
@@ -8,33 +8,90 @@
|
||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||
|
||||
#include "../chaiscript.hpp"
|
||||
#include <boost/preprocessor.hpp>
|
||||
#include <string>
|
||||
|
||||
#define CHAISCRIPT_MODULE(_info) BOOST_PP_SEQ_ELEM(0, _info)
|
||||
|
||||
#define CHAISCRIPT_CLASS_ELEM(_info) BOOST_PP_SEQ_ELEM(1, _info)
|
||||
|
||||
#define CHAISCRIPT_METHOD(_info, _method) & CHAISCRIPT_CLASS_ELEM(_info) :: BOOST_PP_SEQ_ELEM(0, _method)
|
||||
|
||||
#define CHAISCRIPT_METHOD_NAME(_info, _method) \
|
||||
BOOST_PP_SEQ_ELEM(3, _info) (BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0, _method ) ) )
|
||||
|
||||
#define CHAISCRIPT_CLASS_NAME(_info) \
|
||||
BOOST_PP_SEQ_ELEM(2, _info) (BOOST_PP_STRINGIZE(CHAISCRIPT_CLASS_ELEM(_info) ) )
|
||||
|
||||
#define CHAISCRIPT_METHOD_SIGNATURE_PART(_r, _info, _i, _method_part) \
|
||||
BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(_i, 1), < _method_part > )
|
||||
|
||||
#define CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
|
||||
BOOST_PP_SEQ_FOR_EACH_I(CHAISCRIPT_METHOD_SIGNATURE_PART, _info, _method)
|
||||
|
||||
#define CHAISCRIPT_CLASS_CONSTRUCTOR(_r, _info, _constructor) \
|
||||
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::constructor<_constructor>() BOOST_PP_COMMA() CHAISCRIPT_CLASS_NAME(_info) BOOST_PP_RPAREN() ;
|
||||
|
||||
#define CHAISCRIPT_CLASS_METHOD(_r, _info, _method) \
|
||||
CHAISCRIPT_MODULE(_info) ->add BOOST_PP_LPAREN() chaiscript::fun CHAISCRIPT_METHOD_SIGNATURE(_info, _method) \
|
||||
BOOST_PP_LPAREN() CHAISCRIPT_METHOD(_info, _method) BOOST_PP_RPAREN() BOOST_PP_COMMA() CHAISCRIPT_METHOD_NAME(_info, _method)BOOST_PP_RPAREN() ;
|
||||
|
||||
#define CHAISCRIPT_CLASS_CONSTRUCTORS(_info, _constructors) \
|
||||
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_CONSTRUCTOR, _info, _constructors)
|
||||
|
||||
#define CHAISCRIPT_CLASS_METHODS(_info, _methods) \
|
||||
BOOST_PP_SEQ_FOR_EACH(CHAISCRIPT_CLASS_METHOD, _info, _methods)
|
||||
|
||||
#define CHAISCRIPT_CLASS_EX(_module, _class_name, _class_name_translator, _method_name_translator, _constructors, _methods) \
|
||||
{ \
|
||||
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
|
||||
CHAISCRIPT_CLASS_CONSTRUCTORS((_module)(_class_name)(_class_name_translator), _constructors) \
|
||||
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
|
||||
}
|
||||
|
||||
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, _class_name_translator, _method_name_translator, _methods) \
|
||||
{ \
|
||||
_module->add(chaiscript::user_type<_class_name>(), _class_name_translator (BOOST_PP_STRINGIZE(_class_name))); \
|
||||
CHAISCRIPT_CLASS_METHODS((_module)(_class_name)(_class_name_translator)(_method_name_translator), _methods) \
|
||||
}
|
||||
|
||||
#define CHAISCRIPT_CLASS(_module, _class_name, _constructors, _methods) \
|
||||
CHAISCRIPT_CLASS_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
||||
chaiscript::utility::method_name_translator, _constructors, _methods)
|
||||
|
||||
#define CHAISCRIPT_CLASS_NO_CONSTRUCTOR(_module, _class_name, _methods) \
|
||||
CHAISCRIPT_CLASS_NO_CONSTRUCTOR_EX(_module, _class_name, chaiscript::utility::class_name_translator, \
|
||||
chaiscript::utility::method_name_translator, _methods)
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
/// \brief Classes and functions which provide general utility to the end user.
|
||||
namespace utility
|
||||
{
|
||||
|
||||
template<typename Class, typename ModuleType>
|
||||
void add_class(ModuleType &t_module,
|
||||
const std::string &t_classname,
|
||||
const std::vector<chaiscript::Proxy_Function> &t_constructors,
|
||||
const std::vector<std::pair<chaiscript::Proxy_Function, std::string>> &t_funcs)
|
||||
inline std::string class_name_translator(const std::string &t_name)
|
||||
{
|
||||
size_t colon = t_name.rfind("::");
|
||||
if (colon != std::string::npos)
|
||||
{
|
||||
t_module.add(chaiscript::user_type<Class>(), t_classname);
|
||||
|
||||
for(const chaiscript::Proxy_Function &ctor: t_constructors)
|
||||
{
|
||||
t_module.add(ctor, t_classname);
|
||||
}
|
||||
|
||||
for(auto fun: t_funcs)
|
||||
{
|
||||
t_module.add(fun.first, fun.second);
|
||||
}
|
||||
|
||||
return t_name.substr(colon+2, std::string::npos);
|
||||
} else {
|
||||
return t_name;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string method_name_translator(const std::string &t_name)
|
||||
{
|
||||
size_t namestart = t_name.rfind("operator");
|
||||
namestart = (namestart == std::string::npos)?0:namestart+strlen("operator");
|
||||
|
||||
if (namestart == 0)
|
||||
{
|
||||
namestart = t_name.rfind("::");
|
||||
namestart = (namestart == std::string::npos)?0:namestart+strlen("::");
|
||||
}
|
||||
|
||||
return t_name.substr(namestart, std::string::npos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
82
readme.md
Normal file
82
readme.md
Normal file
@@ -0,0 +1,82 @@
|
||||
ChaiScript
|
||||
|
||||
http://www.chaiscript.com
|
||||
|
||||
(c) 2009-2012 Jason Turner and Jonathan Turner
|
||||
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the
|
||||
ground up to directly target C++ and take advantage of modern C++ development
|
||||
techniques, working with the developer like he expects it to work. Being a
|
||||
native C++ application, it has some advantages over existing embedded scripting
|
||||
languages:
|
||||
|
||||
1) It uses a header-only approach, which makes it easy to integrate with
|
||||
existing projects.
|
||||
2) It maintains type safety between your C++ application and the user scripts.
|
||||
3) It supports a variety of C++ techniques including callbacks, overloaded
|
||||
functions, class methods, and stl containers.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
ChaiScript requires a recent version of Boost (http://www.boost.org) to build.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
* Add the ChaiScript include directory to your project's header search path
|
||||
* Add `#include <chaiscript/chaiscript.hpp>` to your source file
|
||||
* Instantiate the ChaiScript engine in your application. For example, create
|
||||
a new engine with the name `chai` like so: `chaiscript::ChaiScript chai`
|
||||
|
||||
Once instantiated, the engine is ready to start running ChaiScript source. You
|
||||
have two main options for processing ChaiScript source: a line at a time using
|
||||
`chai.eval(string)` and a file at a time using `chai.eval_file(fname)`
|
||||
|
||||
To make functions in your C++ code visible to scripts, they must be registered
|
||||
with the scripting engine. To do so, call add:
|
||||
|
||||
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
||||
|
||||
Once registered the function will be visible to scripts as "my_function_name"
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some
|
||||
modifications to make it easier to use. For usage examples see the "samples"
|
||||
directory, and for more in-depth look at the language, the unit tests in the
|
||||
"unittests" directory cover the most ground.
|
||||
|
||||
For examples of how to register parts of your C++ application, see
|
||||
"example.cpp" in the "src" directory. Example.cpp is verbose and shows every
|
||||
possible way of working with the library. For further documentation generate
|
||||
the doxygen documentation in the build folder or see the website
|
||||
http://www.chaiscript.com.
|
||||
|
||||
|
||||
The shortest complete example possible follows:
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
||||
|
||||
|
55
readme.txt
55
readme.txt
@@ -1,55 +0,0 @@
|
||||
ChaiScript
|
||||
http://www.chaiscript.com
|
||||
(c) 2009-2012 Jason Turner and Jonathan Turner
|
||||
Release under the BSD license, see "license.txt" for details.
|
||||
|
||||
[Introduction]
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques, working with the developer like he expects it to work. Being a native C++ application, it has some advantages over existing embedded scripting languages:
|
||||
|
||||
1) It uses a header-only approach, which makes it easy to integrate with existing projects.
|
||||
2) It maintains type safety between your C++ application and the user scripts.
|
||||
3) It supports a variety of C++ techniques including callbacks, overloaded functions, class methods, and stl containers.
|
||||
|
||||
[Requirements]
|
||||
|
||||
ChaiScript requires a C++11 compiler to build with support for variadic templates. It has been tested with gcc 4.7 and clang 3.1 (with libcxx).
|
||||
|
||||
[Usage]
|
||||
|
||||
* Add the ChaiScript include directory to your project's header search path
|
||||
* Add "#include <chaiscript/chaiscript.hpp> to your source file
|
||||
* Instantiate the ChaiScript engine in your application. For example, create a new engine with the name 'chai' like so: "chaiscript::ChaiScript chai"
|
||||
|
||||
Once instantiated, the engine is ready to start running ChaiScript source. You have two main options for processing ChaiScript source: a line at a time using "chai.evaluate_string(string)" and a file at a time using "chai.evaluate_file(fname)"
|
||||
|
||||
To make functions in your C++ code visible to scripts, they must be registered with the scripting engine. To do so, call add:
|
||||
|
||||
chai.add(chaiscript::fun(&my_function), "my_function_name");
|
||||
|
||||
Once registered the function will be visible to scripts as "my_function_name"
|
||||
|
||||
[Examples]
|
||||
|
||||
ChaiScript is similar to ECMAScript (aka JavaScript(tm)), but with some modifications to make it easier to use. For usage examples see the "samples" directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground.
|
||||
|
||||
For examples of how to register parts of your C++ application, see "example.cpp" in the "src" directory. Example.cpp is verbose and shows every possible way of working with the library. For further documentation generate the doxygen documentation in the build folder or see the website http://www.chaiscript.com.
|
||||
|
||||
The shortest complete example possible follows:
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chai.add(chaiscript::fun(&function), "function");
|
||||
|
||||
double d = chai.eval<double>("function(3, 4.75);");
|
||||
}
|
@@ -1,6 +1,10 @@
|
||||
Changes since 4.1.0
|
||||
* Fix missed gcc build error in 4.1.0
|
||||
|
||||
Changes since 4.0.0
|
||||
* Dropped boost in favor of C++11
|
||||
* Separated out stdlib to make more options for compile time improvements
|
||||
* Fix sizing of numeric constants to match that of the C++ standard
|
||||
* Add support for u,ll,l,f suffixes for numeric constants
|
||||
* Siginificant improvement in error reporting
|
||||
|
||||
Changes since 3.1.0
|
||||
* svenstaro: Unused variables and CMake consistency fixes
|
||||
|
@@ -7,17 +7,19 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/dispatchkit/function_call.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
void log(const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
|
||||
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] " << msg << std::endl;
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
|
||||
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
@@ -38,7 +40,7 @@ void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
|
||||
struct System
|
||||
{
|
||||
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
|
||||
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
||||
|
||||
void add_callback(const std::string &t_name,
|
||||
const chaiscript::Proxy_Function &t_func)
|
||||
@@ -50,7 +52,7 @@ struct System
|
||||
void do_callbacks(const std::string &inp)
|
||||
{
|
||||
log("Running Callbacks: " + inp);
|
||||
for (std::map<std::string, std::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
|
||||
for (std::map<std::string, boost::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
|
||||
itr != m_callbacks.end();
|
||||
++itr)
|
||||
{
|
||||
@@ -59,7 +61,7 @@ struct System
|
||||
}
|
||||
};
|
||||
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
@@ -85,7 +87,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
// Let's use chaiscript to add a new lambda callback to our system.
|
||||
// The function "{ 'Callback1' + x }" is created in chaiscript and passed into our C++ application
|
||||
// in the "add_callback" function of struct System the chaiscript function is converted into a
|
||||
// std::function, so it can be handled and called easily and type-safely
|
||||
// boost::function, so it can be handled and called easily and type-safely
|
||||
chai.eval("system.add_callback(\"#1\", fun(x) { \"Callback1 \" + x });");
|
||||
|
||||
// Because we are sharing the "system" object with the chaiscript engine we have equal
|
||||
@@ -106,14 +108,14 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
// A shortcut to using eval is just to use the chai operator()
|
||||
chai("log(\"Test Module\", \"Test Message\");");
|
||||
|
||||
//Finally, it is possible to register any std::function as a system function, in this
|
||||
//Finally, it is possible to register any boost::function as a system function, in this
|
||||
//way, we can, for instance add a bound member function to the system
|
||||
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
chai.add(fun(&System::do_callbacks, boost::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
|
||||
std::function<void ()> caller = chai.eval<std::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
|
||||
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
|
||||
caller();
|
||||
|
||||
|
||||
@@ -137,13 +139,13 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
||||
//Creating a functor on the stack and using it immediatly
|
||||
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
int x = chai.eval<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << x;
|
||||
log("Functor test output", ss.str());
|
||||
|
||||
chai.add(var(std::shared_ptr<int>()), "nullvar");
|
||||
chai.add(var(boost::shared_ptr<int>()), "nullvar");
|
||||
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
|
||||
|
||||
// test the global const action
|
||||
@@ -165,7 +167,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//Dynamic objects test
|
||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Function("TestType", fun(&hello_world))), "hello_world");
|
||||
chai.add(chaiscript::Proxy_Function(new dispatch::detail::Dynamic_Object_Constructor("TestType", fun(&hello_constructor))), "TestType");
|
||||
// chai.add(fun(std::function<Boxed_Value (dispatch::Dynamic_Object &)>(std::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", std::placeholders::_1))), "attr");
|
||||
// chai.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
|
||||
|
||||
chai.eval("var x = TestType()");
|
||||
// chai.eval("x.attr = \"hi\"");
|
||||
|
@@ -1,14 +1,13 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
#include "chaiscript/chaiscript.hpp"
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
std::string get_next_command() {
|
||||
#ifdef READLINE_AVAILABLE
|
||||
@@ -31,32 +30,30 @@ void fuction(void)
|
||||
|
||||
class test
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
chaiscript::ChaiScript::State backupState;
|
||||
|
||||
ChaiScript chai;
|
||||
ChaiScript::State backupState;
|
||||
public:
|
||||
test()
|
||||
: chai(chaiscript::Std_Lib::library())
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
~test(){}
|
||||
test()
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
~test(){}
|
||||
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::fun(&fuction),"Whatever()");
|
||||
}
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(fun(&fuction),"Whatever()");
|
||||
}
|
||||
|
||||
void RunFile(std::string sFile)
|
||||
{
|
||||
try {
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
void RunFile(std::string sFile)
|
||||
{
|
||||
try {
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@@ -1,21 +0,0 @@
|
||||
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_chaiscript_stdlib()
|
||||
{
|
||||
return chaiscript::Std_Lib::library();
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
52
src/main.cpp
52
src/main.cpp
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
@@ -20,7 +20,7 @@ char* readline(const char* p)
|
||||
std::string retval;
|
||||
std::cout << p ;
|
||||
std::getline(std::cin, retval);
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
return std::cin.eof() ? NULL : _strdup(retval.c_str());
|
||||
#else
|
||||
return std::cin.eof() ? NULL : strdup(retval.c_str());
|
||||
@@ -52,7 +52,7 @@ void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
bool throws_exception(const boost::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
@@ -63,7 +63,7 @@ bool throws_exception(const std::function<void ()> &f)
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
@@ -80,21 +80,18 @@ std::string get_next_command() {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw ) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos+1, std::string::npos);
|
||||
}
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos+1, std::string::npos);
|
||||
}
|
||||
retval = val;
|
||||
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
@@ -127,7 +124,7 @@ void interactive(chaiscript::ChaiScript& chai)
|
||||
//Then, we try to print the result of the evaluation to the user
|
||||
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
|
||||
try {
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
std::cout << chai.eval<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
@@ -152,7 +149,7 @@ int main(int argc, char *argv[])
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
@@ -160,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -233,18 +230,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
if (ee.call_stack.size() > 0) {
|
||||
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
|
||||
for (size_t j = 1; j < ee.call_stack.size(); ++j) {
|
||||
if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
|
||||
&& ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@@ -1,41 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2010, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <thread>
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c)
|
||||
{
|
||||
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
|
||||
std::stringstream ss;
|
||||
ss << "MyVar" << rand();
|
||||
c.add(chaiscript::var(5), ss.str());
|
||||
c("use(\"work.chai\"); do_chai_work(10000);");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::string input;
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
//chai.add_shared_object(chaiscript::Boxed_Value(10000), "num_iterations");
|
||||
|
||||
std::vector<std::shared_ptr<std::thread> > threads;
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads.push_back(std::shared_ptr<std::thread>(new std::thread(std::bind(do_work, std::ref(chai)))));
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,12 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <chaiscript/utility/utility.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -16,11 +14,11 @@
|
||||
|
||||
bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return bool(pf->get_parse_tree());
|
||||
return pf->get_parse_tree();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -28,8 +26,8 @@ bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
|
||||
chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
@@ -53,52 +51,46 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
|
||||
|
||||
m->add(chaiscript::base_class<std::exception, chaiscript::exception::eval_error>());
|
||||
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::exception::eval_error>(*m,
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(&chaiscript::exception::eval_error::call_stack), "call_stack"} }
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<chaiscript::File_Position>(*m,
|
||||
"File_Position",
|
||||
{ constructor<File_Position()>(),
|
||||
constructor<File_Position(int, int)>() },
|
||||
{ {fun(&File_Position::line), "line"},
|
||||
{fun(&File_Position::column), "column"} }
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<AST_Node>(*m,
|
||||
"AST_Node",
|
||||
{ },
|
||||
{ {fun(&AST_Node::text), "text"},
|
||||
{fun(&AST_Node::identifier), "identifier"},
|
||||
{fun(&AST_Node::filename), "filename"},
|
||||
{fun(&AST_Node::start), "start"},
|
||||
{fun(&AST_Node::end), "end"},
|
||||
{fun(&AST_Node::internal_to_string), "internal_to_string"},
|
||||
{fun(&AST_Node::children), "children"},
|
||||
{fun(&AST_Node::replace_child), "replace_child"}
|
||||
}
|
||||
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
|
||||
chaiscript::exception::eval_error,
|
||||
((reason))
|
||||
((call_stack))
|
||||
);
|
||||
|
||||
chaiscript::utility::add_class<parser::ChaiScript_Parser>(*m,
|
||||
"ChaiScript_Parser",
|
||||
{ constructor<parser::ChaiScript_Parser ()>() },
|
||||
{ {fun(&parser::ChaiScript_Parser::parse), "parse"},
|
||||
{fun(&parser::ChaiScript_Parser::ast), "ast"} }
|
||||
);
|
||||
CHAISCRIPT_CLASS( m,
|
||||
chaiscript::File_Position,
|
||||
(chaiscript::File_Position())
|
||||
(chaiscript::File_Position(int,int)),
|
||||
((line))
|
||||
((column))
|
||||
);
|
||||
|
||||
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
|
||||
chaiscript::AST_Node,
|
||||
((text))
|
||||
((identifier))
|
||||
((filename))
|
||||
((start))
|
||||
((end))
|
||||
((internal_to_string))
|
||||
((children))
|
||||
((replace_child))
|
||||
);
|
||||
|
||||
CHAISCRIPT_CLASS( m,
|
||||
chaiscript::parser::ChaiScript_Parser,
|
||||
(chaiscript::parser::ChaiScript_Parser ()),
|
||||
((parse))
|
||||
((ast))
|
||||
);
|
||||
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -1,12 +1,11 @@
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -17,6 +16,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extr
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -42,7 +42,7 @@ int *get_new_int()
|
||||
|
||||
// MSVC doesn't like that we are using C++ return types from our C declared module
|
||||
// but this is the best way to do it for cross platform compatibility
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -82,6 +82,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -1,10 +0,0 @@
|
||||
def do_chai_work(num_iters)
|
||||
{
|
||||
var i = 0;
|
||||
for (var k = 0; k<num_iters * 10; ++k)
|
||||
{
|
||||
i += k;
|
||||
}
|
||||
|
||||
print(i);
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 = 2 } );
|
||||
assert_throws("Mismatched types in equation, lhs is const.", fun() { 1 + 2 = 2 } );
|
@@ -1,2 +0,0 @@
|
||||
var prod = bind(foldl, _, `*`, 1.0)
|
||||
assert_equal(60, prod([3, 4, 5]))
|
@@ -1,34 +0,0 @@
|
||||
|
||||
def add(x, y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
assert_equal(2, add.get_arity());
|
||||
|
||||
var b = bind(add, 2, _);
|
||||
|
||||
assert_equal(1, b.get_arity());
|
||||
|
||||
var c = bind(b, 3);
|
||||
|
||||
assert_equal(0, c.get_arity());
|
||||
|
||||
assert_equal(6, b(4));
|
||||
assert_equal(5, c());
|
||||
|
||||
def concat2(a,b,c,d)
|
||||
{
|
||||
return to_string(a) + to_string(b) + to_string(c) + to_string(d);
|
||||
}
|
||||
|
||||
var d = bind(concat2, _, " Hello ", _, " World");
|
||||
assert_equal(2, d.get_arity());
|
||||
|
||||
assert_equal("1 Hello 3 World", d(1,3));
|
||||
|
||||
var e = bind(`<`, _, 5);
|
||||
var types = e.get_param_types();
|
||||
assert_equal(2, types.size());
|
||||
assert_equal(true, types[0].bare_equal(bool_type));
|
||||
|
@@ -1 +0,0 @@
|
||||
{print("hello")}
|
@@ -1 +0,0 @@
|
||||
assert_equal(false, !true)
|
@@ -1,7 +0,0 @@
|
||||
var i = 0
|
||||
while (i < 10) {
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert_equal(5, i);
|
@@ -1 +0,0 @@
|
||||
assert_equal("b", to_string('b'))
|
@@ -1,7 +0,0 @@
|
||||
assert_equal(true, 1.is_var_const());
|
||||
assert_equal(false, 1.is_var_reference());
|
||||
assert_equal(true, 1.is_var_pointer());
|
||||
assert_equal(false, 1.is_var_null());
|
||||
assert_equal(false, 1.is_var_undef());
|
||||
var i;
|
||||
assert_equal(true, i.is_var_undef());
|
@@ -1,3 +0,0 @@
|
||||
var v = collate(1, 2)
|
||||
assert_equal(1, v[0])
|
||||
assert_equal(2, v[1])
|
@@ -1 +0,0 @@
|
||||
assert_equal(false, 1 > 2);
|
@@ -1 +0,0 @@
|
||||
assert_equal(true, 1 < 2)
|
@@ -1,5 +0,0 @@
|
||||
var v = concat([1, 2], [3, 4]);
|
||||
|
||||
assert_equal(4, v.size());
|
||||
assert_equal(1, v[0]);
|
||||
assert_equal(4, v[3]);
|
@@ -1,4 +0,0 @@
|
||||
//If the following succeeds, the test passes
|
||||
|
||||
|
||||
"Hello World".for_each(fun(x) { print(x) } )
|
@@ -1 +0,0 @@
|
||||
assert_equal("3.5bob", 3.5.to_string() + "bob");
|
@@ -1 +0,0 @@
|
||||
assert_equal("3bob", 3.to_string + "bob")
|
@@ -1 +0,0 @@
|
||||
assert_equal(6.8, "3.5".to_double() + 3.3)
|
@@ -1 +0,0 @@
|
||||
assert_equal(8, "4".to_int() + 4)
|
@@ -1,11 +0,0 @@
|
||||
var a = [1,2,3, [4,5,6] ]
|
||||
|
||||
assert_equal(a[3][0], 4)
|
||||
|
||||
|
||||
def Test::Test() { this.a = [1,2,3]; }
|
||||
attr Test::a;
|
||||
|
||||
var t = Test();
|
||||
|
||||
assert_equal(t.a[0], 1)
|
@@ -1,11 +0,0 @@
|
||||
assert_equal(`==`, `==`);
|
||||
assert_not_equal(`==`, `<`);
|
||||
assert_equal(`<`.get_arity(), 2);
|
||||
assert_equal(`+`.get_annotation(), "Multiple method dispatch function wrapper.");
|
||||
assert_equal(get_arity.get_contained_functions().size(), 0);
|
||||
assert_equal(get_arity.get_arity(), 1);
|
||||
assert_equal(get_arity.get_param_types().size(), 2);
|
||||
|
||||
var paramtypes = get_arity.get_param_types();
|
||||
|
||||
assert_equal(true, paramtypes[1].bare_equal(Function_type));
|
@@ -1 +0,0 @@
|
||||
assert_equal([3,4], drop([1, 2, 3, 4], 2))
|
@@ -1 +0,0 @@
|
||||
assert_equal([2, 3], drop_while([1, 2, 3], odd))
|
@@ -1,4 +0,0 @@
|
||||
var x=.5
|
||||
assert_equal(.5, x)
|
||||
var y=-.5
|
||||
assert_equal(-.5, y)
|
@@ -1 +0,0 @@
|
||||
assert_equal(7, eval("3 + 4"))
|
@@ -1,39 +0,0 @@
|
||||
load_module("reflection")
|
||||
|
||||
def deep()
|
||||
{
|
||||
try {
|
||||
} catch {
|
||||
|
||||
} finally {
|
||||
if (2)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
def func()
|
||||
{
|
||||
deep();
|
||||
}
|
||||
|
||||
def doing()
|
||||
{
|
||||
for (var i = 0; i < 10; ++i)
|
||||
{
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
def while_doing()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
doing();
|
||||
}
|
||||
}
|
||||
|
||||
var f = fun() { while_doing(); }
|
||||
|
||||
assert_equal(get_eval_error(f).call_stack.size(), 16)
|
@@ -1 +0,0 @@
|
||||
assert_equal(true, even(4))
|
@@ -1,9 +0,0 @@
|
||||
var x = 1
|
||||
try {
|
||||
throw(x)
|
||||
x = 2
|
||||
}
|
||||
catch(e) {
|
||||
x = e + 3
|
||||
}
|
||||
assert_equal(4, x);
|
@@ -1,32 +0,0 @@
|
||||
var finallyone = false;
|
||||
|
||||
try {
|
||||
throw(3)
|
||||
}
|
||||
catch(x) {
|
||||
assert_equal(3, x)
|
||||
}
|
||||
finally {
|
||||
finallyone = true;
|
||||
}
|
||||
|
||||
assert_equal(true, finallyone);
|
||||
|
||||
var try2 = false;
|
||||
var catch2 = false;
|
||||
var finally2 = false;
|
||||
|
||||
|
||||
try {
|
||||
try2 = true;
|
||||
}
|
||||
catch {
|
||||
catch2 = true;
|
||||
}
|
||||
finally {
|
||||
finally2 = true;
|
||||
}
|
||||
|
||||
assert_equal(true, try2);
|
||||
assert_equal(false, catch2);
|
||||
assert_equal(true, finally2);
|
@@ -1,34 +0,0 @@
|
||||
var results = [];
|
||||
|
||||
for (var i = 2; i < 6; ++i) {
|
||||
try {
|
||||
throw(i)
|
||||
}
|
||||
catch(e) : e < 2 {
|
||||
results.push_back("c1: " + e.to_string());
|
||||
}
|
||||
catch(e) : e < 4 {
|
||||
results.push_back("c2: " + e.to_string());
|
||||
}
|
||||
catch(e) {
|
||||
results.push_back("c3: " + e.to_string());
|
||||
}
|
||||
catch {
|
||||
// Should never get called
|
||||
assert_equal(false, true)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
throw(3)
|
||||
}
|
||||
catch(e) : e < 3
|
||||
{
|
||||
// Should never get called
|
||||
assert_equal(false, true);
|
||||
}
|
||||
catch {
|
||||
results.push_back("defaultcatch");
|
||||
}
|
||||
|
||||
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);
|
@@ -1 +0,0 @@
|
||||
assert_equal([1,3], filter([1, 2, 3, 4], odd))
|
@@ -1,7 +0,0 @@
|
||||
assert_equal(true, 1.2 < 2)
|
||||
assert_equal(true, 1.2 > 1)
|
||||
assert_equal(1.2, 1.2)
|
||||
|
||||
assert_equal(true, .5 > 0)
|
||||
assert_equal(true, .5 < 1)
|
||||
assert_equal(0.5, .5)
|
@@ -1 +0,0 @@
|
||||
assert_equal(10, foldl([1, 2, 3, 4], `+`, 0))
|
@@ -1,7 +0,0 @@
|
||||
var ret = []
|
||||
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
ret.push_back(i);
|
||||
}
|
||||
|
||||
assert_equal([0,1,2,3,4], ret);
|
@@ -1 +0,0 @@
|
||||
for_each([1, 2, 3], print)
|
@@ -1,3 +0,0 @@
|
||||
var v = [1,2,3];
|
||||
var r = range(v);
|
||||
for_each(r, fun(x) { assert_equal(true, x>0); } )
|
@@ -1,4 +0,0 @@
|
||||
// Don't bother checking the output from this one, just makes sure it executes
|
||||
var v = [1,2,3];
|
||||
var r = retro(range(v));
|
||||
for_each(r, print)
|
@@ -1 +0,0 @@
|
||||
assert_equal(2, `+`.get_contained_functions()[0].get_arity())
|
@@ -1,76 +0,0 @@
|
||||
|
||||
#Test Function Description
|
||||
def test_function(a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// test_function tests
|
||||
assert_equal(test_function.get_arity(), 1);
|
||||
assert_equal(trim(test_function.get_annotation()), "#Test Function Description");
|
||||
assert_equal(test_function.get_contained_functions().size(), 0);
|
||||
assert_equal(test_function.get_param_types().size(), 2);
|
||||
|
||||
assert_equal(test_function, test_function);
|
||||
|
||||
assert_not_equal(test_function, `+`);
|
||||
|
||||
assert_equal(test_function.call([1]), 1);
|
||||
|
||||
// dynamic object function tests
|
||||
|
||||
def int::test_fun()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
assert_equal(test_fun.get_arity(), 1);
|
||||
assert_equal(test_fun.get_contained_functions.size(), 1);
|
||||
assert_equal(test_fun.get_param_types().size(), 2);
|
||||
assert_equal(test_fun, test_fun);
|
||||
var test_fun_types = test_fun.get_param_types();
|
||||
assert_equal(true, test_fun_types[0].bare_equal(Object_type));
|
||||
assert_equal(true, test_fun_types[1].bare_equal(int_type));
|
||||
|
||||
|
||||
// built-ins tests
|
||||
|
||||
assert_equal(2, `==`.get_arity());
|
||||
|
||||
// < should be the merging of two functions bool <(PODObject, PODObject) and bool <(string, string)
|
||||
// we want to peel it apart and make sure that's true
|
||||
var types = `<`.get_param_types();
|
||||
assert_equal(3, types.size());
|
||||
assert_equal(true, types[0].bare_equal(bool_type));
|
||||
assert_equal(true, types[1].bare_equal(Object_type));
|
||||
assert_equal(true, types[2].bare_equal(Object_type));
|
||||
assert_equal(2, `<`.get_contained_functions().size());
|
||||
|
||||
|
||||
// guard existence tests
|
||||
|
||||
def with_guard(x) : x > 3 {}
|
||||
def without_guard(x) {}
|
||||
|
||||
def group_guard(x) {}
|
||||
def group_guard(x) : x > 3 {}
|
||||
|
||||
assert_equal(true, with_guard.has_guard());
|
||||
assert_equal(false, without_guard.has_guard());
|
||||
|
||||
assert_equal(2, group_guard.get_contained_functions().size());
|
||||
var group = group_guard.get_contained_functions();
|
||||
|
||||
assert_equal(true, group[0].has_guard())
|
||||
assert_equal(false, group[1].has_guard())
|
||||
|
||||
assert_throws("Function does not have a guard", fun() { group[0].get_guard(); } );
|
||||
assert_throws("Function does not have a guard", fun() { without_guard.get_guard(); } );
|
||||
|
||||
var guard = with_guard.get_guard();
|
||||
|
||||
assert_equal(false, guard.has_guard());
|
||||
assert_throws("Function does not have a guard", fun() { guard.get_guard(); } );
|
@@ -1,3 +0,0 @@
|
||||
var x = `+`
|
||||
x = `-`
|
||||
assert_equal(1, x(5,4))
|
@@ -1 +0,0 @@
|
||||
assert_equal([1,2,3,4,5,6,7,8,9,10], generate_range(1, 10))
|
@@ -1,7 +0,0 @@
|
||||
load_module("test_module")
|
||||
|
||||
|
||||
assert_equal(to_int(TestValue1), 1)
|
||||
|
||||
assert_equal(TestValue1.type_name(), "TestEnum")
|
||||
|
@@ -1,7 +0,0 @@
|
||||
var t = false;
|
||||
|
||||
if (true) {
|
||||
t = true;
|
||||
}
|
||||
|
||||
assert_equal(true, t);
|
@@ -1,13 +0,0 @@
|
||||
var i = 3
|
||||
var b1 = false;
|
||||
var b2 = false;
|
||||
|
||||
if (i == 2) {
|
||||
b1 = true;
|
||||
}
|
||||
else {
|
||||
b2 = true;
|
||||
}
|
||||
|
||||
assert_equal(false, b1);
|
||||
assert_equal(true, b2);
|
@@ -1,18 +0,0 @@
|
||||
var b1 = false;
|
||||
var b2 = false;
|
||||
var b3 = false;
|
||||
|
||||
var i = 3
|
||||
if (i == 2) {
|
||||
b1 = true;
|
||||
}
|
||||
else if (i == 4) {
|
||||
b2 = true;
|
||||
}
|
||||
else if (i == 3) {
|
||||
b3 = true;
|
||||
}
|
||||
|
||||
assert_equal(false, b1);
|
||||
assert_equal(false, b2);
|
||||
assert_equal(true, b3);
|
@@ -1,14 +0,0 @@
|
||||
var i = 3
|
||||
var b = false
|
||||
if (i == 2) {
|
||||
assert_equal(false, true)
|
||||
}
|
||||
else if (i == 4) {
|
||||
assert_equal(false, true)
|
||||
}
|
||||
else {
|
||||
assert_equal(true, true)
|
||||
b = true
|
||||
}
|
||||
|
||||
assert_equal(true, b)
|
@@ -1,10 +0,0 @@
|
||||
|
||||
// tests more complex parses of the index operator
|
||||
|
||||
def Bob::bob3() { return [1,2,3]; }
|
||||
def Bob::Bob() {}
|
||||
var b = Bob();
|
||||
|
||||
|
||||
assert_equal(b.bob3()[0], 1);
|
||||
assert_equal((b.bob3())[1], 2);
|
@@ -1,8 +0,0 @@
|
||||
load_module("test_module")
|
||||
|
||||
var t0 = TestBaseType()
|
||||
var t = TestDerivedType();
|
||||
|
||||
assert_equal(t0.func(), 0);
|
||||
assert_equal(t.func(), 1);
|
||||
|
@@ -1,3 +0,0 @@
|
||||
var bob = 5.5
|
||||
assert_equal("5.5", "${bob}")
|
||||
assert_equal("val: 8 and 8", "val: ${5.5 + 2.5} and ${bob + 2.5}")
|
@@ -1,4 +0,0 @@
|
||||
assert_equal("\$ {4 + 5}", "$ {4 + 5}")
|
||||
assert_equal("\$9", "$${4+5}")
|
||||
assert_equal("Value: \${4 + 5}", "Value: \${4 + 5}")
|
||||
assert_equal("Value: \$9", "Value: \$${4 + 5}")
|
@@ -1 +0,0 @@
|
||||
assert_throws("Illegal const function assignment", fun() { clone = `-` } );
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user