Compare commits
164 Commits
Release-4.
...
v5.1.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
455324bf13 | ||
![]() |
deef33640c | ||
![]() |
85ba42849b | ||
![]() |
58f3256389 | ||
![]() |
f1a4c4c427 | ||
![]() |
afd27a4b01 | ||
![]() |
6bb90f9d6d | ||
![]() |
4c65e45598 | ||
![]() |
57c6d72a79 | ||
![]() |
923369a4f4 | ||
![]() |
964342bff3 | ||
![]() |
c5a86401aa | ||
![]() |
623c64299a | ||
![]() |
9832d1ce39 | ||
![]() |
ed7bdfb172 | ||
![]() |
87c9006174 | ||
![]() |
204ab53afc | ||
![]() |
d47cd63fec | ||
![]() |
193151f52e | ||
![]() |
6642e02496 | ||
![]() |
8f7226051e | ||
![]() |
d84b4c0b37 | ||
![]() |
46d1c50923 | ||
![]() |
9e3c2960aa | ||
![]() |
84e17b8d06 | ||
![]() |
9fd4a1b9f5 | ||
![]() |
32fab64882 | ||
![]() |
8cb49e9494 | ||
![]() |
441cdf0935 | ||
![]() |
f0016d978a | ||
![]() |
1155720b14 | ||
![]() |
7052234650 | ||
![]() |
c2934caad6 | ||
![]() |
f5b7be3743 | ||
![]() |
d8f881239f | ||
![]() |
199b1f5233 | ||
![]() |
0a436398dd | ||
![]() |
9f309fcbe9 | ||
![]() |
4e33e969dc | ||
![]() |
f27739cf71 | ||
![]() |
08d9d9e28e | ||
![]() |
935276fccd | ||
![]() |
f8feaf6ea8 | ||
![]() |
dfcc415c31 | ||
![]() |
927235d871 | ||
![]() |
a6924bcc9e | ||
![]() |
a3b50d4151 | ||
![]() |
bf4f90a4ff | ||
![]() |
45f07f9924 | ||
![]() |
d3b8daeff0 | ||
![]() |
39d817469c | ||
![]() |
7a25625fdd | ||
![]() |
5e6a51ba63 | ||
![]() |
a8ea5f151d | ||
![]() |
6cda1140c4 | ||
![]() |
5a76d98692 | ||
![]() |
949f54b9c4 | ||
![]() |
f6e53dd42d | ||
![]() |
d55439a7ac | ||
![]() |
953c4e4847 | ||
![]() |
3bccf4d977 | ||
![]() |
a67022e31e | ||
![]() |
a951d2b0af | ||
![]() |
b7e1cf41e5 | ||
![]() |
30104cc3ed | ||
![]() |
5a380abc68 | ||
![]() |
d2aba2ef56 | ||
![]() |
4ebfe264e9 | ||
![]() |
a3e299fe1b | ||
![]() |
832df7f9e8 | ||
![]() |
6c53e08e9b | ||
![]() |
b1a27020f7 | ||
![]() |
4767aeb544 | ||
![]() |
66deef52c8 | ||
![]() |
8f7793a795 | ||
![]() |
2969f61fe4 | ||
![]() |
13a049cf54 | ||
![]() |
f2c6745b8a | ||
![]() |
13ffc92bc3 | ||
![]() |
e853e2e4ac | ||
![]() |
1bdedd3b45 | ||
![]() |
9162b02ce9 | ||
![]() |
ba9d13bf7b | ||
![]() |
16bdfe4571 | ||
![]() |
62891b8537 | ||
![]() |
4c5df91d51 | ||
![]() |
a0f7c46cc9 | ||
![]() |
7f5fce001b | ||
![]() |
90125d0f9a | ||
![]() |
919b6430c4 | ||
![]() |
7027f6b834 | ||
![]() |
cebd2c9763 | ||
![]() |
b82895c489 | ||
![]() |
cf97a73485 | ||
![]() |
37b8e6c3f9 | ||
![]() |
c73f16fdfe | ||
![]() |
68df78a2a6 | ||
![]() |
bca86c87e1 | ||
![]() |
a04dbf2c2d | ||
![]() |
4674594ee7 | ||
![]() |
1f4900c363 | ||
![]() |
8e24eef265 | ||
![]() |
974c903d1c | ||
![]() |
9ec78752a0 | ||
![]() |
48ecb3e2b4 | ||
![]() |
98d2eadde2 | ||
![]() |
286b130f47 | ||
![]() |
927619bf47 | ||
![]() |
179a674b00 | ||
![]() |
ee4c9575ae | ||
![]() |
b615d2a423 | ||
![]() |
dc6998259e | ||
![]() |
136b877afa | ||
![]() |
9a9d4e1ae0 | ||
![]() |
27ae40b813 | ||
![]() |
5dc0931ca2 | ||
![]() |
5a3975b7a4 | ||
![]() |
bc75df4d58 | ||
![]() |
b27aa50d6a | ||
![]() |
488f2ea393 | ||
![]() |
db0e342a96 | ||
![]() |
702b5fdba1 | ||
![]() |
3329732ceb | ||
![]() |
e1e0561c7e | ||
![]() |
52d9e1e871 | ||
![]() |
a28dfd8695 | ||
![]() |
1eb402e474 | ||
![]() |
3765c23598 | ||
![]() |
784ca41270 | ||
![]() |
425ca59a34 | ||
![]() |
abfd37644e | ||
![]() |
4bf3783d0b | ||
![]() |
4a99471304 | ||
![]() |
e0d7977f8a | ||
![]() |
92de42e42b | ||
![]() |
e3350fe55f | ||
![]() |
2ca7a7d7da | ||
![]() |
ac4bb95dfb | ||
![]() |
535adce298 | ||
![]() |
d04960bc4a | ||
![]() |
12bd5b0af5 | ||
![]() |
d6b475239a | ||
![]() |
6f1bffda3a | ||
![]() |
64382a2399 | ||
![]() |
f996c0df37 | ||
![]() |
d5e1650167 | ||
![]() |
cc927fc6bc | ||
![]() |
6f282b6a56 | ||
![]() |
194001f9a1 | ||
![]() |
a3c3b8683b | ||
![]() |
5efdcdff99 | ||
![]() |
cd97880d70 | ||
![]() |
0a9cb0cbe9 | ||
![]() |
99aaa079a4 | ||
![]() |
f4080c4c75 | ||
![]() |
4522ff0732 | ||
![]() |
b297162d13 | ||
![]() |
62cf6293e8 | ||
![]() |
6bb2678d18 | ||
![]() |
aa402fdfde | ||
![]() |
53108463df | ||
![]() |
c842bf14c1 | ||
![]() |
e2da56f199 | ||
![]() |
afa96ecbf9 |
141
CMakeLists.txt
141
CMakeLists.txt
@@ -13,24 +13,22 @@ 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 4)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
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})
|
||||
|
||||
@@ -39,8 +37,16 @@ configure_file(Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
include(CTest)
|
||||
include(CPack)
|
||||
|
||||
include(cmake/CheckCXX11Features.cmake)
|
||||
|
||||
find_library(READLINE_LIBRARY NAMES readline PATH /usr/lib /usr/local/lib /opt/local/lib)
|
||||
|
||||
if(HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
message(STATUS "Variadic Template support detected")
|
||||
else()
|
||||
message(SEND_ERROR "The selected compiler does not support the C++11 feature Variadic Templates.")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
|
||||
|
||||
@@ -61,74 +67,81 @@ if(MSVC)
|
||||
add_definitions(/bigobj)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic)
|
||||
add_definitions(-Wall -Wextra -Wshadow -pedantic -std=c++0x)
|
||||
|
||||
if (APPLE)
|
||||
# -Wno-missing-field-initializers is for boost on macos
|
||||
add_definitions(-Wno-missing-field-initializers -Wno-sign-compare)
|
||||
add_definitions(-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 (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.chai 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)
|
||||
|
||||
if (Boost_FOUND)
|
||||
link_directories( ${Boost_LIBRARY_DIRS} )
|
||||
else()
|
||||
message(FATAL_ERROR "Can not find Boost")
|
||||
endif(Boost_FOUND)
|
||||
else()
|
||||
add_definitions(-DCHAISCRIPT_NO_THREADS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_HOST_UNIX)
|
||||
set(DYNAMIC_LOADER "dl")
|
||||
list(APPEND LIBS "dl")
|
||||
|
||||
if (MULTITHREAD_SUPPORT_ENABLED)
|
||||
list(APPEND LIBS "pthread")
|
||||
add_definitions(-pthread)
|
||||
endif()
|
||||
endif(CMAKE_HOST_UNIX)
|
||||
|
||||
if (MSVC)
|
||||
# Boost on MSVC does automatic linking
|
||||
set(LIBS ${DYNAMIC_LOADER} ${READLINE_LIB})
|
||||
else()
|
||||
set(LIBS ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
||||
endif()
|
||||
list(APPEND LIBS ${READLINE_LIB})
|
||||
|
||||
|
||||
if (CMAKE_COMPILER_2005)
|
||||
# vs2005 is a bit too loud about possible loss of data warnings
|
||||
# ADD_DEFINITIONS(/wd4244)
|
||||
endif()
|
||||
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${Boost_INCLUDE_DIR})
|
||||
add_library(chaiscript_stdlib MODULE src/chaiscript_stdlib.cpp)
|
||||
target_link_libraries(chaiscript_stdlib ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
|
||||
add_executable(chai src/main.cpp ${Chai_INCLUDES})
|
||||
target_link_libraries(chai ${LIBS})
|
||||
target_link_libraries(chai ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_dependencies(chai chaiscript_stdlib)
|
||||
|
||||
if (BUILD_SAMPLES)
|
||||
add_executable(example samples/example.cpp)
|
||||
target_link_libraries(example ${LIBS})
|
||||
target_link_libraries(example ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
target_link_libraries(memory_leak_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
endif()
|
||||
|
||||
|
||||
if (BUILD_MODULES)
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${LIBS})
|
||||
target_link_libraries(stl_extra ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
|
||||
add_library(reflection MODULE src/reflection.cpp)
|
||||
target_link_libraries(reflection ${LIBS})
|
||||
target_link_libraries(reflection ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
set(MODULES stl_extra reflection)
|
||||
endif()
|
||||
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai)
|
||||
file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai)
|
||||
|
||||
list(SORT UNIT_TESTS)
|
||||
|
||||
@@ -138,7 +151,7 @@ if(BUILD_TESTING)
|
||||
foreach(filename ${UNIT_TESTS})
|
||||
message(STATUS "Adding test ${filename}")
|
||||
add_test(${filename} chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/unit_test.inc ${CMAKE_CURRENT_SOURCE_DIR}/unittests/${filename})
|
||||
endforeach(filename)
|
||||
endforeach(filename)
|
||||
|
||||
set_property(TEST ${UNIT_TESTS}
|
||||
PROPERTY ENVIRONMENT
|
||||
@@ -148,53 +161,89 @@ if(BUILD_TESTING)
|
||||
|
||||
if (NOT UNIT_TEST_LIGHT)
|
||||
add_executable(utility_test unittests/utility_test.cpp)
|
||||
target_link_libraries(utility_test ${LIBS})
|
||||
target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
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})
|
||||
target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
add_test(NAME MultiFile_Test COMMAND multifile_test)
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${LIBS})
|
||||
target_link_libraries(test_module ${LIBS} ${EXTRA_LINKER_FLAGS})
|
||||
|
||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
endif()
|
||||
|
103
cmake/CheckCXX11Features.cmake
Normal file
103
cmake/CheckCXX11Features.cmake
Normal file
@@ -0,0 +1,103 @@
|
||||
# Checks for C++11 features
|
||||
# CXX11_FEATURE_LIST - a list containing all supported features
|
||||
# HAS_CXX11_AUTO - auto keyword
|
||||
# HAS_CXX11_NULLPTR - nullptr
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
# HAS_CXX11_STATIC_ASSERT - static_assert()
|
||||
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
|
||||
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
#
|
||||
# Original script by Rolf Eike Beer
|
||||
# Modifications by Andreas Weis
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
|
||||
SET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_CXX_FLAGS "-std=c++0x")
|
||||
endif()
|
||||
|
||||
MACRO(CXX11_CHECK_FEATURE FEATURE_NAME FEATURE_NUMBER RESULT_VAR)
|
||||
IF (NOT DEFINED ${RESULT_VAR})
|
||||
SET(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11/cxx11_${FEATURE_NAME}")
|
||||
|
||||
IF (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME}-N${FEATURE_NUMBER})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\" (N${FEATURE_NUMBER})")
|
||||
ELSE (${FEATURE_NUMBER})
|
||||
SET(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/c++11-test-${FEATURE_NAME})
|
||||
SET(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
ENDIF (${FEATURE_NUMBER})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
|
||||
SET(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
SET(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
SET(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
IF (CROSS_COMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}")
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ELSE (CROSS_COMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}")
|
||||
IF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}_fail" "${_SRCFILE_FAIL}")
|
||||
IF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ELSE (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ENDIF (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
ENDIF (CROSS_COMPILING)
|
||||
IF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}")
|
||||
IF (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} FALSE)
|
||||
ELSE (_TMP_RESULT)
|
||||
SET(${RESULT_VAR} TRUE)
|
||||
ENDIF (_TMP_RESULT)
|
||||
ENDIF (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
IF (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- works")
|
||||
LIST(APPEND CXX11_FEATURE_LIST ${RESULT_VAR})
|
||||
ELSE (${RESULT_VAR})
|
||||
MESSAGE(STATUS "Checking C++11 support for ${_LOG_NAME} -- not supported")
|
||||
ENDIF (${RESULT_VAR})
|
||||
SET(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
ENDIF (NOT DEFINED ${RESULT_VAR})
|
||||
ENDMACRO(CXX11_CHECK_FEATURE)
|
||||
|
||||
CXX11_CHECK_FEATURE("auto" 2546 HAS_CXX11_AUTO)
|
||||
CXX11_CHECK_FEATURE("nullptr" 2431 HAS_CXX11_NULLPTR)
|
||||
CXX11_CHECK_FEATURE("lambda" 2927 HAS_CXX11_LAMBDA)
|
||||
CXX11_CHECK_FEATURE("static_assert" 1720 HAS_CXX11_STATIC_ASSERT)
|
||||
CXX11_CHECK_FEATURE("rvalue_references" 2118 HAS_CXX11_RVALUE_REFERENCES)
|
||||
CXX11_CHECK_FEATURE("decltype" 2343 HAS_CXX11_DECLTYPE)
|
||||
CXX11_CHECK_FEATURE("cstdint" "" HAS_CXX11_CSTDINT_H)
|
||||
CXX11_CHECK_FEATURE("long_long" 1811 HAS_CXX11_LONG_LONG)
|
||||
CXX11_CHECK_FEATURE("variadic_templates" 2555 HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
CXX11_CHECK_FEATURE("constexpr" 2235 HAS_CXX11_CONSTEXPR)
|
||||
CXX11_CHECK_FEATURE("sizeof_member" 2253 HAS_CXX11_SIZEOF_MEMBER)
|
||||
CXX11_CHECK_FEATURE("__func__" 2340 HAS_CXX11_FUNC)
|
||||
|
||||
SET(CXX11_FEATURE_LIST ${CXX11_FEATURE_LIST} CACHE STRING "C++11 feature support list")
|
||||
MARK_AS_ADVANCED(FORCE CXX11_FEATURE_LIST)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS ${CHECK_CXX11_OLD_CMAKE_CXX_FLAGS})
|
||||
UNSET(CHECK_CXX11_OLD_CMAKE_CXX_FLAGS)
|
||||
|
8
cmake/c++11-test-__func__-N2340.cpp
Normal file
8
cmake/c++11-test-__func__-N2340.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
if (!__func__) { return 1; }
|
||||
if(std::strlen(__func__) <= 0) { return 1; }
|
||||
return 0;
|
||||
}
|
12
cmake/c++11-test-auto-N2546.cpp
Normal file
12
cmake/c++11-test-auto-N2546.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
auto i = 5;
|
||||
auto f = 3.14159f;
|
||||
auto d = 3.14159;
|
||||
bool ret = (
|
||||
(sizeof(f) < sizeof(d)) &&
|
||||
(sizeof(i) == sizeof(int))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
19
cmake/c++11-test-constexpr-N2235.cpp
Normal file
19
cmake/c++11-test-constexpr-N2235.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
constexpr int square(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
constexpr int the_answer()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int test_arr[square(3)];
|
||||
bool ret = (
|
||||
(square(the_answer()) == 1764) &&
|
||||
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
10
cmake/c++11-test-cstdint.cpp
Normal file
10
cmake/c++11-test-cstdint.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <cstdint>
|
||||
int main()
|
||||
{
|
||||
bool test =
|
||||
(sizeof(int8_t) == 1) &&
|
||||
(sizeof(int16_t) == 2) &&
|
||||
(sizeof(int32_t) == 4) &&
|
||||
(sizeof(int64_t) == 8);
|
||||
return test ? 0 : 1;
|
||||
}
|
11
cmake/c++11-test-decltype-N2343.cpp
Normal file
11
cmake/c++11-test-decltype-N2343.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
bool check_size(int i)
|
||||
{
|
||||
return sizeof(int) == sizeof(decltype(i));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
bool ret = check_size(42);
|
||||
return ret ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-lambda-N2927.cpp
Normal file
5
cmake/c++11-test-lambda-N2927.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
7
cmake/c++11-test-long_long-N1811.cpp
Normal file
7
cmake/c++11-test-long_long-N1811.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-nullptr-N2431.cpp
Normal file
5
cmake/c++11-test-nullptr-N2431.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int* test = nullptr;
|
||||
return test ? 1 : 0;
|
||||
}
|
5
cmake/c++11-test-nullptr-N2431_fail_compile.cpp
Normal file
5
cmake/c++11-test-nullptr-N2431_fail_compile.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
int i = nullptr;
|
||||
return 1;
|
||||
}
|
15
cmake/c++11-test-rvalue_references-N2118.cpp
Normal file
15
cmake/c++11-test-rvalue_references-N2118.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
int foo(int& lvalue)
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
int foo(int&& rvalue)
|
||||
{
|
||||
return 321;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 42;
|
||||
return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1;
|
||||
}
|
14
cmake/c++11-test-sizeof_member-N2253.cpp
Normal file
14
cmake/c++11-test-sizeof_member-N2253.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
struct foo {
|
||||
char bar;
|
||||
int baz;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
bool ret = (
|
||||
(sizeof(foo::bar) == 1) &&
|
||||
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
|
||||
(sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz))
|
||||
);
|
||||
return ret ? 0 : 1;
|
||||
}
|
5
cmake/c++11-test-static_assert-N1720.cpp
Normal file
5
cmake/c++11-test-static_assert-N1720.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
5
cmake/c++11-test-static_assert-N1720_fail_compile.cpp
Normal file
5
cmake/c++11-test-static_assert-N1720_fail_compile.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
int main()
|
||||
{
|
||||
static_assert(1 < 0, "this should fail");
|
||||
return 0;
|
||||
}
|
23
cmake/c++11-test-variadic_templates-N2555.cpp
Normal file
23
cmake/c++11-test-variadic_templates-N2555.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
int Accumulate()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
int Accumulate(T v, Ts... vs)
|
||||
{
|
||||
return v + Accumulate(vs...);
|
||||
}
|
||||
|
||||
template<int... Is>
|
||||
int CountElements()
|
||||
{
|
||||
return sizeof...(Is);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int acc = Accumulate(1, 2, 3, 4, -5);
|
||||
int count = CountElements<1,2,3,4,5>();
|
||||
return ((acc == 5) && (count == 5)) ? 0 : 1;
|
||||
}
|
@@ -50,7 +50,7 @@ function run_test
|
||||
# Run multithreaded tests
|
||||
echo "****Building multithreaded test"
|
||||
pushd src
|
||||
g++ multithreaded.cpp -lboost_thread-mt -ldl -omultithreaded -I../include -O3
|
||||
g++ multithreaded.cpp -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 (var i = 2; i < n; ++i)
|
||||
for (auto i = 2; i < n; ++i)
|
||||
{
|
||||
if (n % i == 0) {return false}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ def isprime(n)
|
||||
|
||||
def primes(n)
|
||||
{
|
||||
var count = 0
|
||||
for (var i = 2; i <= n; ++i)
|
||||
auto count = 0
|
||||
for (auto i = 2; i <= n; ++i)
|
||||
{
|
||||
if (isprime(i)) {++count}
|
||||
}
|
||||
@@ -21,5 +21,6 @@ def primes(n)
|
||||
}
|
||||
|
||||
|
||||
var N = 5000
|
||||
auto 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', 'attr',
|
||||
'def', 'false', 'fun', 'true', 'var', 'auto', '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
|
||||
syn keyword chaiscriptType fun var auto
|
||||
|
||||
"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 two dependecies. boost::threads (optional) and the
|
||||
/// ChaiScript is a header only library with only one dependecy: 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
|
||||
/// both boost::threads and the dynamic loader. For example:
|
||||
/// the dynamic loader. For example:
|
||||
///
|
||||
/// \code
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl -lboost_threads
|
||||
/// gcc main.cpp -I/path/to/chaiscript/headers -ldl
|
||||
/// \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,7 +248,9 @@
|
||||
///
|
||||
/// std::string append_string_int(const std::string &t_lhs, int t_rhs)
|
||||
/// {
|
||||
/// return t_lhs + boost::lexical_cast<std::string>(t_rhs);
|
||||
/// std::stringstream ss;
|
||||
/// ss << t_lhs << t_rhs;
|
||||
/// return ss.str();
|
||||
/// }
|
||||
///
|
||||
/// chai.add(fun(append_string_int), "+");
|
||||
@@ -297,8 +302,8 @@
|
||||
/// <hr>
|
||||
/// \subsection pointerconversions Pointer / Object Conversions
|
||||
///
|
||||
/// 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.
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
@@ -311,12 +316,12 @@
|
||||
/// void fun3(int);
|
||||
/// void fun4(int &);
|
||||
/// void fun5(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>);
|
||||
/// 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>);
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
@@ -377,10 +382,10 @@
|
||||
/// \subsection functionobjects Function Objects
|
||||
///
|
||||
/// Functions are first class objects in Chaiscript and ChaiScript supports automatic conversion
|
||||
/// between ChaiScript functions and boost::function objects.
|
||||
/// between ChaiScript functions and std::function objects.
|
||||
///
|
||||
/// \code
|
||||
/// void callafunc(const boost::function<void (const std::string &)> &t_func)
|
||||
/// void callafunc(const std::function<void (const std::string &)> &t_func)
|
||||
/// {
|
||||
/// t_func("bob");
|
||||
/// }
|
||||
@@ -390,9 +395,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 boost::function
|
||||
/// // which expects a typed std::function
|
||||
///
|
||||
/// boost::function<void ()> f = chai.eval<boost::function<void ()> >("dump_system");
|
||||
/// std::function<void ()> f = chai.eval<std::function<void ()> >("dump_system");
|
||||
/// f(); // call the ChaiScript function dump_system, from C++
|
||||
/// }
|
||||
/// \endcode
|
||||
@@ -407,7 +412,7 @@
|
||||
///
|
||||
/// Thread safety can be disabled by defining CHAISCRIPT_NO_THREADS when using the library.
|
||||
///
|
||||
/// Disabling thread safety increases performance and removes the requirement for boost_threads.
|
||||
/// Disabling thread safety increases performance in many cases.
|
||||
///
|
||||
/// <hr>
|
||||
///
|
||||
@@ -743,20 +748,16 @@
|
||||
/// \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_ */
|
||||
|
28
include/chaiscript/chaiscript_defines.hpp
Normal file
28
include/chaiscript/chaiscript_defines.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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
|
||||
|
44
include/chaiscript/chaiscript_stdlib.hpp
Normal file
44
include/chaiscript/chaiscript_stdlib.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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
|
||||
|
@@ -7,8 +7,11 @@
|
||||
#ifndef CHAISCRIPT_THREADING_HPP_
|
||||
#define CHAISCRIPT_THREADING_HPP_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <boost/thread.hpp>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#else
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
@@ -25,48 +28,92 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// If threading is enabled, then this namespace contains boost::thread classes.
|
||||
/// If threading is enabled, then this namespace contains std 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
|
||||
using boost::unique_lock;
|
||||
using boost::shared_lock;
|
||||
using boost::lock_guard;
|
||||
using boost::shared_mutex;
|
||||
using boost::recursive_mutex;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses boost::thread_specific_ptr<T>. If
|
||||
|
||||
/// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
|
||||
/// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
|
||||
///
|
||||
/// \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
|
||||
{
|
||||
if (!m_thread_storage.get())
|
||||
{
|
||||
m_thread_storage.reset(new T());
|
||||
}
|
||||
|
||||
return m_thread_storage.get();
|
||||
return get_tls().get();
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
{
|
||||
return *(this->operator->());
|
||||
return *get_tls();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
mutable boost::thread_specific_ptr<T> m_thread_storage;
|
||||
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;
|
||||
|
||||
|
||||
/*
|
||||
static __thread std::shared_ptr<T> *m_data = 0;
|
||||
|
||||
if (!m_data) { m_data = new std::shared_ptr<T>(new T()); }
|
||||
|
||||
return *m_data;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
mutable mutex m_mutex;
|
||||
mutable std::unordered_map<std::thread::id, std::shared_ptr<T> > m_instances;
|
||||
};
|
||||
|
||||
#else
|
||||
|
162
include/chaiscript/dispatchkit/any.hpp
Normal file
162
include/chaiscript/dispatchkit/any.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
// 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) throw()
|
||||
const std::string &t_what) noexcept
|
||||
: from(t_from), to(&t_to), m_what(t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const std::string &t_what) throw()
|
||||
bad_boxed_cast(const std::string &t_what) noexcept
|
||||
: to(0), m_what(t_what)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_cast() throw() {}
|
||||
virtual ~bad_boxed_cast() noexcept {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
virtual const char * what() const throw()
|
||||
virtual const char * what() const noexcept
|
||||
{
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
@@ -4,90 +4,130 @@
|
||||
// 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 <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)
|
||||
#include <functional>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \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<int>
|
||||
struct Placeholder
|
||||
{
|
||||
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// \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)
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
|
||||
{
|
||||
return boost::bind(boost::mem_fn(f), o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, 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)
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, 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)
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
|
||||
{
|
||||
return boost::bind(f, o BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM(n, param, _));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef n
|
||||
#undef m
|
||||
|
||||
#endif
|
||||
|
@@ -12,7 +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
|
||||
{
|
||||
@@ -25,9 +26,9 @@ namespace chaiscript
|
||||
/// \param[in] v Boxed_Number to copy into the new object
|
||||
/// \returns The newly created object.
|
||||
template<typename P1>
|
||||
boost::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
std::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
{
|
||||
boost::shared_ptr<P1> p(new P1());
|
||||
std::shared_ptr<P1> p(new P1());
|
||||
Boxed_Value bv(p);
|
||||
Boxed_Number nb(bv);
|
||||
nb = v;
|
||||
@@ -93,27 +94,30 @@ namespace chaiscript
|
||||
|
||||
|
||||
/**
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
template<typename Input>
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
return boost::lexical_cast<std::string>(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
|
||||
*/
|
||||
* 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)
|
||||
{
|
||||
return boost::lexical_cast<Input>(i);
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
@@ -139,7 +143,7 @@ namespace chaiscript
|
||||
* function variables.
|
||||
*/
|
||||
template<typename Type>
|
||||
boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p)
|
||||
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
@@ -148,10 +152,10 @@ namespace chaiscript
|
||||
* Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
*/
|
||||
template<typename Type>
|
||||
boost::shared_ptr<typename boost::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const boost::shared_ptr<typename boost::add_const<Type>::type> &p)
|
||||
std::shared_ptr<typename std::remove_const<Type>::type>
|
||||
shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
|
||||
{
|
||||
return boost::const_pointer_cast<typename boost::remove_const<Type>::type>(p);
|
||||
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +166,7 @@ namespace chaiscript
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<Type> &rhs)
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
{
|
||||
if (lhs.is_undef()
|
||||
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
|
||||
@@ -283,10 +287,10 @@ namespace chaiscript
|
||||
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return pf->get_guard();
|
||||
return bool(pf->get_guard());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -294,7 +298,7 @@ namespace chaiscript
|
||||
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
||||
{
|
||||
boost::shared_ptr<const dispatch::Dynamic_Proxy_Function> pf = boost::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_guard())
|
||||
@@ -312,7 +316,9 @@ namespace chaiscript
|
||||
throw bv;
|
||||
}
|
||||
|
||||
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()))
|
||||
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()))
|
||||
{
|
||||
e->add(user_type<void>(), "void");
|
||||
return e;
|
||||
@@ -340,24 +346,22 @@ namespace chaiscript
|
||||
static std::vector<Boxed_Value> do_return_boxed_value_vector(FunctionType f,
|
||||
const dispatch::Proxy_Function_Base *b)
|
||||
{
|
||||
typedef typename boost::function_types::result_type<FunctionType>::type Vector;
|
||||
Vector v = (b->*f)();
|
||||
auto v = (b->*f)();
|
||||
|
||||
std::vector<Boxed_Value> vbv;
|
||||
for (typename Vector::const_iterator itr = v.begin();
|
||||
itr != v.end();
|
||||
++itr)
|
||||
|
||||
for (const auto &o: v)
|
||||
{
|
||||
vbv.push_back(const_var(*itr));
|
||||
vbv.push_back(const_var(o));
|
||||
}
|
||||
|
||||
return vbv;
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
static boost::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
static std::function<std::vector<Boxed_Value> (const dispatch::Proxy_Function_Base*)> return_boxed_value_vector(const Function &f)
|
||||
{
|
||||
return boost::bind(&do_return_boxed_value_vector<Function>, f, _1);
|
||||
return std::bind(&do_return_boxed_value_vector<Function>, f, std::placeholders::_1);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -388,7 +392,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
m->add(constructor<std::runtime_error (const std::string &)>(), "runtime_error");
|
||||
m->add(fun(boost::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
m->add(fun(std::function<std::string (const std::runtime_error &)>(&what)), "what");
|
||||
|
||||
m->add(user_type<dispatch::Dynamic_Object>(), "Dynamic_Object");
|
||||
m->add(constructor<dispatch::Dynamic_Object (const std::string &)>(), "Dynamic_Object");
|
||||
@@ -396,7 +400,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() { 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->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->add(fun(&has_guard), "has_guard");
|
||||
m->add(fun(&get_guard), "get_guard");
|
||||
@@ -419,6 +423,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");
|
||||
@@ -438,18 +443,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<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);
|
||||
bootstrap_pod_type<std::int8_t>("int8_t", m);
|
||||
bootstrap_pod_type<std::int16_t>("int16_t", m);
|
||||
bootstrap_pod_type<std::int32_t>("int32_t", m);
|
||||
bootstrap_pod_type<std::int64_t>("int64_t", m);
|
||||
bootstrap_pod_type<std::uint8_t>("uint8_t", m);
|
||||
bootstrap_pod_type<std::uint16_t>("uint16_t", m);
|
||||
bootstrap_pod_type<std::uint32_t>("uint32_t", m);
|
||||
bootstrap_pod_type<std::uint64_t>("uint64_t", m);
|
||||
|
||||
operators::logical_compliment<bool>(m);
|
||||
|
||||
@@ -459,17 +465,17 @@ namespace chaiscript
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
|
||||
"bind");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
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(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(Proxy_Function(new dispatch::Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&call_exists, std::placeholders::_1))),
|
||||
"call_exists");
|
||||
|
||||
m->add(fun(&type_match), "type_match");
|
||||
m->add(fun(&Boxed_Value::type_match), "type_match");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#define CHAISCRIPT_BOOTSTRAP_STL_HPP_
|
||||
|
||||
#include "dispatchkit.hpp"
|
||||
#include "bootstrap.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -147,62 +148,19 @@ 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)
|
||||
void insert(T &t_target, const T &t_other)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4267)
|
||||
#endif
|
||||
return t_func(t_obj);
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
t_target.insert(t_other.begin(), t_other.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
boost::function<int (const T *)> return_int(size_t (T::*t_func)() const)
|
||||
void insert_ref(T &t_target, const typename T::value_type &t_val)
|
||||
{
|
||||
return boost::bind(&return_int_impl<T>, boost::function<size_t (const T *)>(boost::mem_fn(t_func)), _1);
|
||||
t_target.insert(t_val);
|
||||
}
|
||||
|
||||
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>
|
||||
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, 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 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -285,11 +243,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(boost::function<typename ContainerType::reference (ContainerType *, int)>
|
||||
(boost::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
fun(std::function<typename ContainerType::reference (ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<indexoper>(&ContainerType::at)))), "[]");
|
||||
m->add(
|
||||
fun(boost::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
||||
(boost::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
||||
fun(std::function<typename ContainerType::const_reference (const ContainerType *, int)>
|
||||
(std::mem_fn(static_cast<constindexoper>(&ContainerType::at)))), "[]");
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -313,12 +271,9 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
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");
|
||||
|
||||
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");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -450,8 +405,23 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr unique_associative_container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(boost::function<int (const ContainerType *, const typename ContainerType::key_type &)>(detail::return_int(&ContainerType::count))), "count");
|
||||
m->add(fun<int (const ContainerType *, const typename ContainerType::key_type &)>(&ContainerType::count), "count");
|
||||
|
||||
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
|
||||
|
||||
m->add(fun<int (ContainerType *, const typename ContainerType::key_type &)>(static_cast<erase_ptr>(&ContainerType::erase)), "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;
|
||||
}
|
||||
|
||||
@@ -524,8 +494,8 @@ namespace chaiscript
|
||||
if ( rhs.size() != this.size() ) { \
|
||||
return false; \
|
||||
} else { \
|
||||
var r1 = range(this); \
|
||||
var r2 = range(rhs); \
|
||||
auto r1 = range(this); \
|
||||
auto r2 = range(rhs); \
|
||||
while (!r1.empty()) \
|
||||
{ \
|
||||
if (!eq(r1.front(), r2.front())) \
|
||||
@@ -571,19 +541,19 @@ namespace chaiscript
|
||||
}
|
||||
m->add(fun(&String::push_back), push_back_name);
|
||||
|
||||
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;
|
||||
typedef std::function<int (const String *, const String &, int)> find_func;
|
||||
|
||||
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(&String::c_str), "c_str");
|
||||
m->add(fun(&String::data), "data");
|
||||
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( 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( std::function<String (const String *, int, int)>( [](const String *s, int pos, int len) { return s->substr(pos, len); } ) ), "substr");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -4,8 +4,10 @@
|
||||
// and Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef __boxed_cast_hpp__
|
||||
#define __boxed_cast_hpp__
|
||||
#ifndef CHAISCRIPT_BOXED_CAST_HPP_
|
||||
#define CHAISCRIPT_BOXED_CAST_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
#include "type_info.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
@@ -13,14 +15,6 @@
|
||||
#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
|
||||
{
|
||||
@@ -31,39 +25,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, &, *, boost::shared_ptr, boost::reference_wrapper,
|
||||
/// and boost::function (const and non-const) where possible. boxed_cast is used internally during function
|
||||
/// 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
|
||||
/// 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 boost::reference_wrapper can be extracted as reference,
|
||||
/// \li Boxed_Value constructed from pointer or std::reference_wrapper can be extracted as reference,
|
||||
/// pointer or value types
|
||||
/// \li Boxed_Value constructed from boost::shared_ptr or value types can be extracted as reference,
|
||||
/// pointer, value, or boost::shared_ptr types
|
||||
/// \li Boxed_Value constructed from std::shared_ptr or value types can be extracted as reference,
|
||||
/// pointer, value, or std::shared_ptr types
|
||||
///
|
||||
/// Conversions to boost::function objects are attempted as well
|
||||
/// Conversions to std::function objects are attempted as well
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// // All of the following should succeed
|
||||
/// chaiscript::Boxed_Value bv(1);
|
||||
/// boost::shared_ptr<int> spi = chaiscript::boxed_cast<boost::shared_ptr<int> >(bv);
|
||||
/// std::shared_ptr<int> spi = chaiscript::boxed_cast<std::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);
|
||||
/// boost::shared_ptr<const int> cspi = chaiscript::boxed_cast<boost::shared_ptr<const int> >(bv);
|
||||
/// std::shared_ptr<const int> cspi = chaiscript::boxed_cast<std::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
|
||||
///
|
||||
/// boost::function conversion example
|
||||
/// std::function conversion example
|
||||
/// \code
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// Boxed_Value bv = chai.eval("`+`"); // Get the functor for the + operator which is built in
|
||||
/// boost::function<int (int, int)> f = chaiscript::boxed_cast<boost::function<int (int, int)> >(bv);
|
||||
/// std::function<int (int, int)> f = chaiscript::boxed_cast<std::function<int (int, int)> >(bv);
|
||||
/// int i = f(2,3);
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
@@ -72,22 +66,23 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv);
|
||||
} catch (const boost::bad_any_cast &) {
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
#ifdef CHAISCRIPT_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 (boost::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value)
|
||||
if (std::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 boost::bad_any_cast &) {
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
} else {
|
||||
@@ -96,7 +91,7 @@ namespace chaiscript
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
@@ -10,10 +10,6 @@
|
||||
#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
|
||||
{
|
||||
@@ -27,7 +23,7 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef typename boost::reference_wrapper<typename boost::add_const<Result>::type > Result_Type;
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -35,16 +31,16 @@ namespace chaiscript
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return boost::cref((boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get());
|
||||
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
|
||||
} else {
|
||||
return boost::any_cast<boost::reference_wrapper<const Result> >(ob.get());
|
||||
return ob.get().cast<std::reference_wrapper<const Result> >();
|
||||
}
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
|
||||
} else {
|
||||
return boost::cref(*(boost::any_cast<boost::shared_ptr<const Result> >(ob.get())));
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,16 +73,16 @@ namespace chaiscript
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
} else {
|
||||
return (boost::any_cast<boost::reference_wrapper<const Result> >(ob.get())).get_pointer();
|
||||
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
|
||||
}
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
} else {
|
||||
return (boost::any_cast<boost::shared_ptr<const Result> >(ob.get())).get();
|
||||
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,9 +100,9 @@ namespace chaiscript
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
return (boost::any_cast<boost::reference_wrapper<Result> >(ob.get())).get_pointer();
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
} else {
|
||||
return (boost::any_cast<boost::shared_ptr<Result> >(ob.get())).get();
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -117,76 +113,77 @@ namespace chaiscript
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef typename boost::reference_wrapper<Result> Result_Type;
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
static Result &cast(const Boxed_Value &ob)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
return boost::any_cast<boost::reference_wrapper<Result> >(ob.get());
|
||||
return ob.get().cast<std::reference_wrapper<Result> >();
|
||||
} else {
|
||||
return boost::ref(*(boost::any_cast<boost::shared_ptr<Result> >(ob.get())));
|
||||
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
|
||||
return r;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a boost::shared_ptr<> type
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename boost::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
|
||||
{
|
||||
typedef typename boost::shared_ptr<Result> Result_Type;
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
return boost::any_cast<boost::shared_ptr<Result> >(ob.get());
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a boost::shared_ptr<const> type
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename boost::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
|
||||
{
|
||||
typedef typename boost::shared_ptr<const Result> Result_Type;
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return boost::const_pointer_cast<const Result>(boost::any_cast<boost::shared_ptr<Result> >(ob.get()));
|
||||
return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
|
||||
} else {
|
||||
return boost::any_cast<boost::shared_ptr<const Result> >(ob.get());
|
||||
return ob.get().cast<std::shared_ptr<const Result> >();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<Result> > : Cast_Helper_Inner<boost::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<Result> &> : Cast_Helper_Inner<boost::shared_ptr<Result> >
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const boost::shared_ptr<const> & type
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> > : Cast_Helper_Inner<boost::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::shared_ptr<const Result> &> : Cast_Helper_Inner<boost::shared_ptr<const Result> >
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
};
|
||||
|
||||
@@ -221,35 +218,35 @@ namespace chaiscript
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a boost::reference_wrapper type
|
||||
* Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
*/
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const boost::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
|
||||
struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
|
||||
{
|
||||
};
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "../language/chaiscript_algebraic.hpp"
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -47,8 +47,9 @@ namespace chaiscript
|
||||
case Operators::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -81,7 +82,7 @@ namespace chaiscript
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
@@ -114,7 +115,7 @@ namespace chaiscript
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return t_lhs;
|
||||
}
|
||||
@@ -142,8 +143,9 @@ namespace chaiscript
|
||||
case Operators::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -167,8 +169,9 @@ namespace chaiscript
|
||||
case Operators::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -189,7 +192,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 boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -205,13 +208,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 boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
} else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) {
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::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 boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -237,24 +240,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(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 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 {
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,27 +281,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(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 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 {
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::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:
|
||||
@@ -313,6 +329,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(std::int8_t)) {
|
||||
return get_as_aux<Target, std::int8_t>();
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return get_as_aux<Target, std::int16_t>();
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return get_as_aux<Target, std::int32_t>();
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return get_as_aux<Target, std::int64_t>();
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return get_as_aux<Target, std::uint8_t>();
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return get_as_aux<Target, std::uint16_t>();
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return get_as_aux<Target, std::uint32_t>();
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return get_as_aux<Target, std::uint64_t>();
|
||||
} else {
|
||||
throw chaiscript::detail::exception::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(std::int8_t)) {
|
||||
return to_string_aux<int>(Boxed_Value(get_as_aux<int, std::int8_t>()));
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
return to_string_aux<std::int16_t>(bv);
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
return to_string_aux<std::int32_t>(bv);
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
return to_string_aux<std::int64_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
return to_string_aux<unsigned int>(Boxed_Value(get_as_aux<unsigned int, std::uint8_t>()));
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
return to_string_aux<std::uint16_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
return to_string_aux<std::uint32_t>(bv);
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
return to_string_aux<std::uint64_t>(bv);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Boxed_Number &t_rhs) const
|
||||
{
|
||||
@@ -384,12 +487,12 @@ namespace chaiscript
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == typeid(bool))
|
||||
{
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
if (!inp_.is_arithmetic())
|
||||
{
|
||||
throw boost::bad_any_cast();
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -12,14 +12,7 @@
|
||||
#include "../chaiscript_threading.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <boost/shared_ptr.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>
|
||||
#include "any.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -43,7 +36,7 @@ namespace chaiscript
|
||||
struct Data
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
const boost::any &to,
|
||||
const chaiscript::detail::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),
|
||||
@@ -67,7 +60,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
Type_Info m_type_info;
|
||||
boost::any m_obj;
|
||||
chaiscript::detail::Any m_obj;
|
||||
void *m_data_ptr;
|
||||
const void *m_const_data_ptr;
|
||||
bool m_is_ref;
|
||||
@@ -75,69 +68,69 @@ namespace chaiscript
|
||||
|
||||
struct Object_Data
|
||||
{
|
||||
static boost::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||
{
|
||||
return boost::shared_ptr<Data> (new Data(
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<void>::get(),
|
||||
boost::any(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
0)
|
||||
);
|
||||
nullptr)
|
||||
;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> *obj)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
|
||||
{
|
||||
return get(*obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
|
||||
{
|
||||
return boost::shared_ptr<Data>(new Data(
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(obj),
|
||||
chaiscript::detail::Any(obj),
|
||||
false,
|
||||
obj.get())
|
||||
obj.get()
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(T *t)
|
||||
static std::shared_ptr<Data> get(T *t)
|
||||
{
|
||||
return get(boost::ref(*t));
|
||||
return get(std::ref(*t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
|
||||
{
|
||||
return boost::shared_ptr<Data>(new Data(
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(obj),
|
||||
chaiscript::detail::Any(obj),
|
||||
true,
|
||||
obj.get_pointer())
|
||||
&obj.get()
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static boost::shared_ptr<Data> get(const T& t)
|
||||
static std::shared_ptr<Data> get(const T& t)
|
||||
{
|
||||
boost::shared_ptr<T> p(new T(t));
|
||||
return boost::shared_ptr<Data>(new Data(
|
||||
auto p = std::make_shared<T>(t);
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
boost::any(p),
|
||||
chaiscript::detail::Any(p),
|
||||
false,
|
||||
p.get())
|
||||
p.get()
|
||||
);
|
||||
}
|
||||
|
||||
static boost::shared_ptr<Data> get()
|
||||
static std::shared_ptr<Data> get()
|
||||
{
|
||||
return boost::shared_ptr<Data> (new Data(
|
||||
return std::make_shared<Data>(
|
||||
Type_Info(),
|
||||
boost::any(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
0)
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -226,7 +219,7 @@ namespace chaiscript
|
||||
return (m_data->m_data_ptr == 0 && m_data->m_const_data_ptr == 0);
|
||||
}
|
||||
|
||||
const boost::any & get() const
|
||||
const chaiscript::detail::Any & get() const
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
@@ -251,11 +244,17 @@ 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:
|
||||
boost::shared_ptr<Data> m_data;
|
||||
std::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, boost::shared_ptr, or boost::reference_type
|
||||
/// \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
|
||||
/// a copy is not made.
|
||||
/// \param t The value to box
|
||||
///
|
||||
@@ -282,7 +281,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(boost::shared_ptr<typename boost::add_const<T>::type >(new T(t)));
|
||||
return Boxed_Value(std::shared_ptr<typename std::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.
|
||||
@@ -293,33 +292,33 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(T *t)
|
||||
{
|
||||
return Boxed_Value( const_cast<typename boost::add_const<T>::type *>(t) );
|
||||
return Boxed_Value( const_cast<typename std::add_const<T>::type *>(t) );
|
||||
}
|
||||
|
||||
/// \brief Takes a boost::shared_ptr to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
/// \brief Takes a std::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 boost::shared_ptr<T> &t)
|
||||
Boxed_Value const_var_impl(const std::shared_ptr<T> &t)
|
||||
{
|
||||
return Boxed_Value( boost::const_pointer_cast<typename boost::add_const<T>::type>(t) );
|
||||
return Boxed_Value( std::const_pointer_cast<typename std::add_const<T>::type>(t) );
|
||||
}
|
||||
|
||||
/// \brief Takes a boost::reference_wrapper value, adds const to the referenced type and returns an immutable Boxed_Value.
|
||||
/// \brief Takes a std::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 boost::reference_wrapper<T> &t)
|
||||
Boxed_Value const_var_impl(const std::reference_wrapper<T> &t)
|
||||
{
|
||||
return Boxed_Value( boost::cref(t.get()) );
|
||||
return Boxed_Value( std::cref(t.get()) );
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a boost::reference or pointer type
|
||||
/// \brief Takes an object and returns an immutable Boxed_Value. If the object is a std::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
|
||||
@@ -349,11 +348,6 @@ 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,14 +11,12 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
@@ -41,12 +39,12 @@ namespace chaiscript
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
reserved_word_error(const std::string &t_word) throw()
|
||||
reserved_word_error(const std::string &t_word) noexcept
|
||||
: std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~reserved_word_error() throw() {}
|
||||
virtual ~reserved_word_error() noexcept {}
|
||||
|
||||
std::string word() const
|
||||
{
|
||||
@@ -88,12 +86,12 @@ namespace chaiscript
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
global_non_const() throw()
|
||||
global_non_const() noexcept
|
||||
: std::runtime_error("a global object must be const")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~global_non_const() throw() {}
|
||||
virtual ~global_non_const() noexcept {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -125,7 +123,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw exception::global_non_const();
|
||||
throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.push_back(std::make_pair(t_bv, t_name));
|
||||
@@ -140,7 +138,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const boost::shared_ptr<Module> &m)
|
||||
Module &add(const std::shared_ptr<Module> &m)
|
||||
{
|
||||
m->apply(*this, *this);
|
||||
return *m;
|
||||
@@ -156,6 +154,11 @@ 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;
|
||||
@@ -170,7 +173,7 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
t.add(begin->first, begin->second);
|
||||
} catch (const exception::name_conflict_error &) {
|
||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
@@ -210,7 +213,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/// Convenience typedef for Module objects to be added to the ChaiScript runtime
|
||||
typedef boost::shared_ptr<Module> ModulePtr;
|
||||
typedef std::shared_ptr<Module> ModulePtr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -373,7 +376,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 boost::shared_ptr<StackData> Stack;
|
||||
typedef std::shared_ptr<StackData> Stack;
|
||||
|
||||
struct State
|
||||
{
|
||||
@@ -382,10 +385,12 @@ 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(boost::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
: m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -447,7 +452,7 @@ namespace chaiscript
|
||||
Scope::iterator itr = scope.find(name);
|
||||
if (itr != stack.back().end())
|
||||
{
|
||||
throw exception::name_conflict_error(name);
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, obj));
|
||||
}
|
||||
@@ -461,14 +466,14 @@ namespace chaiscript
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw exception::global_non_const();
|
||||
throw chaiscript::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 exception::name_conflict_error(name);
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
m_state.m_global_objects.insert(std::make_pair(name, obj));
|
||||
}
|
||||
@@ -668,6 +673,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
|
||||
@@ -782,10 +808,9 @@ namespace chaiscript
|
||||
/**
|
||||
* Dump object info to stdout
|
||||
*/
|
||||
void dump_object(Boxed_Value o) const
|
||||
void dump_object(const Boxed_Value &o) const
|
||||
{
|
||||
Type_Info ti = o.get_type_info();
|
||||
std::cout << (ti.is_const()?"const ":"") << get_type_name(ti) << std::endl;
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -877,7 +902,7 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string type_name(Boxed_Value obj) const
|
||||
std::string type_name(const Boxed_Value &obj) const
|
||||
{
|
||||
return get_type_name(obj.get_type_info());
|
||||
}
|
||||
@@ -963,8 +988,8 @@ namespace chaiscript
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
if (dynamic_lhs && dynamic_rhs)
|
||||
{
|
||||
@@ -1056,7 +1081,7 @@ namespace chaiscript
|
||||
|
||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
||||
{
|
||||
throw exception::reserved_word_error(name);
|
||||
throw chaiscript::exception::reserved_word_error(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1084,7 +1109,7 @@ namespace chaiscript
|
||||
{
|
||||
if ((*t_f) == *(*itr2))
|
||||
{
|
||||
throw exception::name_conflict_error(t_name);
|
||||
throw chaiscript::exception::name_conflict_error(t_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,9 +11,6 @@
|
||||
#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
|
||||
{
|
||||
@@ -23,22 +20,22 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) throw()
|
||||
const std::string &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) throw()
|
||||
bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() throw() {}
|
||||
virtual ~bad_boxed_dynamic_cast() noexcept {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,8 +87,8 @@ namespace chaiscript
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_derived.is_const())
|
||||
{
|
||||
boost::shared_ptr<const Base> data
|
||||
= boost::dynamic_pointer_cast<const Base>(detail::Cast_Helper<boost::shared_ptr<const Derived> >::cast(t_derived));
|
||||
std::shared_ptr<const Base> data
|
||||
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
@@ -99,8 +96,8 @@ namespace chaiscript
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
boost::shared_ptr<Base> data
|
||||
= boost::dynamic_pointer_cast<Base>(detail::Cast_Helper<boost::shared_ptr<Derived> >::cast(t_derived));
|
||||
std::shared_ptr<Base> data
|
||||
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
@@ -115,15 +112,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(boost::cref(data));
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived);
|
||||
Base &data = dynamic_cast<Base &>(d);
|
||||
return Boxed_Value(boost::ref(data));
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -139,9 +136,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
static boost::shared_ptr<Dynamic_Conversion> create()
|
||||
static std::shared_ptr<Dynamic_Conversion> create()
|
||||
{
|
||||
boost::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>());
|
||||
std::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
|
||||
@@ -168,7 +165,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@@ -222,7 +219,7 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
typedef std::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.
|
||||
@@ -252,9 +249,9 @@ namespace chaiscript
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
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);
|
||||
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");
|
||||
|
||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
||||
}
|
||||
@@ -278,9 +275,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 exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -52,16 +51,26 @@ 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 boost::optional<Type_Info> &t_ti = boost::optional<Type_Info>())
|
||||
const Type_Info &t_ti)
|
||||
: 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(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(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)");
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
@@ -88,9 +97,7 @@ namespace chaiscript
|
||||
|
||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||
{
|
||||
std::vector<Const_Proxy_Function> fs;
|
||||
fs.push_back(m_func);
|
||||
return fs;
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
|
||||
@@ -123,23 +130,18 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
static std::vector<Type_Info> build_param_types(
|
||||
const std::vector<Type_Info> &t_inner_types, boost::optional<Type_Info> t_objectti)
|
||||
const std::vector<Type_Info> &t_inner_types, const Type_Info& t_objectti)
|
||||
{
|
||||
if (t_objectti)
|
||||
{
|
||||
std::vector<Type_Info> types(t_inner_types);
|
||||
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;
|
||||
} else {
|
||||
return t_inner_types;
|
||||
}
|
||||
assert(types.size() > 1);
|
||||
assert(types[1].bare_equal(user_type<Boxed_Value>()));
|
||||
types[1] = t_objectti;
|
||||
return types;
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const boost::optional<Type_Info> &ti)
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
{
|
||||
static Type_Info doti = user_type<Dynamic_Object>();
|
||||
if (bv.get_type_info().bare_equal(doti))
|
||||
@@ -162,7 +164,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
static bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const boost::optional<Type_Info> &ti)
|
||||
const std::shared_ptr<Type_Info> &ti)
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@@ -174,7 +176,7 @@ namespace chaiscript
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
boost::optional<Type_Info> m_ti;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
|
||||
};
|
||||
|
||||
@@ -193,10 +195,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 exception::bad_boxed_cast &) {}
|
||||
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::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 boost::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
|
||||
typedef std::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,9 +7,6 @@
|
||||
#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"
|
||||
@@ -25,13 +22,13 @@ namespace chaiscript
|
||||
/**
|
||||
* Build a function caller that knows how to dispatch on a set of functions
|
||||
* example:
|
||||
* boost::function<void (int)> f =
|
||||
* std::function<void (int)> f =
|
||||
* build_function_caller(dispatchkit.get_function("print"));
|
||||
* \returns A boost::function object for dispatching
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] funcs the set of functions to dispatch on.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
boost::function<FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||
{
|
||||
FunctionType *p=0;
|
||||
@@ -45,14 +42,14 @@ namespace chaiscript
|
||||
* example:
|
||||
* void my_function(Proxy_Function f)
|
||||
* {
|
||||
* boost::function<void (int)> local_f =
|
||||
* std::function<void (int)> local_f =
|
||||
* build_function_caller(f);
|
||||
* }
|
||||
* \returns A boost::function object for dispatching
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] func A function to execute.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
boost::function<FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func)
|
||||
{
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
@@ -65,7 +62,7 @@ namespace chaiscript
|
||||
* and creating a typesafe C++ function caller from it.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
boost::function<FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv));
|
||||
@@ -74,12 +71,12 @@ namespace chaiscript
|
||||
|
||||
namespace detail{
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const boost::function &
|
||||
* Cast helper to handle automatic casting to const std::function &
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const boost::function<Signature> &>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -87,18 +84,18 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const boost::function<Signature> &>::cast(ob);
|
||||
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to boost::function
|
||||
* Cast helper to handle automatic casting to std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<boost::function<Signature> >
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -106,18 +103,18 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<boost::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<std::function<Signature> >::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const boost::function
|
||||
* Cast helper to handle automatic casting to const std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const boost::function<Signature> >
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
typedef boost::function<Signature> Result_Type;
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob)
|
||||
{
|
||||
@@ -125,7 +122,7 @@ namespace chaiscript
|
||||
{
|
||||
return dispatch::functor<Signature>(ob);
|
||||
} else {
|
||||
return Cast_Helper_Inner<const boost::function<Signature> >::cast(ob);
|
||||
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -4,19 +4,9 @@
|
||||
// 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"
|
||||
@@ -54,50 +44,41 @@ 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) )
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs)
|
||||
: m_funcs(t_funcs)
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(n, addparam, ~)
|
||||
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)...
|
||||
}
|
||||
|
||||
return Function_Caller_Ret<Ret>::call(funcs, params);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* used internally for unwrapping a function call's types
|
||||
*/
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
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]);
|
||||
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
|
||||
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
|
||||
(funcs[0]);
|
||||
|
||||
if (pfi)
|
||||
{
|
||||
@@ -107,13 +88,11 @@ namespace chaiscript
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
|
||||
return boost::bind(&function_caller<Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Param)>, funcs
|
||||
BOOST_PP_ENUM_TRAILING(n, curry, ~));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "boxed_number.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -44,27 +43,27 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<boost::shared_ptr<Ret> &>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<boost::shared_ptr<Ret> >
|
||||
struct Handle_Return<std::shared_ptr<Ret> >
|
||||
{
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const boost::shared_ptr<Ret> &>
|
||||
struct Handle_Return<const std::shared_ptr<Ret> &>
|
||||
{
|
||||
static Boxed_Value handle(const boost::shared_ptr<Ret> &r)
|
||||
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
|
||||
{
|
||||
return Boxed_Value(r);
|
||||
}
|
||||
@@ -75,7 +74,7 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,12 +87,12 @@ namespace chaiscript
|
||||
{
|
||||
static Boxed_Value handle(Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::ref(r));
|
||||
return Boxed_Value(std::ref(r));
|
||||
}
|
||||
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return Boxed_Value(boost::cref(r));
|
||||
return Boxed_Value(std::cref(r));
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -7,6 +7,8 @@
|
||||
#ifndef CHAISCRIPT_OPERATORS_HPP_
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace bootstrap
|
||||
@@ -154,7 +156,7 @@ namespace chaiscript
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_minus(L l)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
|
@@ -4,24 +4,36 @@
|
||||
// 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, ...)
|
||||
@@ -39,43 +51,8 @@ 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 <boost/function.hpp>
|
||||
#include <boost/type_traits/add_reference.hpp>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include "proxy_functions_detail.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -23,42 +23,10 @@ namespace chaiscript
|
||||
class Boxed_Number;
|
||||
struct AST_Node;
|
||||
|
||||
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
|
||||
typedef std::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++
|
||||
@@ -81,14 +49,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.
|
||||
std::vector<Type_Info> get_param_types() const { return m_types; }
|
||||
const 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<boost::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||
virtual std::vector<std::shared_ptr<const Proxy_Function_Base> > get_contained_functions() const
|
||||
{
|
||||
return std::vector<boost::shared_ptr<const Proxy_Function_Base> >();
|
||||
return std::vector<std::shared_ptr<const Proxy_Function_Base> >();
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +109,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<boost::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -175,11 +143,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Common typedef used for passing of any registered function in ChaiScript
|
||||
typedef boost::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
|
||||
typedef std::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 boost::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
typedef std::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
|
||||
namespace exception
|
||||
{
|
||||
@@ -187,11 +155,11 @@ namespace chaiscript
|
||||
class guard_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
guard_error() throw()
|
||||
guard_error() noexcept
|
||||
: std::runtime_error("Guard evaluation failed")
|
||||
{ }
|
||||
|
||||
virtual ~guard_error() throw()
|
||||
virtual ~guard_error() noexcept
|
||||
{ }
|
||||
};
|
||||
}
|
||||
@@ -206,7 +174,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dynamic_Proxy_Function(
|
||||
const boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> &t_f,
|
||||
const std::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 = "",
|
||||
@@ -297,7 +265,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)
|
||||
{
|
||||
@@ -308,7 +276,7 @@ namespace chaiscript
|
||||
return types;
|
||||
}
|
||||
|
||||
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
std::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
|
||||
int m_arity;
|
||||
std::string m_description;
|
||||
Proxy_Function m_guard;
|
||||
@@ -413,6 +381,7 @@ 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();
|
||||
@@ -444,18 +413,18 @@ namespace chaiscript
|
||||
|
||||
/**
|
||||
* The standard typesafe function call implementation of Proxy_Function
|
||||
* It takes a boost::function<> object and performs runtime
|
||||
* It takes a std::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 boost::function<Func> &f)
|
||||
Proxy_Function_Impl(const std::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() {}
|
||||
|
||||
@@ -465,13 +434,11 @@ 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())
|
||||
@@ -487,7 +454,7 @@ namespace chaiscript
|
||||
return "";
|
||||
}
|
||||
|
||||
boost::function<Func> internal_function() const
|
||||
std::function<Func> internal_function() const
|
||||
{
|
||||
return m_f;
|
||||
}
|
||||
@@ -495,11 +462,11 @@ namespace chaiscript
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return detail::Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::function<Func> m_f;
|
||||
std::function<Func> m_f;
|
||||
Func *m_dummy_func;
|
||||
};
|
||||
|
||||
@@ -513,8 +480,8 @@ namespace chaiscript
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Attribute_Access() {}
|
||||
|
||||
@@ -522,6 +489,7 @@ 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 {
|
||||
@@ -559,10 +527,10 @@ namespace chaiscript
|
||||
if (bv.is_const())
|
||||
{
|
||||
const Class *o = boxed_cast<const Class *>(bv);
|
||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
} else {
|
||||
Class *o = boxed_cast<Class *>(bv);
|
||||
return detail::Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
|
||||
}
|
||||
} else {
|
||||
throw exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
@@ -572,11 +540,9 @@ namespace chaiscript
|
||||
private:
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
std::vector<Type_Info> v;
|
||||
v.push_back(user_type<T>());
|
||||
v.push_back(user_type<Class>());
|
||||
return v;
|
||||
return {user_type<T>(), user_type<Class>()};
|
||||
}
|
||||
|
||||
T Class::* m_attr;
|
||||
};
|
||||
}
|
||||
@@ -591,17 +557,16 @@ namespace chaiscript
|
||||
class dispatch_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
dispatch_error() throw()
|
||||
: std::runtime_error("No matching function to dispatch to")
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
dispatch_error(bool is_const) throw()
|
||||
: std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":""))
|
||||
{
|
||||
}
|
||||
virtual ~dispatch_error() noexcept {}
|
||||
|
||||
virtual ~dispatch_error() throw() {}
|
||||
std::vector<Boxed_Value> parameters;
|
||||
std::vector<Const_Proxy_Function> functions;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -614,9 +579,10 @@ namespace chaiscript
|
||||
* function is found or throw dispatch_error if no matching function is found
|
||||
*/
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, InItr end,
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist)
|
||||
{
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
@@ -635,7 +601,7 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
|
||||
throw exception::dispatch_error(plist.empty()?false:plist[0].is_const());
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -4,13 +4,6 @@
|
||||
// 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_
|
||||
|
||||
@@ -19,9 +12,6 @@
|
||||
#include "type_info.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -42,26 +32,13 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~arity_error() throw() {}
|
||||
virtual ~arity_error() noexcept {}
|
||||
|
||||
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
|
||||
@@ -70,62 +47,104 @@ namespace chaiscript
|
||||
* Used by Proxy_Function_Impl to return a list of all param types
|
||||
* it contains.
|
||||
*/
|
||||
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)))
|
||||
template<typename Ret, typename ... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
||||
{
|
||||
std::vector<Type_Info> ti;
|
||||
ti.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
|
||||
|
||||
BOOST_PP_REPEAT(n, gettypeinfo, ~)
|
||||
|
||||
return ti;
|
||||
return std::vector<Type_Info> { chaiscript::detail::Get_Type_Info<Ret>::get(),
|
||||
chaiscript::detail::Get_Type_Info<Params>::get()... };
|
||||
}
|
||||
|
||||
|
||||
// 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 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,
|
||||
template<typename Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
if (params.size() != n)
|
||||
if (params.size() == sizeof...(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;
|
||||
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params);
|
||||
}
|
||||
|
||||
return true;
|
||||
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef n
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -137,7 +156,7 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params));
|
||||
}
|
||||
@@ -147,7 +166,7 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const boost::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms)
|
||||
{
|
||||
call_func(fun, params);
|
||||
return Handle_Return<void>::handle();
|
||||
|
@@ -9,12 +9,6 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@@ -22,39 +16,48 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<bool Object, bool MemFn>
|
||||
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>
|
||||
struct Fun_Helper
|
||||
{
|
||||
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
|
||||
>(t)));
|
||||
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
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>
|
||||
struct Fun_Helper<true>
|
||||
{
|
||||
template<typename T, typename Class>
|
||||
static Proxy_Function go(T Class::* m)
|
||||
@@ -65,19 +68,19 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a boost::function object
|
||||
/// \param[in] f boost::function to expose to ChaiScript
|
||||
/// \brief Creates a new Proxy_Function object from a std::function object
|
||||
/// \param[in] f std::function to expose to ChaiScript
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// boost::function<int (char, float, std::string)> f = get_some_function();
|
||||
/// std::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 boost::function<T> &f)
|
||||
Proxy_Function fun(const std::function<T> &f)
|
||||
{
|
||||
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
|
||||
}
|
||||
@@ -105,7 +108,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Proxy_Function fun(T 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);
|
||||
return dispatch::detail::Fun_Helper<std::is_member_object_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
|
||||
@@ -122,7 +125,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, boost::ref(obj)), "memberfunction");
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
@@ -148,7 +151,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, boost::ref(obj), 1), "memberfunction");
|
||||
/// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction");
|
||||
/// \endcode
|
||||
///
|
||||
/// \sa \ref addingfunctions
|
||||
|
@@ -9,17 +9,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#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>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@@ -29,7 +20,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Bare_Type
|
||||
{
|
||||
typedef typename boost::remove_const<typename boost::remove_pointer<typename boost::remove_reference<T>::type>::type>::type type;
|
||||
typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -147,72 +138,72 @@ namespace chaiscript
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
constexpr static Type_Info get()
|
||||
{
|
||||
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,
|
||||
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,
|
||||
&typeid(T),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<boost::shared_ptr<T> >
|
||||
struct Get_Type_Info<std::shared_ptr<T> >
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
constexpr static Type_Info get()
|
||||
{
|
||||
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> ),
|
||||
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> ),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const boost::shared_ptr<T> &>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
constexpr static Type_Info get()
|
||||
{
|
||||
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> &),
|
||||
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> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<boost::reference_wrapper<T> >
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
constexpr static Type_Info get()
|
||||
{
|
||||
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> ),
|
||||
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> ),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const boost::reference_wrapper<T> &>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
{
|
||||
typedef T type;
|
||||
|
||||
static Type_Info get()
|
||||
constexpr static Type_Info get()
|
||||
{
|
||||
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> &),
|
||||
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> &),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
};
|
||||
@@ -234,7 +225,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Type_Info user_type(const T &/*t*/)
|
||||
constexpr Type_Info user_type(const T &/*t*/)
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
@@ -249,7 +240,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
Type_Info user_type()
|
||||
constexpr Type_Info user_type()
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
@@ -7,8 +7,7 @@
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
|
@@ -7,8 +7,8 @@
|
||||
#ifndef CHAISCRIPT_COMMON_HPP_
|
||||
#define CHAISCRIPT_COMMON_HPP_
|
||||
|
||||
#include <chaiscript/dispatchkit/dispatchkit.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <sstream>
|
||||
#include "../dispatchkit/dispatchkit.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, Switch, Case, Default, Ternary_Cond
|
||||
Logical_And, Logical_Or, Reference, 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", "Switch", "Case", "Default", "Ternary Condition"};
|
||||
"Logical_And", "Logical_Or", "Reference", "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 boost::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<struct AST_Node> AST_NodePtr;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
@@ -69,48 +69,351 @@ 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) throw() :
|
||||
std::runtime_error("Error: \"" + t_why + "\" " +
|
||||
(t_fname != "__EVAL__" ? ("in '" + t_fname + "' ") : "during evaluation ") +
|
||||
+ "at (" + boost::lexical_cast<std::string>(t_where.line) + ", " +
|
||||
boost::lexical_cast<std::string>(t_where.column) + ")"),
|
||||
reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname)
|
||||
{ }
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
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) throw()
|
||||
eval_error(const std::string &t_why,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
bool t_dot_notation,
|
||||
const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
|
||||
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 :
|
||||
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
|
||||
: std::runtime_error("Error: \"" + t_why + "\" "),
|
||||
reason(t_why)
|
||||
{}
|
||||
|
||||
virtual ~eval_error() throw() {}
|
||||
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() noexcept {}
|
||||
|
||||
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_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();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
|
||||
= std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
|
||||
|
||||
if (dynfun)
|
||||
{
|
||||
Proxy_Function f = dynfun->get_guard();
|
||||
|
||||
if (f)
|
||||
{
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfunguard
|
||||
= std::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;
|
||||
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 (std::vector<Boxed_Value>::const_iterator itr = t_parameters.begin();
|
||||
itr != t_parameters.end();
|
||||
++itr)
|
||||
{
|
||||
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);
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format_filename(const std::string &t_fname)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
if (t_fname != "__EVAL__")
|
||||
{
|
||||
ss << "in '" << t_fname << "' ";
|
||||
} else {
|
||||
ss << "during evaluation ";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format_location(const File_Position &t_where)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "at (" << t_where.line << ", " << t_where.column << ")";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
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, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
ss << format_filename(t_fname);
|
||||
ss << " ";
|
||||
|
||||
ss << format_location(t_where);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why,
|
||||
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 << "With parameters: " << format_parameters(t_parameters, t_dot_notation, t_ss);
|
||||
ss << " ";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << format_why(t_why);
|
||||
ss << " ";
|
||||
|
||||
ss << format_filename(t_fname);
|
||||
ss << " ";
|
||||
|
||||
ss << format_location(t_where);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors generated when loading a file
|
||||
*/
|
||||
struct file_not_found_error : public std::runtime_error {
|
||||
file_not_found_error(const std::string &t_filename) throw()
|
||||
file_not_found_error(const std::string &t_filename) noexcept
|
||||
: std::runtime_error("File Not Found: " + t_filename)
|
||||
{ }
|
||||
|
||||
virtual ~file_not_found_error() throw() {}
|
||||
virtual ~file_not_found_error() noexcept {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// \brief Struct that doubles as both a parser ast_node and an AST node.
|
||||
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
|
||||
struct AST_Node : std::enable_shared_from_this<AST_Node> {
|
||||
public:
|
||||
const std::string text;
|
||||
const int identifier;
|
||||
boost::shared_ptr<const std::string> filename;
|
||||
const int identifier; //< \todo shouldn't this be a strongly typed enum value?
|
||||
std::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
|
||||
*/
|
||||
@@ -147,14 +450,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::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 boost::shared_ptr<std::string> &t_fname) :
|
||||
AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname) :
|
||||
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
@@ -10,12 +10,17 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include <chaiscript/language/chaiscript_common.hpp>
|
||||
#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 BOOST_WINDOWS
|
||||
#ifdef CHAISCRIPT_WINDOWS
|
||||
#define VC_EXTRA_LEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
@@ -23,8 +28,8 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include <chaiscript/language/chaiscript_prelude.hpp>
|
||||
#include <chaiscript/language/chaiscript_parser.hpp>
|
||||
#include "chaiscript_prelude.chai"
|
||||
#include "chaiscript_parser.hpp"
|
||||
#include "../dispatchkit/exception_specification.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -34,12 +39,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) throw()
|
||||
load_module_error(const std::string &t_reason) noexcept
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~load_module_error() throw()
|
||||
virtual ~load_module_error() noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -57,7 +62,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw exception::load_module_error(dlerror());
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +85,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw exception::load_module_error(dlerror());
|
||||
throw chaiscript::exception::load_module_error(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +185,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +205,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!m_symbol)
|
||||
{
|
||||
throw exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
throw chaiscript::exception::load_module_error(GetErrorMessage(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +228,7 @@ namespace chaiscript
|
||||
{
|
||||
Loadable_Module(const std::string &, const std::string &)
|
||||
{
|
||||
throw exception::load_module_error("Loadable module support not available for your platform");
|
||||
throw chaiscript::exception::load_module_error("Loadable module support not available for your platform");
|
||||
}
|
||||
|
||||
ModulePtr m_moduleptr;
|
||||
@@ -231,7 +236,7 @@ namespace chaiscript
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef boost::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
typedef std::shared_ptr<Loadable_Module> Loadable_Module_Ptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +298,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current evaluation m_engine
|
||||
*/
|
||||
@@ -304,9 +308,7 @@ namespace chaiscript
|
||||
/**
|
||||
* Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude.
|
||||
*/
|
||||
void build_eval_system() {
|
||||
using namespace bootstrap;
|
||||
m_engine.add_reserved_word("auto");
|
||||
void build_eval_system(const ModulePtr &t_lib) {
|
||||
m_engine.add_reserved_word("def");
|
||||
m_engine.add_reserved_word("fun");
|
||||
m_engine.add_reserved_word("while");
|
||||
@@ -316,25 +318,27 @@ namespace chaiscript
|
||||
m_engine.add_reserved_word("&&");
|
||||
m_engine.add_reserved_word("||");
|
||||
m_engine.add_reserved_word(",");
|
||||
m_engine.add_reserved_word(":=");
|
||||
m_engine.add_reserved_word("var");
|
||||
m_engine.add_reserved_word("auto");
|
||||
m_engine.add_reserved_word("return");
|
||||
m_engine.add_reserved_word("break");
|
||||
m_engine.add_reserved_word("true");
|
||||
m_engine.add_reserved_word("false");
|
||||
m_engine.add_reserved_word("_");
|
||||
|
||||
add(Bootstrap::bootstrap());
|
||||
if (t_lib)
|
||||
{
|
||||
add(t_lib);
|
||||
}
|
||||
|
||||
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::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::get_type_name, boost::ref(m_engine)), "name");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||
|
||||
|
||||
typedef void (ChaiScript::*load_mod_1)(const std::string&);
|
||||
@@ -343,16 +347,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");
|
||||
|
||||
do_eval(chaiscript_prelude, "standard prelude");
|
||||
do_eval(ChaiScript_Prelude::chaiscript_prelude, "standard prelude");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,7 +361,7 @@ namespace chaiscript
|
||||
std::ifstream infile(t_filename.c_str(), std::ios::in | std::ios::ate | std::ios::binary );
|
||||
|
||||
if (!infile.is_open()) {
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
@@ -382,9 +381,11 @@ 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 std::vector<std::string> &t_modulepaths = std::vector<std::string>(),
|
||||
ChaiScript(const ModulePtr &t_lib,
|
||||
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)
|
||||
{
|
||||
@@ -398,9 +399,74 @@ namespace chaiscript
|
||||
m_usepaths.push_back("");
|
||||
}
|
||||
|
||||
build_eval_system();
|
||||
build_eval_system(t_lib);
|
||||
}
|
||||
|
||||
/// \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.
|
||||
@@ -438,7 +504,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 exception::global_non_const If t_bv is not a constant object
|
||||
/// \throw chaiscript::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)
|
||||
{
|
||||
@@ -456,8 +522,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:
|
||||
///
|
||||
@@ -478,6 +548,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:
|
||||
@@ -497,7 +571,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
|
||||
@@ -554,7 +644,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 exception::load_module_error In the event that no matching module can be found.
|
||||
/// \throw chaiscript::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;
|
||||
@@ -578,7 +668,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 exception::load_module_error &e) {
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
@@ -600,7 +690,7 @@ namespace chaiscript
|
||||
errstring += itr->what();
|
||||
}
|
||||
|
||||
throw exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
throw chaiscript::exception::load_module_error("Unable to find module: " + t_module_name + " Errors: " + errstring);
|
||||
}
|
||||
|
||||
/// \brief Load a binary module from a dynamic library. Works on platforms that support
|
||||
@@ -634,7 +724,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \return result of the script execution
|
||||
///
|
||||
/// \throw exception::eval_error In the case that evaluation fails.
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler())
|
||||
{
|
||||
try {
|
||||
@@ -652,17 +742,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 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
|
||||
/// \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
|
||||
/// 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);
|
||||
@@ -675,14 +767,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 exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler())
|
||||
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);
|
||||
@@ -695,7 +789,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 exception::eval_error In the case that evaluation fails.
|
||||
/// \throw chaiscript::exception::eval_error In the case that evaluation fails.
|
||||
Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
|
||||
try {
|
||||
return do_eval(load_file(t_filename), t_filename);
|
||||
@@ -712,8 +806,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 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
|
||||
/// \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
|
||||
/// 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,8 +10,8 @@
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#include "chaiscript_prelude.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -33,6 +33,8 @@ namespace chaiscript
|
||||
, bin_alphabet
|
||||
, id_alphabet
|
||||
, white_alphabet
|
||||
, int_suffix_alphabet
|
||||
, float_suffix_alphabet
|
||||
, max_alphabet
|
||||
, lengthof_alphabet = 256
|
||||
};
|
||||
@@ -45,7 +47,7 @@ namespace chaiscript
|
||||
std::string m_multiline_comment_begin;
|
||||
std::string m_multiline_comment_end;
|
||||
std::string m_singleline_comment;
|
||||
boost::shared_ptr<std::string> m_filename;
|
||||
std::shared_ptr<std::string> m_filename;
|
||||
std::vector<AST_NodePtr> m_match_stack;
|
||||
bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet];
|
||||
|
||||
@@ -175,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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,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;
|
||||
@@ -371,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;
|
||||
@@ -386,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
|
||||
*/
|
||||
@@ -419,6 +451,164 @@ 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));
|
||||
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;
|
||||
}
|
||||
|
||||
static_assert(sizeof(long) == sizeof(uint64_t) || sizeof(long) * 2 == sizeof(uint64_t), "Unexpected sizing of integer types");
|
||||
|
||||
if ((sizeof(long) < sizeof(uint64_t))
|
||||
&& (u >> ((sizeof(uint64_t) - sizeof(long)) * 8)) > 0)
|
||||
{
|
||||
//requires something bigger than long
|
||||
longlong_ = true;
|
||||
}
|
||||
|
||||
|
||||
if (longlong_)
|
||||
{
|
||||
size = sizeof(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_)
|
||||
{
|
||||
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_)
|
||||
{
|
||||
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
|
||||
*/
|
||||
@@ -435,19 +625,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;
|
||||
int64_t temp_int = 0;
|
||||
size_t pos = 0, end = match.length();
|
||||
|
||||
while ((pos < end) && (pos < (2 + sizeof(int) * 8))) {
|
||||
@@ -458,32 +643,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;
|
||||
@@ -1483,10 +1672,10 @@ namespace chaiscript
|
||||
while (Eol()) {}
|
||||
|
||||
while (Case()) {
|
||||
while (Eol());
|
||||
while (Eol()) { } // eat
|
||||
}
|
||||
|
||||
while (Eol());
|
||||
while (Eol()) { } // eat
|
||||
|
||||
if (!Char('}')) {
|
||||
throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename);
|
||||
@@ -1631,10 +1820,10 @@ namespace chaiscript
|
||||
|
||||
size_t prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (Keyword("var")) {
|
||||
if (Keyword("auto") || Keyword("var")) {
|
||||
retval = true;
|
||||
|
||||
if (!Id(true)) {
|
||||
if (!(Reference() || Id(true))) {
|
||||
throw exception::eval_error("Incomplete variable declaration", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
@@ -1672,7 +1861,7 @@ namespace chaiscript
|
||||
throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
if (!Char(')')) {
|
||||
throw exception::eval_error("Missing closing parenthesis", File_Position(m_line, m_col), *m_filename);
|
||||
throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
@@ -1690,7 +1879,7 @@ namespace chaiscript
|
||||
retval = true;
|
||||
Container_Arg_List();
|
||||
if (!Char(']')) {
|
||||
throw exception::eval_error("Missing closing square bracket", 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) {
|
||||
@@ -1711,6 +1900,25 @@ 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
|
||||
*/
|
||||
@@ -1773,6 +1981,15 @@ 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;
|
||||
}
|
||||
@@ -2059,6 +2276,11 @@ 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);
|
||||
@@ -2072,11 +2294,6 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else {
|
||||
has_more = false;
|
||||
}
|
||||
@@ -2093,7 +2310,7 @@ namespace chaiscript
|
||||
m_input_end = t_input.end();
|
||||
m_line = 1;
|
||||
m_col = 1;
|
||||
m_filename = boost::shared_ptr<std::string>(new std::string(t_fname));
|
||||
m_filename = std::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())) {
|
||||
|
530
include/chaiscript/language/chaiscript_prelude.chai
Normal file
530
include/chaiscript/language/chaiscript_prelude.chai
Normal file
@@ -0,0 +1,530 @@
|
||||
// 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_PRELUDE_HPP_
|
||||
#define CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
namespace chaiscript {
|
||||
struct ChaiScript_Prelude {
|
||||
constexpr static const char *chaiscript_prelude=R""(
|
||||
|
||||
def lt(l, r) {
|
||||
if (call_exists(`<`, l, r)) {
|
||||
l < r
|
||||
} else {
|
||||
type_name(l) < type_name(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def gt(l, r) {
|
||||
if (call_exists(`>`, l, r)) {
|
||||
l > r
|
||||
} else {
|
||||
type_name(l) > type_name(r)
|
||||
}
|
||||
}
|
||||
|
||||
def eq(l, r) {
|
||||
if (call_exists(`==`, l, r)) {
|
||||
l == r
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def new(x) {
|
||||
eval(type_name(x))();
|
||||
}
|
||||
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x)
|
||||
{
|
||||
eval(type_name(x))(x);
|
||||
}
|
||||
|
||||
|
||||
# to_string for Pair()
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) {
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">";
|
||||
}
|
||||
|
||||
# to_string for containers
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){
|
||||
"[" + x.join(", ") + "]";
|
||||
}
|
||||
|
||||
# Basic to_string function
|
||||
def to_string(x) {
|
||||
internal_to_string(x);
|
||||
}
|
||||
|
||||
# Prints to console with no carriage return
|
||||
def puts(x) {
|
||||
print_string(x.to_string());
|
||||
}
|
||||
|
||||
# Prints to console with carriage return
|
||||
def print(x) {
|
||||
println_string(x.to_string());
|
||||
}
|
||||
|
||||
# Returns the maximum value of two numbers
|
||||
def max(a, b) {
|
||||
if (a>b) {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
# Returns the minimum value of two numbers
|
||||
def min(a, b)
|
||||
{
|
||||
if (a<b)
|
||||
{
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns true if the value is odd
|
||||
def odd(x) {
|
||||
if (x % 2 == 1)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns true if the value is even
|
||||
def even(x)
|
||||
{
|
||||
if (x % 2 == 0)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Pushes the second value onto the container first value while making a clone of the value
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x)
|
||||
{
|
||||
container.push_back_ref(clone(x))
|
||||
}
|
||||
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x)
|
||||
{
|
||||
container.push_front_ref(clone(x))
|
||||
}
|
||||
|
||||
# Inserts the third value at the position of the second value into the container of the first
|
||||
# while making a clone.
|
||||
def insert_at(container, pos, x)
|
||||
{
|
||||
container.insert_ref_at(pos, clone(x));
|
||||
}
|
||||
|
||||
# Returns the reverse of the given container
|
||||
def reverse(container) {
|
||||
auto retval = new(container);
|
||||
auto r = range(container);
|
||||
while (!r.empty()) {
|
||||
retval.push_back(r.back());
|
||||
r.pop_back();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
# Return a range from a range
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
return clone(r);
|
||||
}
|
||||
|
||||
|
||||
# The retro attribute that contains the underlying range
|
||||
attr retro::m_range;
|
||||
|
||||
# Creates a retro from a retro by returning the original range
|
||||
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro"
|
||||
{
|
||||
clone(r.m_range)
|
||||
}
|
||||
|
||||
|
||||
# Creates a retro range from a range
|
||||
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r)
|
||||
{
|
||||
this.m_range = r;
|
||||
}
|
||||
|
||||
# Returns the first value of a retro
|
||||
def retro::front()
|
||||
{
|
||||
back(this.m_range)
|
||||
}
|
||||
|
||||
# Returns the last value of a retro
|
||||
def retro::back()
|
||||
{
|
||||
front(this.m_range)
|
||||
}
|
||||
|
||||
# Moves the back iterator of a retro towards the front by one
|
||||
def retro::pop_back()
|
||||
{
|
||||
pop_front(this.m_range)
|
||||
}
|
||||
|
||||
# Moves the front iterator of a retro towards the back by one
|
||||
def retro::pop_front()
|
||||
{
|
||||
pop_back(this.m_range)
|
||||
}
|
||||
|
||||
# returns true if the retro is out of elements
|
||||
def retro::empty()
|
||||
{
|
||||
empty(this.m_range);
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value
|
||||
def for_each(container, func) : call_exists(range, container) {
|
||||
var t_range = range(container);
|
||||
while (!t_range.empty()) {
|
||||
func(t_range.front());
|
||||
t_range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
def back_inserter(container) {
|
||||
bind(push_back, container, _);
|
||||
}
|
||||
|
||||
def contains(container, item, compare_func) : call_exists(range, container) {
|
||||
auto t_range = range(container);
|
||||
while (!t_range.empty()) {
|
||||
if ( compare_func(t_range.front(), item) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
t_range.pop_front();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
def contains(container, item) {
|
||||
return contains(container, item, eq)
|
||||
}
|
||||
|
||||
def map(container, func, inserter) : call_exists(range, container) {
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
inserter(func(range.front()));
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value. Creates a new container with the results
|
||||
def map(container, func) {
|
||||
auto retval = new(container);
|
||||
map(container, func, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
# Performs the second value function over the container first value. Starts with initial and continues with each element.
|
||||
def foldl(container, func, initial) : call_exists(range, container){
|
||||
auto retval = initial;
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
retval = (func(range.front(), retval));
|
||||
range.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
# Returns the sum of the elements of the given value
|
||||
def sum(container) {
|
||||
foldl(container, `+`, 0.0)
|
||||
}
|
||||
|
||||
# Returns the product of the elements of the given value
|
||||
def product(container) {
|
||||
foldl(container, `*`, 1.0)
|
||||
}
|
||||
|
||||
# Returns a new container with the elements of the first value concatenated with the elements of the second value
|
||||
def concat(x, y) : call_exists(clone, x) {
|
||||
auto retval = x;
|
||||
auto inserter = back_inserter(retval);
|
||||
auto range = range(y);
|
||||
while (!range.empty()) {
|
||||
inserter(range.front());
|
||||
range.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def take(container, num, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given number of elements taken from the container
|
||||
def take(container, num) {
|
||||
auto retval = new(container);
|
||||
take(container, num, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def take_while(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while ((!r.empty()) && f(r.front())) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given elements match the second value function
|
||||
def take_while(container, f) {
|
||||
auto retval = new(container);
|
||||
take_while(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def drop(container, num, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto i = num;
|
||||
while ((i > 0) && (!r.empty())) {
|
||||
r.pop_front();
|
||||
--i;
|
||||
}
|
||||
while (!r.empty()) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given number of elements dropped from the given container
|
||||
def drop(container, num) {
|
||||
auto retval = new(container);
|
||||
drop(container, num, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def drop_while(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while ((!r.empty())&& f(r.front())) {
|
||||
r.pop_front();
|
||||
}
|
||||
while (!r.empty()) {
|
||||
inserter(r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new container with the given elements dropped that match the second value function
|
||||
def drop_while(container, f) {
|
||||
auto retval = new(container);
|
||||
drop_while(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Applies the second value function to the container. Starts with the first two elements. Expects at least 2 elements.
|
||||
def reduce(container, func) : container.size() >= 2 && call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
auto retval = r.front();
|
||||
r.pop_front();
|
||||
retval = func(retval, r.front());
|
||||
r.pop_front();
|
||||
while (!r.empty()) {
|
||||
retval = func(retval, r.front());
|
||||
r.pop_front();
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a string of the elements in container delimited by the second value string
|
||||
def join(container, delim) {
|
||||
auto retval = "";
|
||||
auto range = range(container);
|
||||
if (!range.empty()) {
|
||||
retval += to_string(range.front());
|
||||
range.pop_front();
|
||||
while (!range.empty()) {
|
||||
retval += delim;
|
||||
retval += to_string(range.front());
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def filter(container, f, inserter) : call_exists(range, container) {
|
||||
auto r = range(container);
|
||||
while (!r.empty()) {
|
||||
if (f(r.front())) {
|
||||
inserter(r.front());
|
||||
}
|
||||
r.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which match the second value function
|
||||
def filter(container, f) {
|
||||
auto retval = new(container);
|
||||
filter(container, f, back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
def generate_range(x, y, inserter) {
|
||||
auto i = x;
|
||||
while (i <= y) {
|
||||
inserter(i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which represents the range from the first value to the second value
|
||||
def generate_range(x, y) {
|
||||
auto retval = Vector();
|
||||
generate_range(x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector with the first value to the second value as its elements
|
||||
def collate(x, y) {
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(range, y) {
|
||||
auto r_x = range(x);
|
||||
auto r_y = range(y);
|
||||
while (!r_x.empty() && !r_y.empty()) {
|
||||
inserter(f(r_x.front(), r_y.front()));
|
||||
r_x.pop_front();
|
||||
r_y.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which joins matching elements of the second and third value with the first value function
|
||||
def zip_with(f, x, y) {
|
||||
auto retval = Vector();
|
||||
zip_with(f,x,y,back_inserter(retval));
|
||||
retval;
|
||||
}
|
||||
|
||||
|
||||
# Returns a new Vector which joins matching elements of the first and second
|
||||
def zip(x, y) {
|
||||
zip_with(collate, x, y);
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the second value string in the first value string
|
||||
def string::find(substr) : is_type(substr, "string") {
|
||||
int(find(this, substr, 0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of last match of the second value string in the first value string
|
||||
def string::rfind(substr) : is_type(substr, "string") {
|
||||
int(rfind(this, substr, -1));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the first match of elements in the second value string in the first value string
|
||||
def string::find_first_of(list) : is_type(list, "string") {
|
||||
int(find_first_of(this, list, 0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the last match of elements in the second value string in the first value string
|
||||
def string::find_last_of(list) : is_type(list, "string") {
|
||||
int(find_last_of(this, list, -1));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the first non-matching element in the second value string in the first value string
|
||||
def string::find_first_not_of(list) : is_type(list, "string") {
|
||||
int(find_first_not_of(this, list, 0));
|
||||
}
|
||||
|
||||
|
||||
# Returns the position of the last non-matching element in the second value string in the first value string
|
||||
def string::find_last_not_of(list) : is_type(list, "string") {
|
||||
int(find_last_not_of(this, list, -1));
|
||||
}
|
||||
|
||||
|
||||
def string::ltrim() {
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'});
|
||||
}
|
||||
|
||||
|
||||
def string::rtrim() {
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}));
|
||||
}
|
||||
|
||||
|
||||
def string::trim() {
|
||||
ltrim(rtrim(this));
|
||||
}
|
||||
|
||||
|
||||
def find(container, value, compare_func) : call_exists(range, container) && is_type(compare_func, "Function") {
|
||||
auto range = range(container);
|
||||
while (!range.empty()) {
|
||||
if (compare_func(range.front(), value)) {
|
||||
return range;
|
||||
} else {
|
||||
range.pop_front();
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
|
||||
def find(container, value) {
|
||||
return find(container, value, eq)
|
||||
}
|
||||
|
||||
|
||||
)"";
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
@@ -1,329 +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_PRELUDE_HPP_
|
||||
#define CHAISCRIPT_PRELUDE_HPP_
|
||||
|
||||
//Note, the expression "[x,y]" in "collate" is parsed as two separate expressions
|
||||
//by C++, so CODE_STRING, takes two expressions and adds in the missing comma
|
||||
#define CODE_STRING(x, y) #x ", " #y
|
||||
|
||||
#define chaiscript_prelude CODE_STRING(\
|
||||
def lt(l, r) { if (call_exists(`<`, l, r)) { l < r } else { type_name(l) < type_name(r) } } \n\
|
||||
def gt(l, r) { if (call_exists(`>`, l, r)) { l > r } else { type_name(l) > type_name(r) } } \n\
|
||||
def eq(l, r) { if (call_exists(`==`, l, r)) { l == r } else { false } } \n\
|
||||
def new(x) { eval(type_name(x))(); } \n\
|
||||
def clone(x) : function_exists(type_name(x)) && call_exists(eval(type_name(x)), x) { eval(type_name(x))(x); } \n\
|
||||
# to_string for Pair()\n\
|
||||
def to_string(x) : call_exists(first, x) && call_exists(second, x) { \n\
|
||||
"<" + x.first.to_string() + ", " + x.second.to_string() + ">"; \n\
|
||||
}\n\
|
||||
# to_string for containers\n\
|
||||
def to_string(x) : call_exists(range, x) && !x.is_type("string"){ \n\
|
||||
"[" + x.join(", ") + "]"; \n\
|
||||
}\n\
|
||||
# Basic to_string function\n\
|
||||
def to_string(x) { \n\
|
||||
internal_to_string(x); \n\
|
||||
}\n\
|
||||
# Prints to console with no carriage return\n\
|
||||
def puts(x) { \n\
|
||||
print_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Prints to console with carriage return\n\
|
||||
def print(x) { \n\
|
||||
println_string(x.to_string()); \n\
|
||||
} \n\
|
||||
# Returns the maximum value of two numbers\n\
|
||||
def max(a, b) { if (a>b) { a } else { b } } \n\
|
||||
# Returns the minimum value of two numbers\n\
|
||||
def min(a, b) { if (a<b) { a } else { b } } \n\
|
||||
# Returns true if the value is odd\n\
|
||||
def odd(x) { if (x % 2 == 1) { true } else { false } } \n\
|
||||
# Returns true if the value is even\n\
|
||||
def even(x) { if (x % 2 == 0) { true } else { false } } \n\
|
||||
# Pushes the second value onto the container first value while making a clone of the value\n\
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x) { container.push_back_ref(clone(x)) } \n\
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value\n\
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x) { container.push_front_ref(clone(x)) } \n\
|
||||
# Inserts the third value at the position of the second value into the container of the first\n\
|
||||
# while making a clone. \n\
|
||||
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\
|
||||
var retval = new(container); \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval.push_back(r.back()); \n\
|
||||
r.pop_back(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Return a range from a range \n\
|
||||
def range(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { return clone(r); }\n\
|
||||
# The retro attribute that contains the underlying range \n\
|
||||
attr retro::m_range; \n\
|
||||
# Creates a retro from a retro by returning the original range\n\
|
||||
def retro(r) : call_exists(get_type_name, r) && get_type_name(r) == "retro" { clone(r.m_range) }\n\
|
||||
# Creates a retro range from a range\n\
|
||||
def retro::retro(r) : call_exists(empty, r) && call_exists(pop_front, r) && call_exists(pop_back, r) && call_exists(back, r) && call_exists(front, r) { this.m_range = r; }\n\
|
||||
# Returns the first value of a retro\n\
|
||||
def retro::front() { back(this.m_range) }\n\
|
||||
# Returns the last value of a retro\n\
|
||||
def retro::back() { front(this.m_range) }\n\
|
||||
# Moves the back iterator of a retro towards the front by one \n\
|
||||
def retro::pop_back() { pop_front(this.m_range) }\n\
|
||||
# Moves the front iterator of a retro towards the back by one \n\
|
||||
def retro::pop_front() { pop_back(this.m_range) } \n\
|
||||
# returns true if the retro is out of elements \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\
|
||||
var t_range = range(container); \n\
|
||||
while (!t_range.empty()) { \n\
|
||||
func(t_range.front()); \n\
|
||||
t_range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
def back_inserter(container) { \n\
|
||||
bind(push_back, container, _); \n\
|
||||
}\n\
|
||||
\n\
|
||||
def contains(container, item, compare_func) : call_exists(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\
|
||||
} \n\
|
||||
return false; \n\
|
||||
} \n\
|
||||
def contains(container, item) { return contains(container, item, eq) } \n\
|
||||
def map(container, func, inserter) : call_exists(range, container) { \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
inserter(func(range.front())); \n\
|
||||
range.pop_front(); \n\
|
||||
} \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\
|
||||
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\
|
||||
var retval = initial; \n\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval = (func(range.front(), retval)); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns the sum of the elements of the given value\n\
|
||||
def sum(container) { foldl(container, `+`, 0.0) } \n\
|
||||
# Returns the product of the elements of the given value\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\
|
||||
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\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def take(container, num, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements taken from the container\n\
|
||||
def take(container, num) {\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\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty()) && f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements match the second value function\n\
|
||||
def take_while(container, f) {\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\
|
||||
var r = range(container); \n\
|
||||
var i = num; \n\
|
||||
while ((i > 0) && (!r.empty())) { \n\
|
||||
r.pop_front(); \n\
|
||||
--i; \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given number of elements dropped from the given container \n\
|
||||
def drop(container, num) {\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\
|
||||
var r = range(container); \n\
|
||||
while ((!r.empty())&& f(r.front())) { \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
while (!r.empty()) { \n\
|
||||
inserter(r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new container with the given elements dropped that match the second value function\n\
|
||||
def drop_while(container, f) {\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\
|
||||
var r = range(container); \n\
|
||||
var retval = r.front(); \n\
|
||||
r.pop_front(); \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
while (!r.empty()) { \n\
|
||||
retval = func(retval, r.front()); \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
# Returns a string of the elements in container delimited by the second value string\n\
|
||||
def join(container, delim) { \n\
|
||||
var retval = ""; \n\
|
||||
var range = range(container); \n\
|
||||
if (!range.empty()) { \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
while (!range.empty()) { \n\
|
||||
retval += delim; \n\
|
||||
retval += to_string(range.front()); \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
retval; \n\
|
||||
} \n\
|
||||
def filter(container, f, inserter) : call_exists(range, container) { \n\
|
||||
var r = range(container); \n\
|
||||
while (!r.empty()) { \n\
|
||||
if (f(r.front())) { \n\
|
||||
inserter(r.front()); \n\
|
||||
} \n\
|
||||
r.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
# Returns a new Vector which match the second value function\n\
|
||||
def filter(container, f) { \n\
|
||||
var retval = new(container); \n\
|
||||
filter(container, f, back_inserter(retval));\n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
def generate_range(x, y, inserter) { \n\
|
||||
var i = x; \n\
|
||||
while (i <= y) { \n\
|
||||
inserter(i); \n\
|
||||
++i; \n\
|
||||
} \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\
|
||||
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\
|
||||
[x, y]; \n\
|
||||
} \n\
|
||||
def zip_with(f, x, y, inserter) : call_exists(range, x) && call_exists(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\
|
||||
r_y.pop_front(); \n\
|
||||
} \n\
|
||||
} \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\
|
||||
var retval = Vector(); \n\
|
||||
zip_with(f,x,y,back_inserter(retval)); \n\
|
||||
retval;\n\
|
||||
}\n\
|
||||
# Returns a new Vector which joins matching elements of the first and second\n\
|
||||
def zip(x, y) { \n\
|
||||
zip_with(collate, x, y); \n\
|
||||
}\n\
|
||||
# Returns the position of the second value string in the first value string\n\
|
||||
def string::find(substr) : is_type(substr, "string") { \n\
|
||||
int(find(this, substr, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of last match of the second value string in the first value string\n\
|
||||
def string::rfind(substr) : is_type(substr, "string") { \n\
|
||||
int(rfind(this, substr, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first match of elements in the second value string in the first value string\n\
|
||||
def string::find_first_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last match of elements in the second value string in the first value string\n\
|
||||
def string::find_last_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
# Returns the position of the first non-matching element in the second value string in the first value string\n\
|
||||
def string::find_first_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_first_not_of(this, list, 0)); \n\
|
||||
} \n\
|
||||
# Returns the position of the last non-matching element in the second value string in the first value string\n\
|
||||
def string::find_last_not_of(list) : is_type(list, "string") { \n\
|
||||
int(find_last_not_of(this, list, -1)); \n\
|
||||
} \n\
|
||||
def string::ltrim() { \n\
|
||||
drop_while(this, fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'}); \n\
|
||||
} \n\
|
||||
def string::rtrim() { \n\
|
||||
reverse(drop_while(reverse(this), fun(x) { x == ' ' || x == '\t' || x == '\r' || x == '\n'})); \n\
|
||||
} \n\
|
||||
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\
|
||||
var range = range(container); \n\
|
||||
while (!range.empty()) { \n\
|
||||
if (compare_func(range.front(), value)) { \n\
|
||||
return range; \n\
|
||||
} else { \n\
|
||||
range.pop_front(); \n\
|
||||
} \n\
|
||||
} \n\
|
||||
return range; \n\
|
||||
} \n\
|
||||
def find(container, value) { return find(container, value, eq) } \
|
||||
)
|
||||
#endif /* CHAISCRIPT_PRELUDE_HPP_ */
|
@@ -8,90 +8,33 @@
|
||||
#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
|
||||
{
|
||||
inline std::string class_name_translator(const std::string &t_name)
|
||||
{
|
||||
size_t colon = t_name.rfind("::");
|
||||
if (colon != std::string::npos)
|
||||
|
||||
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)
|
||||
{
|
||||
return t_name.substr(colon+2, std::string::npos);
|
||||
} else {
|
||||
return t_name;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
113
readme.md
Normal file
113
readme.md
Normal file
@@ -0,0 +1,113 @@
|
||||
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). MacOS
|
||||
10.8 (Mountain Lion) is also known to support the C++11 build with Apple's
|
||||
clang 4.0.
|
||||
|
||||
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`
|
||||
* The default behavior is to load the ChaiScript standard library from a
|
||||
loadable module. A second option is to compile the library into your code,
|
||||
see below for an example.
|
||||
|
||||
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);");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Or, if you want to compile the std lib into your code, which reduces
|
||||
runtime requirements.
|
||||
|
||||
/// main.cpp
|
||||
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
double function(int i, double j)
|
||||
{
|
||||
return i * j;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
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 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.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,3 +1,12 @@
|
||||
Changes since 5.0.0
|
||||
* 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 4.0.0
|
||||
* Dropped boost in favor of C++11
|
||||
* Separated out stdlib to make more options for compile time improvements
|
||||
|
||||
Changes since 3.1.0
|
||||
* svenstaro: Unused variables and CMake consistency fixes
|
||||
* Added support for returning pointers from functions (#13)
|
||||
|
@@ -7,19 +7,17 @@
|
||||
#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 << "[" << boost::posix_time::microsec_clock::local_time() << "] " << msg << std::endl;
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << boost::posix_time::microsec_clock::local_time() << "] <" << module << "> " << msg << std::endl;
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
@@ -40,7 +38,7 @@ void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
|
||||
struct System
|
||||
{
|
||||
std::map<std::string, boost::function<std::string (const std::string &) > > m_callbacks;
|
||||
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
|
||||
|
||||
void add_callback(const std::string &t_name,
|
||||
const chaiscript::Proxy_Function &t_func)
|
||||
@@ -52,7 +50,7 @@ struct System
|
||||
void do_callbacks(const std::string &inp)
|
||||
{
|
||||
log("Running Callbacks: " + inp);
|
||||
for (std::map<std::string, boost::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
|
||||
for (std::map<std::string, std::function<std::string (const std::string &)> >::iterator itr = m_callbacks.begin();
|
||||
itr != m_callbacks.end();
|
||||
++itr)
|
||||
{
|
||||
@@ -61,7 +59,7 @@ struct System
|
||||
}
|
||||
};
|
||||
|
||||
void take_shared_ptr(const boost::shared_ptr<const std::string> &p)
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
@@ -87,7 +85,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
|
||||
// boost::function, so it can be handled and called easily and type-safely
|
||||
// std::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
|
||||
@@ -108,14 +106,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 boost::function as a system function, in this
|
||||
//Finally, it is possible to register any std::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, boost::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks");
|
||||
|
||||
//Call bound version of do_callbacks
|
||||
chai("do_callbacks()");
|
||||
|
||||
boost::function<void ()> caller = chai.eval<boost::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
|
||||
std::function<void ()> caller = chai.eval<std::function<void ()> >("fun() { system.do_callbacks(\"From Functor\"); }");
|
||||
caller();
|
||||
|
||||
|
||||
@@ -139,11 +137,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<boost::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
int x = chai.eval<std::function<int (int, int)> >("fun (x, y) { return x + y; }")(5, 6);
|
||||
|
||||
log("Functor test output", boost::lexical_cast<std::string>(x));
|
||||
std::stringstream ss;
|
||||
ss << x;
|
||||
log("Functor test output", ss.str());
|
||||
|
||||
chai.add(var(boost::shared_ptr<int>()), "nullvar");
|
||||
chai.add(var(std::shared_ptr<int>()), "nullvar");
|
||||
chai("print(\"This should be true.\"); print(nullvar.is_var_null())");
|
||||
|
||||
// test the global const action
|
||||
@@ -165,7 +165,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(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, "TestType", "attr", _1))), "attr");
|
||||
// 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.eval("var x = TestType()");
|
||||
// chai.eval("x.attr = \"hi\"");
|
||||
|
@@ -1,13 +1,14 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "chaiscript/chaiscript.hpp"
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace chaiscript;
|
||||
|
||||
std::string get_next_command() {
|
||||
#ifdef READLINE_AVAILABLE
|
||||
@@ -30,30 +31,32 @@ void fuction(void)
|
||||
|
||||
class test
|
||||
{
|
||||
ChaiScript chai;
|
||||
ChaiScript::State backupState;
|
||||
chaiscript::ChaiScript chai;
|
||||
chaiscript::ChaiScript::State backupState;
|
||||
|
||||
public:
|
||||
test()
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
~test(){}
|
||||
|
||||
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);
|
||||
test()
|
||||
: chai(chaiscript::Std_Lib::library())
|
||||
{
|
||||
backupState = chai.get_state();
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
~test(){}
|
||||
|
||||
void ResetState()
|
||||
{
|
||||
chai.set_state(backupState);
|
||||
chai.add(chaiscript::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
21
src/chaiscript_stdlib.cpp
Normal file
21
src/chaiscript_stdlib.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
#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
|
43
src/main.cpp
43
src/main.cpp
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <regex>
|
||||
|
||||
#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 BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_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 boost::function<void ()> &f)
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
@@ -63,7 +63,7 @@ bool throws_exception(const boost::function<void ()> &f)
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void ()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
@@ -80,7 +80,21 @@ std::string get_next_command() {
|
||||
char *input_raw = readline("eval> ");
|
||||
if ( input_raw ) {
|
||||
add_history(input_raw);
|
||||
retval = boost::trim_copy_if(std::string(input_raw),boost::is_any_of(" \t"));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +127,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<boost::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
@@ -138,7 +152,7 @@ int main(int argc, char *argv[])
|
||||
std::vector<std::string> modulepaths;
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
@@ -146,7 +160,7 @@ int main(int argc, char *argv[])
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -219,18 +233,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,40 +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 <boost/thread.hpp>
|
||||
|
||||
void do_work(chaiscript::ChaiScript &c)
|
||||
{
|
||||
// c("use(\"work.chai\"); do_chai_work(num_iterations);");
|
||||
std::string name = "MyVar" + boost::lexical_cast<std::string>(rand());
|
||||
c.add(chaiscript::var(5), name);
|
||||
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<boost::shared_ptr<boost::thread> > threads;
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads.push_back(boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(do_work, boost::ref(chai)))));
|
||||
}
|
||||
|
||||
for (int i = 0; i < argc - 1; ++i)
|
||||
{
|
||||
threads[i]->join();
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
|
||||
#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 BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -14,11 +16,11 @@
|
||||
|
||||
bool has_parse_tree(const chaiscript::Const_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);
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
return pf->get_parse_tree();
|
||||
return bool(pf->get_parse_tree());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -26,8 +28,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)
|
||||
{
|
||||
boost::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= boost::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_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);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
@@ -51,46 +53,52 @@ 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<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
|
||||
|
||||
CHAISCRIPT_CLASS_NO_CONSTRUCTOR( m,
|
||||
chaiscript::exception::eval_error,
|
||||
((reason))
|
||||
((call_stack))
|
||||
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( m,
|
||||
chaiscript::File_Position,
|
||||
(chaiscript::File_Position())
|
||||
(chaiscript::File_Position(int,int)),
|
||||
((line))
|
||||
((column))
|
||||
);
|
||||
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_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 BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
@@ -1,11 +1,12 @@
|
||||
|
||||
#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 BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -16,6 +17,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extr
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_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 BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4190)
|
||||
#endif
|
||||
@@ -82,6 +82,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifdef CHAISCRIPT_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);
|
||||
}
|
2
unittests/3.x/assign_const.chai
Normal file
2
unittests/3.x/assign_const.chai
Normal file
@@ -0,0 +1,2 @@
|
||||
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 } );
|
2
unittests/3.x/bind.chai
Normal file
2
unittests/3.x/bind.chai
Normal file
@@ -0,0 +1,2 @@
|
||||
var prod = bind(foldl, _, `*`, 1.0)
|
||||
assert_equal(60, prod([3, 4, 5]))
|
34
unittests/3.x/bind2.chai
Normal file
34
unittests/3.x/bind2.chai
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
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
unittests/3.x/block_start.chai
Normal file
1
unittests/3.x/block_start.chai
Normal file
@@ -0,0 +1 @@
|
||||
{print("hello")}
|
1
unittests/3.x/bool_not.chai
Normal file
1
unittests/3.x/bool_not.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(false, !true)
|
7
unittests/3.x/break_while.chai
Normal file
7
unittests/3.x/break_while.chai
Normal file
@@ -0,0 +1,7 @@
|
||||
var i = 0
|
||||
while (i < 10) {
|
||||
if (++i == 5) {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert_equal(5, i);
|
1
unittests/3.x/char_init.chai
Normal file
1
unittests/3.x/char_init.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal("b", to_string('b'))
|
7
unittests/3.x/classification.chai
Normal file
7
unittests/3.x/classification.chai
Normal file
@@ -0,0 +1,7 @@
|
||||
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());
|
3
unittests/3.x/collate.chai
Normal file
3
unittests/3.x/collate.chai
Normal file
@@ -0,0 +1,3 @@
|
||||
var v = collate(1, 2)
|
||||
assert_equal(1, v[0])
|
||||
assert_equal(2, v[1])
|
1
unittests/3.x/compare_gt.chai
Normal file
1
unittests/3.x/compare_gt.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(false, 1 > 2);
|
1
unittests/3.x/compare_lt.chai
Normal file
1
unittests/3.x/compare_lt.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(true, 1 < 2)
|
5
unittests/3.x/concat.chai
Normal file
5
unittests/3.x/concat.chai
Normal file
@@ -0,0 +1,5 @@
|
||||
var v = concat([1, 2], [3, 4]);
|
||||
|
||||
assert_equal(4, v.size());
|
||||
assert_equal(1, v[0]);
|
||||
assert_equal(4, v[3]);
|
4
unittests/3.x/const_range_test.chai
Normal file
4
unittests/3.x/const_range_test.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
//If the following succeeds, the test passes
|
||||
|
||||
|
||||
"Hello World".for_each(fun(x) { print(x) } )
|
1
unittests/3.x/convert_double_string.chai
Normal file
1
unittests/3.x/convert_double_string.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal("3.5bob", 3.5.to_string() + "bob");
|
1
unittests/3.x/convert_int_string.chai
Normal file
1
unittests/3.x/convert_int_string.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal("3bob", 3.to_string + "bob")
|
1
unittests/3.x/convert_string_double.chai
Normal file
1
unittests/3.x/convert_string_double.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(6.8, "3.5".to_double() + 3.3)
|
1
unittests/3.x/convert_string_int.chai
Normal file
1
unittests/3.x/convert_string_int.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(8, "4".to_int() + 4)
|
11
unittests/3.x/deep_array_lookup.chai
Normal file
11
unittests/3.x/deep_array_lookup.chai
Normal file
@@ -0,0 +1,11 @@
|
||||
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)
|
11
unittests/3.x/dispatch_functions.chai
Normal file
11
unittests/3.x/dispatch_functions.chai
Normal file
@@ -0,0 +1,11 @@
|
||||
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
unittests/3.x/drop.chai
Normal file
1
unittests/3.x/drop.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal([3,4], drop([1, 2, 3, 4], 2))
|
1
unittests/3.x/drop_while.chai
Normal file
1
unittests/3.x/drop_while.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal([2, 3], drop_while([1, 2, 3], odd))
|
0
unittests/3.x/empty.chai
Normal file
0
unittests/3.x/empty.chai
Normal file
4
unittests/3.x/equ_shortform.chai
Normal file
4
unittests/3.x/equ_shortform.chai
Normal file
@@ -0,0 +1,4 @@
|
||||
var x=.5
|
||||
assert_equal(.5, x)
|
||||
var y=-.5
|
||||
assert_equal(-.5, y)
|
1
unittests/3.x/eval.chai
Normal file
1
unittests/3.x/eval.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(7, eval("3 + 4"))
|
39
unittests/3.x/eval_error.chai
Normal file
39
unittests/3.x/eval_error.chai
Normal file
@@ -0,0 +1,39 @@
|
||||
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
unittests/3.x/even.chai
Normal file
1
unittests/3.x/even.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(true, even(4))
|
9
unittests/3.x/exception.chai
Normal file
9
unittests/3.x/exception.chai
Normal file
@@ -0,0 +1,9 @@
|
||||
var x = 1
|
||||
try {
|
||||
throw(x)
|
||||
x = 2
|
||||
}
|
||||
catch(e) {
|
||||
x = e + 3
|
||||
}
|
||||
assert_equal(4, x);
|
32
unittests/3.x/exception_finally.chai
Normal file
32
unittests/3.x/exception_finally.chai
Normal file
@@ -0,0 +1,32 @@
|
||||
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);
|
34
unittests/3.x/exception_guards.chai
Normal file
34
unittests/3.x/exception_guards.chai
Normal file
@@ -0,0 +1,34 @@
|
||||
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
unittests/3.x/filter.chai
Normal file
1
unittests/3.x/filter.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal([1,3], filter([1, 2, 3, 4], odd))
|
7
unittests/3.x/float.chai
Normal file
7
unittests/3.x/float.chai
Normal file
@@ -0,0 +1,7 @@
|
||||
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
unittests/3.x/foldl.chai
Normal file
1
unittests/3.x/foldl.chai
Normal file
@@ -0,0 +1 @@
|
||||
assert_equal(10, foldl([1, 2, 3, 4], `+`, 0))
|
7
unittests/3.x/for.chai
Normal file
7
unittests/3.x/for.chai
Normal file
@@ -0,0 +1,7 @@
|
||||
var ret = []
|
||||
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
ret.push_back(i);
|
||||
}
|
||||
|
||||
assert_equal([0,1,2,3,4], ret);
|
1
unittests/3.x/for_each.chai
Normal file
1
unittests/3.x/for_each.chai
Normal file
@@ -0,0 +1 @@
|
||||
for_each([1, 2, 3], print)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user